Измерение времени выполнения выбранных циклов

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

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

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

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

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

1
задан Arjun Singri 29 April 2010 в 18:43
поделиться

3 ответа

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

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

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

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

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

2
ответ дан 3 September 2019 в 00:56
поделиться

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

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

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

0
ответ дан 3 September 2019 в 00:56
поделиться

Я рад, что вы ищете процент, потому что это легко получить. Просто запустите его. Если он работает быстро, поставьте вокруг него внешний цикл, чтобы это заняло много времени. Это не повлияет на проценты. Пока он работает, получите стекшоты. Вы можете сделать это с помощью 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
ответ дан 3 September 2019 в 00:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: