gettimeofday (), гарантировал, что был разрешения микросекунды?

Я портирую игру, которая была первоначально записана для API Win32, к Linux (хорошо, портировав порт OS X порта Win32 к Linux).

Я реализовал QueryPerformanceCounter путем предоставления uSeconds начиная с запуска процесса:

BOOL QueryPerformanceCounter(LARGE_INTEGER* performanceCount)
{
    gettimeofday(&currentTimeVal, NULL);
    performanceCount->QuadPart = (currentTimeVal.tv_sec - startTimeVal.tv_sec);
    performanceCount->QuadPart *= (1000 * 1000);
    performanceCount->QuadPart += (currentTimeVal.tv_usec - startTimeVal.tv_usec);

    return true;
}

Это, вместе с QueryPerformanceFrequency() предоставление постоянных 1000000 как частота, работы хорошо над моей машиной, давая мне переменную на 64 бита, которая содержит uSeconds начиная с запуска программы.

Таким образом, действительно ли это портативно? Я не хочу обнаруживать, что это работает по-другому, если ядро было скомпилировано определенным способом или чем-нибудь как этот. Хорошо с ним являющийся непортативным к чему-то другому, чем Linux, как бы то ни было.

92
задан Rann Lifshitz 31 May 2018 в 01:36
поделиться

9 ответов

Возможно. Но у Вас есть большие проблемы. gettimeofday() может привести к неправильным синхронизациям, если существуют процессы в Вашей системе, которые изменяют таймер (т.е., ntpd). На "нормальном" Linux, тем не менее, я полагаю, что разрешение gettimeofday() 10us. Это может перейти вперед и назад и время, следовательно, на основе процессов, работающих на Вашей системе. Это эффективно делает ответ на Ваш вопрос нет.

необходимо изучить clock_gettime(CLOCK_MONOTONIC) для синхронизации интервалов. Это переносит от нескольких меньше проблем из-за вещей как многоядерные системы и настройки внешнего таймера.

кроме того, изучите эти clock_getres() функция.

55
ответ дан Paul Fleming 24 November 2019 в 06:31
поделиться

Высокое разрешение, Низко Служебная Синхронизация для Intel Processors

, Если Вы находитесь на аппаратных средствах Intel, вот то, как считать ЦП счетчик команд в реальном времени. Это скажет Вам количество циклов ЦП, выполняемых, так как процессор был загружен. Это - вероятно, счетчик с самыми прекрасными зернами, который можно получить для измерения производительности.

Примечание, что это - количество циклов ЦП. На Linux можно получить скорость ЦП от/proc/cpuinfo и разделиться для получения числа секунд. Преобразование этого к двойному довольно удобно.

, Когда я выполняю это на своем поле, я добираюсь

11867927879484732
11867927879692217
it took this long to call printf: 207485

, Вот Руководство разработчика Intel, которое дает тонны детали.

#include <stdio.h>
#include <stdint.h>

inline uint64_t rdtsc() {
    uint32_t lo, hi;
    __asm__ __volatile__ (
      "xorl %%eax, %%eax\n"
      "cpuid\n"
      "rdtsc\n"
      : "=a" (lo), "=d" (hi)
      :
      : "%ebx", "%ecx");
    return (uint64_t)hi << 32 | lo;
}

main()
{
    unsigned long long x;
    unsigned long long y;
    x = rdtsc();
    printf("%lld\n",x);
    y = rdtsc();
    printf("%lld\n",y);
    printf("it took this long to call printf: %lld\n",y-x);
}
40
ответ дан Evan Teran 24 November 2019 в 06:31
поделиться

Можно интересоваться FAQ Linux для clock_gettime(CLOCK_REALTIME)

14
ответ дан CesarB 24 November 2019 в 06:31
поделиться

@Bernard:

я должен признать, большая часть Вашего примера пошла прямо по моей голове. Это действительно компилирует и, кажется, работает, все же. Действительно ли это безопасно для систем SMP или SpeedStep?

Это - хороший вопрос... Я думаю код хорошо. С практической точки зрения мы используем его в моей компании каждый день, и мы работаем на довольно огромном количестве полей, всего от 2-8 ядер. Конечно, YMMV, и т.д., но это, кажется, надежное и низкие издержки (потому что это не превращает контекстное переключение в системное пространство), метод синхронизации.

Обычно то, как это работает:

  • объявляют, что блок кода ассемблер (и энергозависимый, таким образом, оптимизатор оставит его в покое).
  • выполняют инструкцию CPUID. В дополнение к получению некоторой информации ЦП (с которым мы ничего не делаем) это синхронизирует буфер выполнения ЦП так, чтобы синхронизации не были затронуты выполнением с изменением последовательности.
  • выполняют rdtsc (метка времени чтения) выполнение. Это выбирает количество циклов машины, выполняемых, так как процессор был сброшен. Это - 64-разрядное значение, таким образом, с текущими скоростями ЦП оно перенесет каждые 194 года или около этого. Интересно, в исходной ссылке Pentium, они отмечают, что она переносит каждые 5 800 лет или около этого.
  • последние строки хранят значения от регистров в переменные привет и lo, и помещают это в 64-разрядное возвращаемое значение.

Определенные примечания:

  • выполнение с изменением последовательности может вызвать неправильные результаты, таким образом, мы выполняем "cpuid" инструкцию, которая в дополнение к предоставлению Вам некоторая информация о CPU также синхронизирует любое неисправное выполнение инструкции.

  • Большая часть ОС синхронизирует счетчики на центральных процессорах, когда они запускают, таким образом, ответ хорош к в течение нескольких наносекунд.

  • бывший в спящем режиме комментарий, вероятно, верен, но на практике Вы, вероятно, не заботитесь о синхронизациях через границы спящего режима.

  • относительно speedstep: Более новый Intel CPUs компенсирует скорость, изменяет и возвращает скорректированное количество. Я сделал быстрое сканирование по некоторым полям в нашей сети и нашел только одно поле, которое не имело ее: Pentium 3, выполняющий некоторый старый сервер базы данных. (это поля Linux, таким образом, я сверился: grep constant_tsc/proc/cpuinfo)

  • я не уверен в центральных процессорах AMD, мы - прежде всего, магазин Intel, хотя я знаю, что некоторые наши системные гуру низкого уровня сделали оценку AMD.

Hope это удовлетворяет Ваше любопытство, это - интересное и (по моему скромному мнению) под - изученная область программирования. Вы знаете, когда Jeff и Joel говорили о том, должен ли программист знать C? Я кричал на них, "эй забудьте, что высокоуровневый C материал... ассемблер - то, что необходимо изучить, хотите ли Вы знать то, что делает компьютер!"

18
ответ дан Tony Delroy 24 November 2019 в 06:31
поделиться

Вино на самом деле использует gettimeofday () для реализации QueryPerformanceCounter (), и это, как известно, заставляет много игр Windows работать над Linux, и Mac

Запускается , http://source.winehq.org/source/dlls/kernel32/cpu.c#L312

приводит к http://source.winehq.org/source/dlls/ntdll/time.c#L448

11
ответ дан Vincent Robert 24 November 2019 в 06:31
поделиться

, Таким образом, это говорит микросекунды явно, но говорит, разрешение системных часов является неуказанным. Я предполагаю разрешение в этом средстве контекста, как самая маленькая сумма это будет когда-либо увеличиваться?

структура данных определяется как наличие микросекунд как единица измерения, но это не означает, что часы или операционная система на самом деле способны к измерению настолько точно.

Как другие люди предложили, gettimeofday() плохо, потому что установка времени может вызвать расфазировку тактовых сигналов и отбросить Ваше вычисление. clock_gettime(CLOCK_MONOTONIC) то, что Вы хотите, и clock_getres() скажет Вам точность Ваших часов.

9
ответ дан vitaut 24 November 2019 в 06:31
поделиться

фактическое разрешение gettimeofday () зависит от аппаратной архитектуры. Процессоры Intel, а также машины SPARC предлагают таймерам высокого разрешения ту меру микросекунды. Другие аппаратные архитектуры отступают к system’s таймеру, который обычно устанавливается на 100 Гц. В таких случаях разрешение времени будет менее точным.

я получил этот ответ от Измерение Времени Высокого разрешения и Таймеры, Первая часть

8
ответ дан Vineet Jain 24 November 2019 в 06:31
поделиться

На основе моего опыта, и на основе того, что я считал через Интернет, ответ является "Нет", это не гарантируется. Это зависит от скорости ЦП, операционной системы, разновидности Linux, и т.д.

4
ответ дан CodingWithoutComments 24 November 2019 в 06:31
поделиться

Чтение RDTSC не надежно в системах SMP, так как каждый ЦП поддерживает их собственный счетчик, и каждому счетчику не гарантируют синхронизируемым относительно другого ЦП.

я мог бы предложить пробовать clock_gettime(CLOCK_REALTIME) . posix руководство указывает, что это должно быть реализовано во всех совместимых системах. Это может обеспечить количество наносекунды, но Вы, вероятно, захотите проверить clock_getres(CLOCK_REALTIME) в Вашей системе для наблюдения, каково фактическое разрешение.

3
ответ дан CesarB 24 November 2019 в 06:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: