12

次のコードを検討してください

#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 のはずです

完全に正常に動作するこのデモを参照してください。

ただし、私のマシンには、スタックオーバーフローのこの回答によると、構成不良を引き起こすと思われるコンパイラがいくつかインストールされています。

したがって、私は提案された修正を試みました: 正しい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具体的には)

(おそらく最も醜い) 回避策として、もちろん、ごくわずかな時間を測定し、それを予想される差と比較して、要因を考え出すことができます。しかし、私はこれをエレガントに解決したいと思っています。

4

3 に答える 3

8

コメントはできませんが、duration_cast のみに問題があるようです...スリープを 1000 ミリ秒まで上げて、time ユーティリティに対して実行しました。確かに、それは 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";
}

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

確かに、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 には本質的に問題はありませんが (へー...)、なんと厄介な問題なのでしょう!

于 2014-06-28T03:32:15.127 に答える
0

明示的に duration_cast(system_time::now() - start).count() を使用してみてください

于 2014-03-05T07:44:01.457 に答える