Проблема измерения N раз Время выполнения блока кода
-
26-09-2019 - |
Вопрос
РЕДАКТИРОВАТЬ: Я только что нашел свою проблему после написания этого долгая пост, объясняя каждую маленькую деталь ... Если кто-то может дать мне хороший ответ на то, что я делаю не так, и как я могу получить время исполнения в считанные секунды (используя поплавок с 5 десятичными периодами Или так), я отмечу это как принято. Подсказка: проблема была на том, как я интерпретировал страницу MACK_GETTTIME ().
Привет,
Допустим, у меня есть функция по имени myOperation
Что мне нужно для измерения времени выполнения. Измерить его, я использую clock_gettime()
Как это было рекомендовано здесь в одном из комментариев.
Мой учитель рекомендует нам измерить его N
Таким образом, мы можем получить среднее, стандартное отклонение и медиана для окончательного доклада. Он также рекомендует нам выполнить myOperation
M
раз вместо одного. Если myOperation
очень быстрая работа, измеряя его M
раз позволяют нам получить чувство «реального времени», которое требуется; Причина, поскольку используемые часы, не могут иметь необходимую точность для измерения такой операции. Итак, исполнение myOperation
только один раз или M
Времена действительно зависит, если сама операция принимает достаточно долго, для точной точности, мы используем.
У меня проблемы с этим заниматься M
время исполнения. Увеличение M
уменьшается (много) конечное среднее значение. Что не имеет смысла для меня. Это похоже на это, в среднем вы берете от 3 до 5 секунд, чтобы путешествовать от пункта A до B. Но затем вы идете от A до B и обратно в 5 раз (что делает его в 10 раз, потому что B - B - это так же, как B к а) и вы измеряете это. Чем вы разделяете на 10, среднее значение, которое вы получаете, одинаково, что вы можете путешествовать от точки A до B, что составляет от 3 до 5 секунд.
Это то, что я хочу, чтобы мой код сделать, но это не работает. Если я продолжаю увеличивать количество раз, когда я иду от до B и обратно, среднее значение будет ниже и снизить каждый раз, это не имеет смысла для меня.
Достаточно теории, вот мой код:
#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
. Отказ Сама операция должна принять одно и то же время (в среднем, конечно, не в том же времени), независимо от того, сколько раз я его выполнял.
Вы могли бы сказать мне, что на самом деле зависит от самой операции, данные прочитаны и что некоторые данные уже могут быть в кэше и BLA BLA, но я не думаю, что это проблема. В моем случае, myOperation
читает 5000 строк текста из файла CSV, отделяя значения по ;
и вставляя эти значения в структуру данных. Для каждой итерации я разрушаю структуру данных и снова инициализирую ее.
Теперь, когда я думаю об этом, я также думаю, что есть время измерения проблемы с clock_gettime()
, Может, я не использую это правильно. Я имею в виду, посмотрите на последний пример, где OPERATIONS = 10000
. Отказ Общее время потребовалось 574133641Н, что было бы примерно 0,5с; Это невозможно, потребовалось пару минут, как я не мог смотреть на экран ждать и пошел что-то съесть.
Решение
Вам просто нужно изменить свой diffTimeClock()
функция, чтобы вернуть количество секунд разницы, как double
:
double diffTimeClock(TimeClock start, TimeClock end) {
double diff;
diff = (end.tv_nsec - start.tv_nsec) / 1E9;
diff += (end.tv_sec - start.tv_sec);
return diff;
}
и в основных рутинных изменениях dTime
к А. double
, и распечатки в соответствии с людьми:
printf(" - SEC (TOTAL): %f\n", dTime);
printf(" - SEC (OP): %f\n\n", dTime / OPERATIONS);
Другие советы
Похоже, тип TimeClock имеет два поля, один в течение секунд и один для наносекунд. Не имеет смысла просто разделить поле наносец с количеством операций. Вам нужно разделить общее время.
Если вы используете систему POSIX, где есть функция GetTimeOfDay (), вы можете использовать что-то подобное, чтобы получить текущее время в микросекундах:
long long timeInMicroseconds(void) {
struct timeval tv;
gettimeofday(&tv,NULL);
return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;
}
Причина, по которой это очень удобно, является то, что для того, чтобы вычислить, насколько ваша функция возьмет вам нужно сделать это:
long long start = timeInMicroseconds();
... do your task N times ...
printf("Total microseconds: %lld", timeInMicroseconds()-start);
Таким образом, вам не нужно иметь дело с двумя целыми числами, один с секундами и одним с микросекундами. Добавление и вычитание времени будут работать очевидно.
Я обычно использую функцию времени () для этого. Это показывает настенные часы времени, но это действительно то, что я забочусь в конце.
Один Gotcha с тестированием производительности - это операционная система может кэшировать операции, связанные с файловой системой. Таким образом, второй (а позже) пробеги могут быть намного быстрее, чем первый пробег. Важно, чтобы вы должны проверить майские операции и в среднем результат, чтобы получить доброе значение для результатов любых изменений, которые вы делаете. Там так много переменных, которые могут помочь вам отфильтровать шум.