LINUX.ORG.RU

[Си] Как измерить время исполнения функции?

 


0

0

Здравствуйте. Есть программа на языке Си, есть функция:
void f()
{
<...>
}

Надо определить сколько времени она исполняется. Желательно как можно точнее.

Что-то вроде такого:
int main()
{
printf("Начинаем замер производительности...\n");
start_some_profiler();
f();
int ticks = end_some_profiler();
printf("Замер производительности показал следующее...");
<...>
}

Что посоветуете?

PS:
В конечном счёте необходимо сравнить эффективность распараллелирования кода используя OpenMP от обычной линейно-исполняющейся программы

Тупой способ: делать gettimeofday до и после вызова и считать время (там, теоретически, до микросекунд)

Ъ олд скулл способ - делать запись в порт до и поле и смотреть осциллографом. (Например Lpt)

marsijanin ★★
()

Скомпилил с `-pg`, запустил, потом выполнил `gprof(1)` в папке с бинарём, увидишь отчёт о том, сколько на какую функцию потратилось времени и ещё много чего.

Sphinx ★★☆☆
()

1. Использовать профайлер.

2. Использовать конструкцию вида:
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);

andreyu ★★★★★
()
Ответ на: комментарий от Sphinx

+1 учись использовать профайлер. Если придётся-таки оптимизировать программу, то с метками задолбаешься, а профайлер тебе сразу более менее объективную картину покажет.

lv ★★
()
Ответ на: комментарий от lv

Профайлер рулит, но с тредами - далеко не всякий. Треды обычно применяют для динамического планирования заданий, а наличие оверхеда со стороны профайлера может сильно повредить распределение заданий по нитям. Наблюдал такое afair с callgrind-ом, но точно не скажу.

YesSSS ★★★
()
Ответ на: комментарий от Sphinx

Там не совсем в этом дело, профайлер способен не просто равномерно замедлить работу проги, но и изменить баланс загрузки процессоров, что для параллельной проги ведет к резкой потере производительности.

Например возможен вариант что одна из нитей просто не успеет к раздаче заданий и вместо четырех процов у тебя будет использоваться три.

YesSSS ★★★
()

Спасиб всем за ответы, решил использовать вызов clock_gettime.
Пробовал gprof но он выдаёт для меня не слишком полезную информацию,
видимо функция слишком быстро функция моя исполняется:
$ gprof ./grad3                        
Flat profile:                                                   

Each sample counts as 0.01 seconds.
 no time accumulated               

  %   cumulative   self              self     total           
 time   seconds   seconds    calls  Ts/call  Ts/call  name    
  0.00      0.00     0.00     3972     0.00     0.00  dfd     
  0.00      0.00     0.00     3885     0.00     0.00  f       
  0.00      0.00     0.00      441     0.00     0.00  get_min 
  0.00      0.00     0.00        1     0.00     0.00  check_result
  0.00      0.00     0.00        1     0.00     0.00  search     

Так что юзаю clock_gettime...

anterior
() автор топика

#ifndef __TSC_TSCMEASUREMENT_H__
#define __TSC_TSCMEASUREMENT_H__

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
	long unsigned	tsc_low,
					tsc_high,
					tsc_low1,
					tsc_high1;
} TscMeasurement;

#define rdtsc(low,high) \
     __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))

inline void tsc_start_measurement (TscMeasurement *tm) {
	rdtsc (tm->tsc_low, tm->tsc_high);
}

inline void tsc_stop_measurement (TscMeasurement *tm) {
	rdtsc (tm->tsc_low1, tm->tsc_high1);
}

inline long long unsigned tsc_get_ticks (const TscMeasurement *tm)
{
	long long unsigned tsc, tsc1;
	tsc = (long long unsigned) tm->tsc_high << 32 |
		((long long unsigned) tm->tsc_low & 0xffffffff);
	tsc1 = (long long unsigned) tm->tsc_high1 << 32 |
		((long long unsigned) tm->tsc_low1 & 0xffffffff);
	return tsc1 - tsc;
}

#ifdef __cplusplus
}
#endif

#endif /*__TSC_TSCMEASUREMENT_H__*/

anonymous
()
Ответ на: комментарий от anonymous

На выходе получается количество тактов процессора, которое заняло выполнение f();
Желательно следить, чтобы процесс не мигрировал на другое ядро/процессор
(можно вручную affinity выставить). Ну и приоритет желательно поднять, чтобы
планировщик другие процессы в измерение не вставлял. Использовать так:

// #include "tscmeasure.h"

TscMeasurement tm;
tsc_start_measurement (&tm);

f ();

tsc_stop_measurement (&tm);

printf ("CPU ticks: %ull\n", tsc_get_ticks (&tm));

anonymous
()
Ответ на: комментарий от anonymous

ээ.. а clock() не то же самое делает?

man 3 clock:

NAME
       clock - Determine processor time

SYNOPSIS
       #include <time.h>

       clock_t clock(void);

DESCRIPTION
       The  clock() function returns an approximation of processor time used
       by the program.

RETURN VALUE
       The value returned is the CPU time used so far as a clock_t;  to  get
       the number of seconds used, divide by CLOCKS_PER_SEC.  If the proces‐
       sor time used is not available or its value  cannot  be  represented,
       the function returns the value (clock_t) -1.

Если не то же самое - просьба - поясните.

lv ★★
()
Ответ на: комментарий от lv

strace тривиальной программы с единственным вызовом clock() показывает, что сlock() делает системный вызов times(), то есть это совсем не то же самое

anonymous
()
Ответ на: комментарий от lv

Бесполезная вещь если внутри функции происходит I/O.

Reset ★★★★★
()
Ответ на: комментарий от frame

У этого кода с rdtsc будут проблемы с процессорами у которых есть управление питанием и в частности изменение частоты и с многоядерными процессорами.

koTuk
()
Ответ на: комментарий от koTuk

если функция висит на данном ядре и грузит его на 100%, то это не даст уйти в "спячку" всему процессору, так что этот метод хорошо подходит для измерения временных интервалов (правда меньних, чем квант времени, выделяемый планировщиком задач)

frame ★★★
()
Ответ на: комментарий от frame

При (не)должной настройке система может менять частоту "на лету", в том числе и плавно (например, при переходе от малой загрузки CPU к большой), поэтому на этот счёт правильное замечание. Просто нужно предварительно проверить, чтобы были отключены такие фичи. Что касается планировщика, до rdtsc тут не хуже функций типа _gettime(). Поднимается приоритет, делается N замеров, чтобы уменьшить влияние случайных событий - и порядок.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.