gpt4 book ai didi

java - JVM 和 C++ 之间纳秒级精度的差异

转载 作者:行者123 更新时间:2023-11-28 04:41:41 24 4
gpt4 key购买 nike

当使用 System.nanoTime() 在 JVM 上测量时间时,您可以获得比使用 std::chrono::high_resolution_clock 更高的精度。这怎么可能,是否有一种跨平台的方法可以在 C++ 中获得与在 JVM 上相同的精度。

例子:

Kotlin (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()
}

输出:平均分辨率:433.37ns

C++:

#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;
}

输出:平均分辨率:15625657.89ns 编辑:(MinGW g++)编辑:输出:平均分辨率:444.88ns (MSVC)

这是在 Windows 上完成的,但在 Linux 上我得到了类似的结果。

编辑:

好吧,原来的 C++ 是用 MinGW 和 g++ 计算的,在切换到 MSVC 后我得到了与 JVM (444.88ns) 相当的结果。

最佳答案

您的 Java (Kotlin) 示例未测量纳秒粒度;它主要测量垃圾收集 Long 对象列表所需的时间。 (或扩展堆,或分配对象和对象头 - 如果您只运行一次测试,它可能会尝试进行垃圾收集,但只要循环运行就不会成功)

Java 的内存分配速度非常快,通常比 C/C++ 的标准内存分配库更快。

对于 C++,纳秒时钟的感知精度中至少有很大一部分可能来自对 vector 调用 push_back 1000 万次,这涉及大量重新分配。

更好的测试是(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-200ns 好得多。

至于你的 C++ 代码,你在我的 MacBookPro 上运行的原始代码给了我 68-78ns(当在循环中运行 10 次时)

我还从您的代码中删除了不必要的 vector ,然后它给出了 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();
}
}

关于java - JVM 和 C++ 之间纳秒级精度的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50064024/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com