时间差与std :: chrono :: system_clock/std :: chrono :: high_resolution_clock

ste*_*fan 12 c++ g++ libstdc++ c++11 c++-chrono

考虑以下代码

#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";
}
Run Code Online (Sandbox Code Playgroud)

我们所期待的是一些东西

差异是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
Run Code Online (Sandbox Code Playgroud)

差异是100126,它应该是大约100000000

g++-4.7 time.cpp -pthread -std=c++11; LD_LIBRARY_PATH=/usr/lib/gcc/i686-linux-gnu/4.8/ ./a.out
Run Code Online (Sandbox Code Playgroud)

差异是100132,它应该大约是100000000

g++-4.8 time.cpp -pthread -std=c++11; LD_LIBRARY_PATH=/usr/lib/gcc/i686-linux-gnu/4.7/ ./a.out
Run Code Online (Sandbox Code Playgroud)

差异是100085953,它应该大约是100000000

g++-4.8 time.cpp -pthread -std=c++11; LD_LIBRARY_PATH=/usr/lib/gcc/i686-linux-gnu/4.8/ ./a.out
Run Code Online (Sandbox Code Playgroud)

差异是100156418,它应该大约是100000000

似乎无论如何,g++-4.8使用任何一个编译工作正常libstdc++,同时g++-4.7在破碎的情况下编译结果.

我在编译器/二进制调用中做错了什么,或者它是一个错误g++-4.7?(这是g++-4.7.3g++-4.8.1要具体)

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

小智 8

我无法发表评论,但似乎只有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";
}
Run Code Online (Sandbox Code Playgroud)

使用time实用程序运行它:

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
Run Code Online (Sandbox Code Playgroud)

所以,确实,它确实看起来像ABI的问题.我的系统与使用较新版本的libstdc ++作为您的系统一样愚蠢.我们可以用ldd和/或LD_DEBUG =文件确认这个:

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)
Run Code Online (Sandbox Code Playgroud)

吸烟枪!这绝对不是正确的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
Run Code Online (Sandbox Code Playgroud)

更好!所以,总的来说,你是安全的.GCC 4.7没有任何内在错误(嘿......),但这是一个令人讨厌的问题!

  • 我知道,我必须说:遇到一个好的第一个答案真的很少见.请留在这个网站:) (2认同)