【问题标题】:time differences with std::chrono::system_clock / std::chrono::high_resolution_clock与 std::chrono::system_clock / std::chrono::high_resolution_clock 的时差
【发布时间】:2014-03-23 03:13:39
【问题描述】:

考虑下面这段代码

#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左右

查看this demo,它工作得很好。

但是,根据this answer here on 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

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

【问题讨论】:

  • 如果有帮助,此页面提到 C++11 时钟 ABI 在 GCC 4.8.1 中发生了更改:gcc.gnu.org/gcc-4.8/changes.html
  • @JohnZwinck 这可能是相关的,但我不知道如何用 4.7 解决这种情况(我想要至少两个编译器版本用于我正在开发的产品。在工作中,只有我的开发机器有 4.8,所有其他机器运行
  • GCC 4.7 对 C++11 没有 100% 的工作支持,所以你可能在那里不走运,或者至少需要一些讨厌的解决方法。我不太确定,也无法从 GCC 网站找到更具体的问题报告。
  • @JohnZwinck 嗯,这是我正在开发的一个可选功能,所以如果这在 4.7 中无法修复,它已经过时了。但它是如此闪亮的功能(当然不是这里的演示代码;-))
  • 除了他们在 4.7 版本之后修复了一个错误之外,还有什么可行的结论吗?如果 4.7 曾经工作过,那么您安装的 stdlib 二进制文件和头文件之间不兼容。但这将是错误配置的一个例外情况。

标签: c++ c++11 g++ libstdc++ chrono


【解决方案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 本身并没有什么问题(呵呵……),但这是一个多么令人讨厌的问题!

【讨论】:

  • 终于有理智的回答了!谢谢你:)
  • 呸,呸!我也是第一个!
  • 我知道而且我必须说:遇到好的第一个答案真的很少见。请留在这个网站:)
【解决方案2】:

尝试明确使用 duration_cast(system_time::now() - start).count()

【讨论】:

  • 我想我的问题应该更准确。我进行了编辑以表明 duration_cast 不能解决问题。
  • 也许你的 g++4.7 的标题有问题?如果库头错误地定义了纳秒,就会导致这个问题。尝试不同版本的 g++4.7,或者您可以简单地查看头文件。
  • 纳秒的定义取决于ratio中的nano,并且对于我拥有的所有版本(4.4、4.6、4.7和4.8)都相同
【解决方案3】:

很多时候,根据编译器版本来区分代码是不可避免的。 我建议不要在运行时解决 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

【讨论】:

    猜你喜欢
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-14
    • 2013-12-05
    相关资源
    最近更新 更多