Измерение коротких временных интервалов в C на Ubuntu / VMware - PullRequest
5 голосов
/ 29 января 2012

Я пытаюсь измерить короткие промежутки времени, порядка нескольких миллисекунд. Это оказывается нетривиальной задачей, поскольку вездесущая функция time() работает с точностью до целых секунд. После некоторого исследования я разработал четыре метода, показанных в примере кода ниже:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>

int main(int argc, char *argv[])
{
    clock_t t0, t1;
    double dt0;

    struct timespec t2, t3;
    double dt1;

    struct timespec t4, t5;
    double dt2;

    struct timeval t6, t7;
    double dt3;

    volatile long long i;

    t2.tv_sec = 0;
    t2.tv_nsec = 0;
    clock_settime(CLOCK_MONOTONIC, &t2);
    clock_settime(CLOCK_REALTIME,  &t2);

    t0 = clock();
    clock_gettime(CLOCK_REALTIME,  &t2);
    clock_gettime(CLOCK_MONOTONIC, &t4);
    gettimeofday(&t6, NULL);

    getchar();
    for (i=0; i<1e9; i++) {};

    gettimeofday(&t7, NULL);
    clock_gettime(CLOCK_MONOTONIC, &t5);
    clock_gettime(CLOCK_REALTIME,  &t3);
    t1 = clock();

    dt0 = (double) (t1 - t0) / CLOCKS_PER_SEC;
    dt1 = (double) (t3.tv_nsec - t2.tv_nsec) / 1e9;
    dt2 = (double) (t5.tv_nsec - t4.tv_nsec) / 1e9;
    dt3 = (double) (t7.tv_usec - t6.tv_usec) / 1e6;

    printf("1. clock():          [0]=%10.0f, [1]=%10.0f, [1-0]=%10.6f sec\n", (double) t0, (double) t1, dt0);
    printf("2. clock_gettime(R): [2]=%10ld, [3]=%10ld, [3-2]=%10f sec\n", (long) t2.tv_nsec, (long) t3.tv_nsec, dt1);
    printf("3. clock_gettime(M): [2]=%10ld, [3]=%10ld, [3-2]=%10f sec\n", (long) t4.tv_nsec, (long) t5.tv_nsec, dt2);
    printf("4. gettimeofday():   [4]=%10ld, [5]=%10ld, [5-4]=%10f sec\n", (long) t6.tv_usec, (long) t7.tv_usec, dt3);

    return 0;
}

Затем я скомпилировал и запустил его:

gcc -lrt -o timer.e timer.c; time ./timer.e

Я использовал вызов getchar(), чтобы ввести задержку в пару секунд, чтобы увидеть разницу между real и user отчетами о времени, и результат был:

1. clock():          [0]=         0, [1]=   3280000, [1-0]=  3.280000 sec
2. clock_gettime(R): [2]= 823922476, [3]= 478650549, [3-2]= -0.345272 sec
3. clock_gettime(M): [2]= 671137949, [3]= 325864897, [3-2]= -0.345273 sec
4. gettimeofday():   [4]=    823924, [5]=    478648, [5-4]= -0.345276 sec

real    0m6.659s
user    0m3.280s
sys     0m0.010s

Как видите, единственным значимым результатом является корреляция между методом 1 и временем user, сообщаемым командой time.

Это приносит пару вопросов: 1. Почему результаты 2-4 бессмысленны? 2. Как измерить реальное время, потраченное на запуск программы, например real число time отчетов?

Моя среда - Ubuntu 10.04 LTS 64-bit на VMware на Windows 7 на ноутбуке HP на базе AMD.

Ответы [ 3 ]

12 голосов
/ 29 января 2012

Вы на правильном пути с clock_gettime().

Однако вы должны избавиться от этих clock_settime() вызовов: просто позвоните clock_gettime() до и после блока кода и посмотрите на разницу.

Кроме того, при расчете разницы следует учитывать как tv_sec, так и tv_nsec; Ваш текущий код просто смотрит на наносекундный компонент и игнорирует полные секунды.

В моей системе Ubuntu следующий код дает довольно точное измерение времени, которое требуется для выполнения цикла:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>

int main(int argc, char *argv[])
{
    struct timespec t2, t3;
    double dt1;

    volatile long long i;

    clock_gettime(CLOCK_MONOTONIC,  &t2);
    for (i=0; i<1e9; i++) {};
    clock_gettime(CLOCK_MONOTONIC,  &t3);
    //time in seconds
    dt1 = (t3.tv_sec - t2.tv_sec) + (double) (t3.tv_nsec - t2.tv_nsec) * 1e-9;
    printf("%f\n", dt1);

    return 0;
}
1 голос
/ 29 января 2012

Ваши clock_settime звонки не соответствуют вашим ожиданиям.Если бы у вас было разрешение, они просто установили бы системные часы на 0, вероятно, не то, что вам нужно.Почти все функции POSIX имеют возвращаемое значение, которое сообщает вам, успешно ли выполнен вызов.Обычно это плохая идея игнорировать это значение.В частности, для вашего случая я думаю, что он должен был дать это значение, как это можно найти на странице man:

EPERM clock_settime () не имеет разрешения для установки указанных часов.1007 *

К счастью, у вас нет прав для установки часов так просто, как это:)

1 голос
/ 29 января 2012

Некоторый намек на измерение времени до микро и даже нано секунд http://en.wikipedia.org/wiki/Time_Stamp_Counter

...