与std::chrono::system_clock/std::chrono::high_resolution_cloc

time differences with std::chrono::system_clock / std::chrono::high_resolution_clock

本文关键字:std chrono resolution cloc high clock system      更新时间:2023-10-16

考虑以下代码

#include <chrono>
#include <iostream>
#include <thread>
int main()
{
using std::chrono::system_clock;
using std::chrono::milliseconds;
using std::chrono::nanoseconds;
using std::chrono::duration_cast;
const auto duration = milliseconds(100);
const auto start = system_clock::now();
std::this_thread::sleep_for(duration);
const auto stop = system_clock::now();
const auto d_correct = duration_cast<nanoseconds>(duration).count();
const auto d_actual = duration_cast<nanoseconds>(stop - start).count();
std::cout << "Difference is " << d_actual << ", and it should be roughly " << d_correct << "n";
}

我们所期待的是

差值为100039989,应该大约为100000000

看看这个演示,它的工作原理非常好。

然而,在我的机器上,安装了几个编译器,根据Stack Overflow上的这个答案,这些编译器似乎会导致配置错误。

因此,我尝试了建议的修复方法:设置正确的LD_LIBRARY_PATH。这些是我尝试过的输出组合(其中包括4.4和4.6…)

g++-4.7 time.cpp -pthread -std=c++11; LD_LIBRARY_PATH=/usr/lib/gcc/i686-linux-gnu/4.7/ ./a.out

差值为100126,应该大约为100000000

g++-4.7 time.cpp -pthread -std=c++11; LD_LIBRARY_PATH=/usr/lib/gcc/i686-linux-gnu/4.8/ ./a.out

差值为100132,应该大约为100000000

g++-4.8 time.cpp -pthread -std=c++11; LD_LIBRARY_PATH=/usr/lib/gcc/i686-linux-gnu/4.7/ ./a.out

差值为100085953,应该大约为100000000

g++-4.8 time.cpp -pthread -std=c++11; LD_LIBRARY_PATH=/usr/lib/gcc/i686-linux-gnu/4.8/ ./a.out

差值为100156418,应该大约为100000000

不管怎样,使用g++-4.8编译都可以使用任何libstdc++,而使用g++-4.7编译则会导致崩溃。

我在编译器/二进制调用中做错了什么吗?还是g++-4.7中的错误?(具体为g++-4.7.3g++-4.8.1)

对于(可能是最丑陋的)变通方法,我当然可以测量一小段时间,将其与预期差异进行比较,然后得出一个因素。然而,我非常想优雅地解决这个问题。

我不能发表评论,但这似乎只是duration_cast的问题。。。我把你的睡眠时间提高到1000毫秒,并与时间效用进行了比较。事实上,它确实会睡1秒。

#include <chrono>
#include <iostream>
#include <thread>
int main()
{
using std::chrono::system_clock;
using std::chrono::milliseconds;
using std::chrono::nanoseconds;
using std::chrono::duration_cast;
const auto duration = milliseconds(1000);
const auto start = system_clock::now();
std::this_thread::sleep_for(duration);
const auto stop = system_clock::now();
const auto d_correct = duration_cast<nanoseconds>(duration).count();
const auto d_actual = duration_cast<nanoseconds>(stop - start).count();
std::cout << "Difference is " << d_actual << ", and it should be roughly " << d_correct << "n";
}

使用时间实用程序运行:

g++-4.7 time.cpp -pthread -std=c++11; time LD_LIBRARY_PATH=/usr/lib/gcc/i686-linux-gnu/4.7/ ./a.out
Difference is 1000193, and it should be roughly 1000000000
real    0m1.004s
user    0m0.000s
sys     0m0.000s

因此,事实上,这看起来确实是ABI的一个问题。我的系统也和你的系统一样愚蠢,使用更新版本的libstdc++。我们可以用ldd和/或LD_DEBUG=files:来确认这一点

ldd a.out 
linux-vdso.so.1 =>  (0x00007fff139fe000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ff0595b7000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ff0593a1000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff059183000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff058dba000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ff058ab5000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff0598e6000)

确凿的证据!这绝对不是正确的libstdc++。。。我所做的一切都无法阻止它!

我的下一个实验是尝试与静态libstdc++链接(http://www.trilithium.com/johan/2005/06/static-libstdc/):

ln -s `g++-4.7 -print-file-name=libstdc++.a`
g++-4.7 -static-libgcc -L. time.cpp -pthread -std=c++11; time ./a.out
Difference is 1000141417, and it should be roughly 1000000000
real    0m1.003s
user    0m0.004s
sys     0m0.000s

一切都好了!所以,总的来说,你是安全的。GCC 4.7本质上没有什么问题(呵呵…),但这是一个多么糟糕的问题!

try显式使用duration_cast(system_time::now()-start).count()

很多时候,根据编译器版本来区分代码是不可避免的。我建议不要在运行时解决4.7和4.8之间的差异(您提到的"丑陋"解决方案)。请改为在编译时中执行。

#if __GNUC__ == 4 && __GNUC_MINOR__ > 7
// your gcc 4.8 and above code here
#else
// your gcc 4.7.x and below code here
#endif