EDIT: Я только что нашел свою проблему после написания этого длинного сообщения, объясняющего каждую мелочь... Если кто-то может дать мне хороший ответ о том, что я делаю неправильно, и как я могу получить время выполнения в секунд (используя число с плавающей запятой с 5 знаками после запятой или около того), я отмечу это как принятое. Подсказка: проблема заключалась в том, как я интерпретировал man-страницу clock_getttime().
Hi,
Допустим, у меня есть функция с именем myOperation
, для которой мне нужно измерить время выполнения. Чтобы измерить это, я использую clock_gettime()
, как было рекомендовано >здесь в одном из комментариев.
Мой учитель рекомендует нам измерить его N
раза, чтобы мы могли получить среднее значение, стандартное отклонение и медиану для итогового отчета. Он также рекомендует нам выполнить myOperation
M
раз вместо одного. Если myOperation
— очень быстрая операция, измерение ее M
раз позволит нам получить представление о «реальном времени», которое она занимает; потому что используемые часы могут не иметь требуемой точности для измерения такой операции. Таким образом, выполнение myOperation
только один раз или M
раз действительно зависит от того, занимает ли сама операция достаточно времени для используемой нами точности часов.
У меня проблемы с выполнением M
раз. Увеличение M
уменьшает (намного) конечное среднее значение. Что не имеет для меня смысла. Это примерно так, в среднем вам требуется от 3 до 5 секунд, чтобы добраться из точки А в Б. Но затем вы идете из А в Б и обратно в А 5 раз (что составляет 10 раз, потому что из А в Б это то же самое, что и Б). к А), и вы измеряете это. Чем вы делите на 10, среднее значение, которое вы получаете, должно быть таким же средним, которое вы берете, путешествуя из точки А в Б, что составляет от 3 до 5 секунд.
Это то, что я хочу, чтобы мой код делал, но он не работает. Если я буду продолжать увеличивать количество раз, когда я иду из А в Б и обратно А, среднее значение будет с каждым разом все ниже и ниже, для меня это не имеет смысла.
Достаточно теории, вот мой код:
#include <stdio.h>
#include <time.h>
#define MEASUREMENTS 1
#define OPERATIONS 1
typedef struct timespec TimeClock;
TimeClock diffTimeClock(TimeClock start, TimeClock end) {
TimeClock aux;
if((end.tv_nsec - start.tv_nsec) < 0) {
aux.tv_sec = end.tv_sec - start.tv_sec - 1;
aux.tv_nsec = 1E9 + end.tv_nsec - start.tv_nsec;
} else {
aux.tv_sec = end.tv_sec - start.tv_sec;
aux.tv_nsec = end.tv_nsec - start.tv_nsec;
}
return aux;
}
int main(void) {
TimeClock sTime, eTime, dTime;
int i, j;
for(i = 0; i < MEASUREMENTS; i++) {
printf(" » MEASURE %02d\n", i+1);
clock_gettime(CLOCK_REALTIME, &sTime);
for(j = 0; j < OPERATIONS; j++) {
myOperation();
}
clock_gettime(CLOCK_REALTIME, &eTime);
dTime = diffTimeClock(sTime, eTime);
printf(" - NSEC (TOTAL): %ld\n", dTime.tv_nsec);
printf(" - NSEC (OP): %ld\n\n", dTime.tv_nsec / OPERATIONS);
}
return 0;
}
Примечания. Приведенная выше функция diffTimeClock
взята из этого запись в блоге. Я заменил свою реальную операцию на myOperation()
, потому что нет никакого смысла публиковать мои настоящие функции, так как мне пришлось бы публиковать длинные блоки кода, вы можете легко закодировать myOperation()
с чем угодно, чтобы скомпилировать код, если хотите.
Как видите, OPERATIONS = 1
и результаты такие:
» MEASURE 01
- NSEC (TOTAL): 27456580
- NSEC (OP): 27456580
Для OPERATIONS = 100
результаты следующие:
» MEASURE 01
- NSEC (TOTAL): 218929736
- NSEC (OP): 2189297
Для OPERATIONS = 1000
результаты следующие:
» MEASURE 01
- NSEC (TOTAL): 862834890
- NSEC (OP): 862834
Для OPERATIONS = 10000
результаты таковы:
» MEASURE 01
- NSEC (TOTAL): 574133641
- NSEC (OP): 57413
Я не гений математики, на самом деле это далеко не так, но для меня это не имеет никакого смысла. Я уже говорил об этом с другом, который работает со мной над этим проектом, и он тоже не может понять различий. Я не понимаю, почему значение становится все ниже и ниже, когда я увеличиваю OPERATIONS
. Сама операция должна занимать одно и то же время (в среднем, конечно, не точно такое же время), независимо от того, сколько раз я ее выполняю.
Вы могли бы сказать мне, что это на самом деле зависит от самой операции, считываемых данных и что некоторые данные могут уже быть в кеше и бла-бла, но я не думаю, что проблема в этом. В моем случае myOperation
читает 5000 строк текста из CSV-файла, разделяет значения на ;
и вставляет эти значения в структуру данных. Для каждой итерации я разрушаю структуру данных и снова ее инициализирую.
Теперь, когда я думаю об этом, я также думаю, что есть проблема с измерением времени с помощью clock_gettime()
, возможно, я неправильно его использую. Я имею в виду, посмотрите на последний пример, где OPERATIONS = 10000
. Общее время, которое потребовалось, составило 574133641 нс, что составляет примерно 0,5 с; это невозможно, это заняло пару минут, так как я не выдержала, глядя в экран и пошла что-то есть.
CLOCK_MONOTONIC
, а неCLOCK_REALTIME
— последнее может измениться, если системное время изменится, первое не изменится. - person caf   schedule 13.05.2010ntpd
изменил его? (Или системный администратор в общей системе?) - person caf   schedule 13.05.2010clock_gettime()
, его даже не существует (во всяком случае, не на Mac моего друга). - person rfgamaral   schedule 13.05.2010