Я портирую игру, которая была первоначально записана для API Win32, к Linux (хорошо, портировав порт OS X порта Win32 к Linux).
Я реализовал QueryPerformanceCounter
путем предоставления uSeconds начиная с запуска процесса:
BOOL QueryPerformanceCounter(LARGE_INTEGER* performanceCount)
{
gettimeofday(¤tTimeVal, 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, как бы то ни было.
Возможно. Но у Вас есть большие проблемы. gettimeofday()
может привести к неправильным синхронизациям, если существуют процессы в Вашей системе, которые изменяют таймер (т.е., ntpd). На "нормальном" Linux, тем не менее, я полагаю, что разрешение gettimeofday()
10us. Это может перейти вперед и назад и время, следовательно, на основе процессов, работающих на Вашей системе. Это эффективно делает ответ на Ваш вопрос нет.
необходимо изучить clock_gettime(CLOCK_MONOTONIC)
для синхронизации интервалов. Это переносит от нескольких меньше проблем из-за вещей как многоядерные системы и настройки внешнего таймера.
кроме того, изучите эти clock_getres()
функция.
Высокое разрешение, Низко Служебная Синхронизация для 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);
}
Можно интересоваться FAQ Linux для clock_gettime(CLOCK_REALTIME)
@Bernard:
я должен признать, большая часть Вашего примера пошла прямо по моей голове. Это действительно компилирует и, кажется, работает, все же. Действительно ли это безопасно для систем SMP или SpeedStep?
Это - хороший вопрос... Я думаю код хорошо. С практической точки зрения мы используем его в моей компании каждый день, и мы работаем на довольно огромном количестве полей, всего от 2-8 ядер. Конечно, YMMV, и т.д., но это, кажется, надежное и низкие издержки (потому что это не превращает контекстное переключение в системное пространство), метод синхронизации.
Обычно то, как это работает:
Определенные примечания:
выполнение с изменением последовательности может вызвать неправильные результаты, таким образом, мы выполняем "cpuid" инструкцию, которая в дополнение к предоставлению Вам некоторая информация о CPU также синхронизирует любое неисправное выполнение инструкции.
Большая часть ОС синхронизирует счетчики на центральных процессорах, когда они запускают, таким образом, ответ хорош к в течение нескольких наносекунд.
бывший в спящем режиме комментарий, вероятно, верен, но на практике Вы, вероятно, не заботитесь о синхронизациях через границы спящего режима.
относительно speedstep: Более новый Intel CPUs компенсирует скорость, изменяет и возвращает скорректированное количество. Я сделал быстрое сканирование по некоторым полям в нашей сети и нашел только одно поле, которое не имело ее: Pentium 3, выполняющий некоторый старый сервер базы данных. (это поля Linux, таким образом, я сверился: grep constant_tsc/proc/cpuinfo)
я не уверен в центральных процессорах AMD, мы - прежде всего, магазин Intel, хотя я знаю, что некоторые наши системные гуру низкого уровня сделали оценку AMD.
Hope это удовлетворяет Ваше любопытство, это - интересное и (по моему скромному мнению) под - изученная область программирования. Вы знаете, когда Jeff и Joel говорили о том, должен ли программист знать C? Я кричал на них, "эй забудьте, что высокоуровневый C материал... ассемблер - то, что необходимо изучить, хотите ли Вы знать то, что делает компьютер!"
Вино на самом деле использует 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
, Таким образом, это говорит микросекунды явно, но говорит, разрешение системных часов является неуказанным. Я предполагаю разрешение в этом средстве контекста, как самая маленькая сумма это будет когда-либо увеличиваться?
структура данных определяется как наличие микросекунд как единица измерения, но это не означает, что часы или операционная система на самом деле способны к измерению настолько точно.
Как другие люди предложили, gettimeofday()
плохо, потому что установка времени может вызвать расфазировку тактовых сигналов и отбросить Ваше вычисление. clock_gettime(CLOCK_MONOTONIC)
то, что Вы хотите, и clock_getres()
скажет Вам точность Ваших часов.
фактическое разрешение gettimeofday () зависит от аппаратной архитектуры. Процессоры Intel, а также машины SPARC предлагают таймерам высокого разрешения ту меру микросекунды. Другие аппаратные архитектуры отступают к system’s таймеру, который обычно устанавливается на 100 Гц. В таких случаях разрешение времени будет менее точным.
я получил этот ответ от Измерение Времени Высокого разрешения и Таймеры, Первая часть
На основе моего опыта, и на основе того, что я считал через Интернет, ответ является "Нет", это не гарантируется. Это зависит от скорости ЦП, операционной системы, разновидности Linux, и т.д.
Чтение RDTSC не надежно в системах SMP, так как каждый ЦП поддерживает их собственный счетчик, и каждому счетчику не гарантируют синхронизируемым относительно другого ЦП.
я мог бы предложить пробовать clock_gettime(CLOCK_REALTIME)
. posix руководство указывает, что это должно быть реализовано во всех совместимых системах. Это может обеспечить количество наносекунды, но Вы, вероятно, захотите проверить clock_getres(CLOCK_REALTIME)
в Вашей системе для наблюдения, каково фактическое разрешение.