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

голоса
82

Я портировании игры, который был первоначально написан для 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, однако.

Задан 01/08/2008 в 15:36
источник пользователем
На других языках...                            


10 ответов

голоса
4

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

Ответил 01/08/2008 в 15:46
источник пользователем

голоса
54

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

Вы должны смотреть clock_gettime(CLOCK_MONOTONIC)на временные интервалы. Она страдает от нескольких менее вопросов из - за таких вещей , как многоядерные системы и настройки внешнего тактового сигнала.

Кроме того , посмотрите в clock_getres()функцию.

Ответил 01/08/2008 в 15:53
источник пользователем

голоса
8

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

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

Ответил 01/08/2008 в 15:55
источник пользователем

голоса
39

Высокое разрешение, низкие накладные расходы Timing для процессоров Intel

Если вы на аппаратной 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);
}
Ответил 02/08/2008 в 09:08
источник пользователем

голоса
9

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

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

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

Ответил 02/08/2008 в 18:57
источник пользователем

голоса
18

@Bernard:

Я должен признать, большинство из вашего примера пошел прямо над моей головой. Это делает компиляции, и, кажется, работает, хотя. Это безопасно для многопроцессорных систем или SpeedStep?

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

В общем, как это работает:

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

Специальные примечания:

  • вне порядка исполнения может привести к неверным результатам, поэтому мы выполняем «CPUID» инструкцию, которая в дополнении к давая вам некоторую информацию о процессоре также синхронизирует выполнение команды испорченной.

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

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

  • относительно SpeedStep: Новые процессоры Intel компенсировать изменения скорости и возвращает скорректированное количество. Я сделал быстрое сканирование над некоторыми из коробок в нашей сети и нашел только один ящик, который не имел это: Pentium 3 работают некоторые старый сервер базы данных. (Это Linux коробки, так что я проверил с: Grep constant_tsc / Proc / CPUInfo)

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

Надеюсь, что это удовлетворяет ваше любопытство, это интересная и (ИМХО) в изученной области программирования. Вы знаете, когда Джефф и Джоэл говорили о том, должен ли программист знать C? Я кричал на них, «Эй забывать, что высокий уровень C материал ... ассемблер то, что вы должны знать, если вы хотите знать, что делает компьютер!»

Ответил 04/08/2008 в 01:51
источник пользователем

голоса
11

Вино на самом деле использует 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

Ответил 04/08/2008 в 15:44
источник пользователем

голоса
3

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

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

Ответил 18/08/2008 в 16:40
источник пользователем

голоса
14

Вы можете быть заинтересованы в Linux FAQ дляclock_gettime(CLOCK_REALTIME)

Ответил 18/08/2008 в 16:51
источник пользователем

голоса
5

Этот ответ упоминает проблемы с часами корректируются. И ваши проблемы , гарантирующие клеща единиц и проблемы со временем корректируются, решаются в C ++ 11 с <chrono>библиотекой.

Часы std::chrono::steady_clockгарантированно не наладятся, и , кроме того , он будет продвигаться вперед с постоянной скоростью по отношению к реальному времени, так как технология SpeedStep не должен влиять на него.

Вы можете получить типизированные единица путем преобразования в одной из std::chrono::durationспециализаций, такие как std::chrono::microseconds. С помощью этого типа нет никакой двусмысленности единиц , используемых значение клеща. Однако, имейте в виду , что часы не обязательно иметь это разрешение. Вы можете преобразовать длительность в аттосекунды, фактически не имея часы , которые точно.

Ответил 26/06/2012 в 16:57
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more