Я пытаюсь найти способ получить время выполнения раздела кода на C. Я уже пробовал и time (), и clock () из time.h, но кажется, что time () возвращает секунды и часы (), кажется, дает мне миллисекунды (или сантисекунды?) Я бы хотел что-то более точное. Есть ли способ отследить время с точностью не менее микросекунды?
Это нужно только для возможности компиляции в Linux.





Возможно, вы захотите поискать в Google инструмент приборы.
Вам нужно приложение профайлер.
Ключевые слова для поиска в SO и поисковых системах: профилирование linux
Попробуйте "bench.h"; это позволяет вам поставить START_TIMER; и STOP_TIMER ("имя"); в ваш код, позволяя произвольно тестировать любой участок кода (примечание: рекомендуется только для коротких участков, а не для вещей, занимающих десятки миллисекунд и более). Его точность соответствует тактовому циклу, хотя в некоторых редких случаях он может изменить способ компиляции промежуточного кода, и в этом случае вам лучше использовать профилировщик (хотя профилировщики обычно труднее использовать для определенных разделов кода).
Работает только на x86.
Хороший, у нас есть похожий, с полезным дополнением, PERF_MARK. Это позволит отметить точку умножения, хранящуюся в статическом массиве. У нас есть версия, которая может сохранять строку для удобного чтения результатов, по умолчанию массив содержит 100 записей, но может быть изменен. PERF_STOP выводит результаты.
Тем, кто добавил примечание об этом сбое в многоядерных системах: я удалил его, потому что это просто неверно. Макрос автоматически обрабатывает переключение контекста и другие внезапные изменения значений RDTSC, поэтому такой проблемы не существует. Я использую его исключительно на многоядерных машинах, и он отлично работает.
Темный Шикари: Это не может быть правильным, этот макрос не может обрабатывать такие вещи, как упреждающее переключение контекста. Просто косяк. Это даст результаты, но они не будут точными. Кроме того, время возврата откалибровано для процессора Core2 (из-за #define NOP_CYCLES), и его необходимо изменить в соответствии с требованиями.
Взгляните на gettimeofday, Часы_* или получить / установить.
Вы упомянули clock() и time() - вы искали gettimeofday()?
Это заполнит struct timeval, который содержит секунды и микросекунды.
Конечно, реальное разрешение зависит от оборудования.
Вы не найдете вызова библиотеки, который позволяет преодолеть тактовое разрешение вашей платформы. Либо используйте профилировщик (man gprof), как предлагал другой плакат, либо - быстро и грязно - поместите цикл вокруг проблемного участка кода, чтобы выполнить его много раз, и используйте clock ().
Если вы разрабатываете на x86 или x64, почему бы не использовать счетчик отметок времени: RDTSC.
Это будет более надежно, чем функции Ansi C, такие как time () или clock (), поскольку RDTSC является атомарной функцией. Использование функций C для этой цели может вызвать проблемы, поскольку у вас нет гарантии, что поток, в котором они выполняются, не будет отключен, и в результате значение, которое они возвращают, не будет точным описанием фактического времени выполнения, которое вы пытаетесь измерить. .
С помощью RDTSC вы можете лучше измерить это. Вам нужно будет преобразовать счетчик тиков обратно в удобочитаемый формат времени H: M: S, который будет зависеть от тактовой частоты процессора, но погуглите, и я уверен, что вы найдете примеры.
Однако даже с RDTSC вы будете включать время, когда ваш код был отключен от выполнения, в то время как лучшее решение, чем использование time () / clock (), если вам нужно точное измерение, вам придется обратиться к профилировщику, который будет инструментировать ваш код. и примите во внимание, когда ваш код на самом деле не выполняется из-за переключений контекста или чего-то еще.
Как бы то ни было, вот один из нескольких макросов:
#include <time.h>
clock_t startm, stopm;
#define START if ( (startm = clock()) == -1) {printf("Error calling clock");exit(1);}
#define STOP if ( (stopm = clock()) == -1) {printf("Error calling clock");exit(1);}
#define PRINTTIME printf( "%6.3f seconds used by the processor.", ((double)stopm-startm)/CLOCKS_PER_SEC);
Тогда просто используйте его с:
main() {
START;
// Do stuff you want to time
STOP;
PRINTTIME;
}
Это зависит от условий. Профайлеры хороши для общих глобальных представлений, однако, если вам действительно нужно точное представление, я рекомендую KISS. Просто запустите код в цикле, чтобы его выполнение заняло около минуты. Затем вычислите простое среднее значение на основе общего времени выполнения и выполненных итераций.
Такой подход позволяет:
Получайте точные результаты с помощью таймеров с низким разрешением.
Не сталкиваться с проблемами, когда приборы мешают работе высокоскоростных кешей (l2, l1, branch… и т. д.) Рядом с процессором. Однако выполнение того же кода в замкнутом цикле также может дать оптимистичные результаты, которые могут не отражать реальные условия.
Не знаю, над какой средой / ОС вы работаете, но ваше время может быть неточным, если другой поток, задача или процесс вытесняют ваш синхронизированный код посередине. Я предлагаю изучить такие механизмы, как мьютексы или семафоры, чтобы предотвратить прерывание вашего процесса другими потоками.
gettimeofday() обеспечивает разрешение в микросекунды, тогда как clock_gettime() обеспечивает разрешение в наносекунды.
int clock_gettime(clockid_t clk_id, struct timespec *tp);
clk_id определяет используемые часы. Используйте CLOCK_REALTIME, если хотите, чтобы общесистемные часы были видны всем процессам. Используйте CLOCK_PROCESS_CPUTIME_ID для таймера процесса и CLOCK_THREAD_CPUTIME_ID для таймера, зависящего от потока.
Профилировщик предоставляет статистическую информацию, которая отличается от фактического измерения.