2014-02-21 10 views
12

Betrachten Sie das folgende Stück CodeZeitdifferenzen mit std :: Chrono :: System_Clock/std :: Chrono :: high_resolution_clock

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

Was wir erwarten, ist etwas auf der Linie der

Difference ist 100039989, und es sollte etwa 100000000 sein

Siehe this demo, wo es absolut gut funktioniert.

Allerdings sind auf meinem Rechner mehrere Compiler installiert, die nach this answer here on Stack Overflow eine Fehlkonfiguration zu verursachen scheinen.

Daher habe ich versucht, den vorgeschlagenen Fix: Einstellung der richtigen LD_LIBRARY_PATH. Dies sind die Kombinationen mit Ausgang Ich habe versucht (ua mit 4.4 und 4.6 ...)

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

Difference 100126, und es sollte in etwa 100000000

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

sein Der Unterschied ist 100132, und es sollte ungefähr 100000000 sein.

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

Unterschied ist 100.085.953, und es sollte in etwa 100000000

Es scheint sein sein grob 100000000

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

Unterschied ist 100.156.418, und es sollte, dass egal wie, Kompilieren mit g++-4.8 funktioniert gut mit einem der libstdc++, während die Kompilierung mit g++-4.7 führt zu einem gebrochenen sitzen .

Mache ich etwas falsch hier im Compiler/Binär-Aufruf oder ist es ein Fehler in g++-4.7? (Es ist g++-4.7.3 und g++-4.8.1 um genau zu sein)

Für (die wahrscheinlich hässlichste) Workaround, kann ich natürlich für eine winzige Zeit messen, vergleichen Sie es mit dem erwarteten Unterschied und kommen mit einem Faktor. Allerdings würde ich das gerne elegant lösen.

+0

Wenn es hilft, diese Seite erwähnt, dass die C++ 11 Uhr ABI in GCC 4.8.1 geändert: http://gcc.gnu.org/gcc-4.8/changes.html –

+0

@JohnZwinck Dies ist wahrscheinlich verwandt, aber ich sehe nicht, wie ich die Situation mit 4.7 beheben kann (Ich möchte mindestens zwei Compiler-Versionen für das Produkt, an dem ich arbeite. Bei der Arbeit hat nur mein Dev-Rechner 4.8, alle anderen laufen <= 4.7) – stefan

+0

GCC 4.7 hat keine 100% funktionierende Unterstützung für C++ 11, also * kann * kein Glück sein, oder zumindest einige fiese Workarounds benötigen. Ich bin mir nicht wirklich sicher, und war nicht in der Lage, einen spezifischeren Problembericht von der GCC-Seite auszugraben. –

Antwort

8

kann ich nicht kommentieren, aber es scheint nur ein Problem mit dem duration_cast zu sein ... Ich Schlaf bis 1000 ms gestoßen und lief gegen die Zeit-Dienstprogramm. Tatsächlich schläft es für 1 Sekunde.

#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 mit dem Dienstprogramm 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 

Also, ja, es sieht aus wie sicher ein Problem mit dem ABI. Und mein System ist genauso dumm, die neuere Version von libstdC++ als Ihr System zu benutzen. Wir können dies mit LDD und/oder LD_DEBUG = Dateien bestätigen:

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) 

SMOKING GUN! Das ist definitiv nicht das richtige libstdC++ ... Und nichts, was ich getan habe, könnte es stoppen!

Mein wurde als nächstes Experiment Verknüpfung mit statischen libstdc versuchen ++ (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 

GANZ BESSER! Also, insgesamt bist du sicher. Mit GCC 4.7 (heh ...) ist nichts falsch, aber was für ein ekliges Problem!

+1

Endlich eine vernünftige Antwort! Danke :) – stefan

+1

D'aw, shucks! Mein erster auch! – ftwl

+2

Ich weiß und ich muss sagen: Es ist wirklich selten, eine gute erste Antwort zu finden. Bitte bleib auf dieser Seite :) – stefan

0

ausdrücklich duration_cast (system_time :: now() - Start) verwenden versuchen .count()

+0

Ich denke, ich hätte in meiner Frage präziser sein sollen. Ich habe bearbeitet, um zu zeigen, dass duration_cast das Problem nicht löst. – stefan

+0

vielleicht stimmt etwas in Ihrem g ++ 4.7 Header nicht? Wenn Bibliotheksheader Nanosekunden falsch definiert, wird dieses Problem verursacht. versuchen Sie eine andere Version von g ++ 4.7 oder Sie können einfach in Header-Dateien suchen. – wacky6

+0

Die Definition von Nanosekunden hängt von 'nano' in' ratio' ab und ist für alle Versionen die ich habe (4.4, 4.6, 4.7 und 4.8) – stefan

0

Viele Male ist es unvermeidbar ist Code gemäß der Compiler-Version zu unterscheiden. Ich würde vorschlagen, nicht die Unterscheidung zwischen 4.7 und 4.8 während der Laufzeit zu lösen (die 'hässliche' Lösung, die Sie erwähnten). Tun Sie es in Kompilierzeit stattdessen.

#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 
Verwandte Themen