Как профилировать время, затрачиваемое на доступ к памяти в приложениях C/С++?
Общее время, затрачиваемое функцией в приложении, можно разделить на два компонента:
- Время, затраченное на фактическое вычисление (Tcomp)
- Время, затрачиваемое на доступ к памяти (Tmem)
Обычно профилировщики дают оценку общего времени, затрачиваемого функцией. Можно ли получить оценку времени, проведенного в терминах двух вышеуказанных компонентов (Tcomp и Tmem)?
Ответы
Ответ 1
Понятие модели Арифметическая интенсивность было предложено моделью Roofline: https://crd.lbl.gov/departments/computer-science/PAR/research/roofline/. Просто сказано, что он определяет количество арифметических команд, выполняемых для каждого доступа к памяти.
Вычисление арифметической интенсивности обычно осуществляется с помощью счетчиков производительности.
Ответ 2
Невозможно измерить это (и это не имеет никакого смысла это делать), потому что вычисление перекрывается с обращениями к памяти в текущих архитектурах процессоров. Также доступная память обычно разбивается на большее количество шагов (доступ к памяти, предварительная выборка к различным уровням кэша, фактическое чтение в регистры процессора).
Вы можете измерять кеширование и промахи на разных уровнях кеша, чтобы оценить эффективность вашего алгоритма на вашем оборудовании, используя perf и его аппаратные счетчики (если поддерживается вашим оборудованием).
Ответ 3
Брендан Грегг в своем недавнем сообщении в блоге Использование процессора неверно предлагает использовать инструкции за цикл PMC. Короче, если IPC является < 1.0, чем приложение можно считать привязанным к памяти. В противном случае это можно считать обязательным. Вот соответствующий отрывок из его поста:
Если ваш IPC равен < 1.0, вы, вероятно, застопорились, и программное обеспечение стратегии настройки включают в себя сокращение ввода-вывода памяти и улучшение ЦП кеширования и локализации памяти, особенно в системах NUMA. аппаратные средства настройка включает использование процессоров с большими кэшами процессора и более быстрое памяти, шин и межсоединений.
Если ваш IPC равен > 1.0, вы, вероятно, связаны с инструкциями. Ищите способы уменьшить выполнение кода: устранить ненужную работу, кеш операций и т.д. Графики пламени CPU - отличный инструмент для этого расследование. Для аппаратной настройки, попробуйте более быструю тактовую частоту и более Ядра /hyperthreads.
Для моих приведенных выше правил я разделился на IPC 1.0. Где я получил это из? Я сделал это, основываясь на моей предыдущей работе с PMC. Вот как вы может получить значение, которое настраивается для вашей системы и времени выполнения: напишите два фиктивные рабочие нагрузки, которые связаны с процессором, и одна граница памяти. Мера их IPC, а затем вычислить их среднюю точку.
Вот несколько примеров фиктивных рабочих нагрузок, созданных инструмент стресса и их IPC.
Тест с привязкой к памяти, IPC низкий (0,02):
$ perf stat stress --vm 4 -t 3
stress: info: [4520] dispatching hogs: 0 cpu, 0 io, 4 vm, 0 hdd
stress: info: [4520] successful run completed in 3s
Performance counter stats for 'stress --vm 4 -t 3':
10767,074968 task-clock:u (msec) # 3,560 CPUs utilized
0 context-switches:u # 0,000 K/sec
0 cpu-migrations:u # 0,000 K/sec
4 555 919 page-faults:u # 0,423 M/sec
4 290 929 426 cycles:u # 0,399 GHz
67 779 143 instructions:u # 0,02 insn per cycle
18 074 114 branches:u # 1,679 M/sec
5 398 branch-misses:u # 0,03% of all branches
3,024851934 seconds time elapsed
Тест с привязкой к ЦП, высокий уровень IPC (1,44):
$ perf stat stress --cpu 4 -t 3
stress: info: [4465] dispatching hogs: 4 cpu, 0 io, 0 vm, 0 hdd
stress: info: [4465] successful run completed in 3s
Performance counter stats for 'stress --cpu 4 -t 3':
11419,683671 task-clock:u (msec) # 3,805 CPUs utilized
0 context-switches:u # 0,000 K/sec
0 cpu-migrations:u # 0,000 K/sec
108 page-faults:u # 0,009 K/sec
30 562 187 954 cycles:u # 2,676 GHz
43 995 290 836 instructions:u # 1,44 insn per cycle
13 043 425 872 branches:u # 1142,188 M/sec
26 312 747 branch-misses:u # 0,20% of all branches
3,001218526 seconds time elapsed
Ответ 4
если вы ищете функцию для получения цикла процессора, тогда повышение будет очень полезно.
Я использовал утилиту Boost Timer для вычисления циклов процессора при системном вызове.
С другой стороны, вы можете поместить ту же функцию в полную программу, чтобы получить общее время.
Надеюсь, это то, что вы ищете.
-Vijay