Временные различия с 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";
}
Что мы ожидаем, это что-то в строке
Разница составляет 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
? (It g++-4.7.3
и g++-4.8.1
, чтобы быть конкретным)
Для (вероятно, самого безобразного) обходного пути я могу, конечно, измерить в течение крошечного времени, сравнить его с ожидаемой разницей и придумать фактор. Однако я бы очень хотел, чтобы это было изящно.
Ответы
Ответ 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";
}
Запустите его с помощью утилиты 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. И моя система так же глупо об использовании более новой версии libstdС++ в качестве вашей системы. Мы можем подтвердить это с помощью 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)
КУРИТЬ! Это определенно не является правильным libstdС++... И ничто из этого не могло остановить его!
Мой следующий эксперимент состоял в попытке установить связь со статическим libstdС++ (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()
Ответ 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