Измерение времени выполнения выбранных циклов - PullRequest
1 голос
/ 29 апреля 2010

Я хочу измерить время выполнения выбранных циклов в C-программе, чтобы увидеть, какой процент от общего времени выполнения программы (в Linux) тратится на эти циклы. Я должен быть в состоянии указать петли, для которых должна измеряться производительность. За последние несколько дней я опробовал несколько инструментов (vtune, hpctoolkit, oprofile), и ни один из них, похоже, не делал этого. Все они находят узкие места в производительности и просто показывают время для них. Это потому, что эти инструменты хранят только время, превышающее пороговое значение (~ 1 мс). Поэтому, если один цикл занимает меньше времени, чем его, то о времени его выполнения сообщаться не будет.

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

Я мог бы вручную написать простой таймер, используя gettimeofday или что-то в этом роде, но в некоторых случаях он не даст точных результатов. Например:

for (i = 0; i < 1000; ++i)
{
    for (j  = 0; j < N; ++j)
    {
        //do some work here
    }
}

Теперь я хочу измерить общее время, проведенное во внутреннем цикле, и мне нужно будет вызвать gettimeofday внутри первого цикла. Так что gettimeofday сам будет вызываться 1000 раз, что приводит к собственным издержкам, и результат будет неточным.

Ответы [ 3 ]

2 голосов
/ 29 апреля 2010

Если у вас нет встроенного эмулятора или коммутационного блока вокруг вашего ЦП, нет такой вещи, как синхронизация по одной петле или одной инструкции. Вам нужно объединить свои тестовые прогоны до чего-то, что занимает по крайней мере несколько секунд каждый, чтобы уменьшить количество ошибок, вызванных другими процессами, происходящими в ЦП, ОС и т. Д.

Если вы хотите точно узнать, сколько времени занимает выполнение определенного цикла, а выполнение занимает, скажем, менее 1 секунды, вам нужно искусственно увеличить количество итераций, чтобы чтобы получить число, которое выше "минимального уровня шума". Затем вы можете взять это число и разделить его на число искусственно завышенных итераций, чтобы получить показатель, который показывает, сколько времени займет один проход через целевой цикл.

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

Это верно, независимо от того, измеряете ли вы производительность с помощью высокопроизводительных счетчиков с точностью до миллисекунды, предоставляемых ЦП, системными часами или настенными часами, чтобы измерить прошедшее время вашего теста.

В противном случае вы просто измеряете белый шум.

0 голосов
/ 30 апреля 2010

Я рад, что вы ищете процент, потому что это легко получить. Просто запусти его. Если он работает быстро, обведите вокруг него внешнюю петлю, чтобы это заняло много времени. Это не повлияет на проценты. Пока он работает, получите Stackshots . Вы можете сделать это с помощью Ctrl-Break в gdb , или вы можете использовать pstack или lsstack . Просто посмотрите, какой процент стеков выдает код, который вам небезразличен.

Предположим, что петли занимают некоторое время, например 0,2 (20%), и вы берете N = 20 выборок. Тогда число сэмплов, которое должно их показать, в среднем составит 20 * 0,2 = 4, а стандартное отклонение количества сэмплов будет равно sqrt (20 * 0,2 * 0,8) = sqrt (3.2) = 1,8, поэтому, если вы хотите большей точности Возьми больше образцов. (Я лично думаю, что точность переоценена.)

0 голосов
/ 29 апреля 2010

Обычно, если вы хотите измерить время, проведенное во внутреннем цикле, вы поместите время на получение подпрограмм вне внешнего цикла, а затем разделите его на число (внешнего) цикла. Если вы ожидаете, что время внутреннего цикла будет относительно постоянным для любого j, то есть.

Любые инструкции по профилированию влекут за собой свои накладные расходы, но, предположительно, накладные расходы будут одинаковыми, независимо от того, где они вставлены, так что «все это появляется при стирке». Предположительно, вы ищете места, где существуют значительные различия между средами выполнения двух сравниваемых процессов, где такая пара вызовов функций не будет проблемой (так как вам также нужен один в конце, чтобы получить время delta), поскольку одна подпрограмма будет в два раза дороже другой.

Большинство платформ также предлагают таймеры с более высоким разрешением, хотя та, что мы здесь используем, скрыта за API, так что «клиентский» код является кроссплатформенным. Я уверен, что немного взглянув, ты сможешь это сделать. Хотя даже здесь маловероятно, что вы достигнете точности более 1 мс, поэтому предпочтительно запускать код несколько раз подряд и время выполнения всего цикла (затем делить на число циклов, естественно).

...