[英]Difference in nanosecond precision between JVM and C++
使用System.nanoTime()
在JVM上测量时间时,与使用std::chrono::high_resolution_clock
相比,您可以获得更高的精度。 在C ++中如何获得与JVM相同的精度,这将是一种跨平台的方式。
fun main(args: Array<String>) {
for (i in 0..10)
test() // warmup
println("Average resolution: ${test()}ns")
}
fun test(): Double {
val timeList = mutableListOf<Long>()
for (i in 0 until 10_000_000) {
val time = System.nanoTime()
if (timeList.isEmpty() || time != timeList.last())
timeList.add(time)
}
return timeList
.mapIndexed { i, l -> if (i > 0) l - timeList[i - 1] else null }
.filterNotNull()
.average()
}
输出: Average resolution: 433.37ns
#include <iostream>
#include <chrono>
#include <numeric>
#include <vector>
int main() {
using namespace std;
using namespace chrono;
vector<long long int> time_list;
for(int i = 0; i < 10'000'000; ++i) {
auto time = duration_cast<nanoseconds>(high_resolution_clock::now().time_since_epoch()).count();
if(time_list.empty() || time != time_list[time_list.size() - 1])
time_list.push_back(time);
}
adjacent_difference(time_list.begin(), time_list.end(), time_list.begin());
auto result = accumulate(time_list.begin() + 1, time_list.end(), 0.0) / (time_list.size() - 1);
printf("Average resolution: %.2fns", result);
return 0;
}
输出: Average resolution: 15625657.89ns
编辑:(MinGW g ++)编辑:输出: Average resolution: 444.88ns
(MSVC)
这是在Windows上完成的,但是在Linux上我得到了类似的结果。
好了,切换到MSVC之后,原始的C ++是用MinGW和g ++计算出来的,我得到了与JVM(444.88ns)相当的结果。
您的Java(Kotlin)示例未测量纳秒级粒度; 它主要用于测量垃圾收集Long对象列表所需的时间。 (或扩展堆,或分配对象和对象标头-如果仅运行一次测试,它可能会尝试进行垃圾回收,但只要循环正在运行,它就不会成功)
Java的内存分配非常快,通常比C / C ++的标准内存分配器库快。
对于C ++,纳秒时钟的感知精度中至少有很大一部分可能来自对向量的1000万次push_back
调用,这涉及许多重分配。
更好的测试是(Kotlin,但对于C ++也可以这样做)-无需记住列表中的时间戳以计算它们之间的平均差。
fun main(args: Array<String>) {
for (i in 0 until 10) {
runTest();
}
}
fun runTest() {
var lastTime = System.nanoTime()
var count = 0;
var total = 0L;
for (i in 0 until 50_000_000) {
val time = System.nanoTime()
if (time > lastTime) {
count++;
total += time - lastTime;
lastTime = time;
}
}
val result = total / count;
println("Average resolution: ${result}ns")
}
注意:这使我在Java中具有32-35ns的一致精度,比原始代码给我的45-200 ns好得多。
至于您的C ++代码,您在MacBookPro上运行的原始代码给了我68-78ns(在运行10次的循环中运行)
我还从代码中删除了不必要的向量,然后给出了50-51ns的结果,这很好地表明了实际粒度为50ns。
JVM的性能要比32-35ns(比50ns好38%)要好一些,但是裕度远没有您提到的那么大。
请重试,并使用不需要将结果存储在列表中的代码发布输出,因为这会极大地影响结果。
#include <iostream>
#include <chrono>
#include <numeric>
#include <vector>
int main1() {
using namespace std;
using namespace chrono;
vector<long long int> time_list;
long long total = 0;
int count = 0;
auto lastTime = duration_cast<nanoseconds>(high_resolution_clock::now().time_since_epoch()).count();
for(int i = 0; i < 50000000; ++i) {
auto time = duration_cast<nanoseconds>(high_resolution_clock::now().time_since_epoch()).count();
if (time > lastTime) {
count++;
total += time - lastTime;
lastTime = time;
}
}
long long result = total / count;
printf("Average resolution: %.2lld ns\n", result);
return 0;
}
int main() {
for (int i = 0; i < 10; i++) {
main1();
}
}
c ++中的分辨率取决于平台,但是使用平台特定的调用(例如,在Linux上,来自time.h
clock_gettime
)可能会提高准确性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.