2015-01-16 3 views
0

Я хочу спросить, что кто-то из вас здесь знаком с этой функцией, как показано ниже в Interbench. Я хочу перенести это на платформу Windows, но продолжаю терпеть неудачу. Я могу получить только микросекундную точность, используя timeval вместо timespec. И в конце будет ошибка: деление на ноль и исключения нарушения доступаInterbench Benchmark Code

unsigned long get_usecs(struct timeval *myts) 
{ 
    if (clock_gettime(myts)) 
     terminal_error("clock_gettime"); 

    return (myts->tv_sec * 1000000 + myts->tv_usec); 
} 

void burn_loops(unsigned long loops) 
{ 
    unsigned long i; 

    /* 
    * We need some magic here to prevent the compiler from optimising 
    * this loop away. Otherwise trying to emulate a fixed cpu load 
    * with this loop will not work. 
    */ 

    for (i = 0; i < loops; i++) 
     _ReadWriteBarrier(); 
} 
void calibrate_loop() 
{ 
    unsigned long long start_time, loops_per_msec, run_time = 0; 
    unsigned long loops; 
    struct timeval myts; 

    loops_per_msec = 100000; 

redo: 
    /* Calibrate to within 1% accuracy */ 
    while (run_time > 1010000 || run_time < 990000) { 
     loops = loops_per_msec; 
     start_time = get_usecs(&myts); 
     burn_loops(loops); 
     run_time = get_usecs(&myts) - start_time; 
     loops_per_msec = (1000000 * loops_per_msec/run_time ? run_time : loops_per_msec); 
    } 

    /* Rechecking after a pause increases reproducibility */ 
    Sleep(1 * 1000); 
    loops = loops_per_msec; 
    start_time = get_usecs(&myts); 
    burn_loops(loops); 
    run_time = get_usecs(&myts) - start_time; 

    /* Tolerate 5% difference on checking */ 
    if (run_time > 1050000 || run_time < 950000) 
     goto redo; 

    loops_per_ms = loops_per_msec; 
} 
+0

Предоставленная функция в значительной степени зависит от функции 'get_usecs()' для вычисления времени, а также использует функции 'burn_loops()' и 'Sleep()' для некоторых своих действий. * Ни один из них не является стандартной функцией C или даже POSIX, поэтому вы не предоставили нам достаточно информации, чтобы сообщить соответствующий ответ. –

+0

@JohnBollinger, я добавил в нужные функции. – Davy

ответ

-1

Вам необходимо будет изменить этот код для окон. Чтобы получить синхронизацию миллисекунды на окнах, вам нужно объявить что-то вроде:

struct _timeb myTimeb; 

И затем использовать

_ftime(&myTimeb); 

Результаты в миллисекундах будет:

myTimeb.millitm 

Подробности на сайте MSDN с кодом Пример: http://msdn.microsoft.com/en-us/library/z54t9z5f.aspx

Я вижу, вы уже пытаетесь использовать MSDN Sleep() также. Надеюсь, вы портировали это право, поскольку в качестве аргумента требуется микросекунды, тогда как usleep() на стороне Unix taxse миллисекунды ... Я предполагаю, что у вас есть * 1000 в вызове, который будет использоваться для преобразования миллисекунд в микросекунды которая является ошибкой, которую я видел раньше.

Это не касается burn_loop()

+0

Вопрос гласит, что предоставленный код дает * только * микросекундную точность. Желательна большая точность (т. Е. Наносекунда), не менее (миллисекунда). Вы всегда можете просто обрезать/округлить до * уменьшить * точность. –

0

Единственной clock_gettime() функции Я знаю, это один указанный POSIX, и эта функция имеет другую подпись, чем тот, который вы используете. Он обеспечивает наносекундное разрешение (хотя вряд ли он обеспечит точность с одним наносекундом). Насколько мне известно, он недоступен в Windows. Ответ Microsoft на получение разницы во времени на наносекундах заключается в использовании его запаса "Query Performance Counter" (QPC) API. Однако поставьте это на минутку, потому что я подозреваю, что разрешение часов не является вашей реальной проблемой.

Предположим, что ваша функция get_usecs() успешно восстанавливает часы с разрешением в микросекунду и по меньшей мере (около) миллисекундной точности, как и кажется, ваш код выглядит немного странным. В частности, это задание ...

loops_per_msec = (1000000 * loops_per_msec/run_time 
     ? run_time 
     : loops_per_msec); 

... выглядит совсем не так, как это более очевидным, когда форматирование подчеркивает приоритет оператора, как указано выше (* и / имеют более высокий приоритет, чем ?:). Это даст вам ваше разделение на ноль, если вы не получите измеримое положительное время выполнения, иначе оно всегда даст вам то же самое значение loops_per_msec, с которого вы начали, либо run_time, последний из которых даже не имеет правильные единицы.

Я подозреваю, что намерение было что-то больше, как это ...

loops_per_msec = ((1000000 * loops_per_msec) 
     /(run_time ? run_time : loops_per_msec)); 

..., но все еще есть проблема: если петли 1000000 не достаточно, чтобы потреблять по крайней мере, одну микросекунду (как измерено) то вы попадете в бесконечный цикл, с loops_per_msec повторно установлен в 1000000.

Это будет менее восприимчиво к этой конкретной проблеме ...

loops_per_msec = ((1000000 * loops_per_msec)/(run_time ? run_time : 1)); 

...и это имеет для меня больше смысла, потому что если измеренное время работы составляет 0 микросекунд, то 1 микросекунда является лучшим отличным от нуля приближением к такому, чем любое другое возможное значение. Обратите внимание, что это увеличит ваш loops_per_msec довольно быстро (в миллион раз), когда измеренное время работы равно нулю в микросекундах. Вы не можете делать это много раз, не переполняясь, даже если unsigned long long окажется 128 бит, и если вы получите переполнение, вы перейдете в бесконечный цикл. С другой стороны, если это переполнение происходит, это указывает на абсурдно большое правильное значение для loops_per_msec, которое вы пытаетесь оценить.

И это приводит меня к выводу: я подозреваю, что ваша реальная проблема заключается в том, что ваши расчеты сроки неправильны или недействительными, либо потому, что get_usecs() не работает должным образом или потому что тело burn_loops() оптимизируется прочь (несмотря на ваши усилия по избегайте этого). Вам не нужна субмикросекундная точность для ваших измерений времени. Фактически, вам даже не нужна лучше, чем миллисекундная точность, если ваш burn_loop() действительно работает пропорционально значению его аргумента.