|
Bog BOS: oprofile - исследование особенностей вычислительной производительности с использованием аппаратных счётчиков событий
|
Последнее изменение файла: 2022.03.28
Скопировано с www.bog.pp.ru: 2024.11.23
Bog BOS: oprofile - исследование особенностей вычислительной производительности с использованием аппаратных счётчиков событий
oprofile - исследование особенностей вычислительной производительности на уровне системы
с использованием встроенных в ЦП счётчиков событий: такты ядра, такты шины, обращений к шине, промахи кеша и т.п.
(количество счётчиков, поддерживаемые типы событий и маски событий зависят от архитектуры и модели ЦП).
Можно подсчитывать события, происходящие в режиме ядра, в режиме пользователя или обоих режимах.
При достижении заданного числа событий проиcходит прерывание (NMI, non-maskable interrupts), обработчик прерывания
записывает сообщение о событии (счётчик адреса и номер процесса) в буфер ядра,
сервис oprofiled переносит накопленные данные из буфера ядра в файл.
Сохранённый счётчик адреса и стек вызовов позволяет привязывать события к программам (модулям ядра), операторам ЯВУ и командам.
Позволяет определить "узкое горло", включая подсистемы ядра (модули и обработчики прерываний).
В качестве прообраза использовалась система DCPI (DEC Continuous Profiling Infrastructure).
Не оказывает воздействия на исполняемые программмы ни в поведении, ни в производительности (счётчики обновляются аппаратно).
Пакет oprofile (oprofile-gui, oprofile-jit, oprofile-devel) версии 0.9.4 в RHEL5.4
(для Nehalem (i7, Xeon 55xx) требуется 0.9.5).
Для IBS (Instruction-Based Sampling) для AMD K10 требуется ядро 2.6.28.
Используется модуль ядра oprofile, демон oprofiled, утилита управления opcontrol
и утилиты генерации отчётов opreport (возможна фильтрация по программам) и opannotate (с точностью до строки ЯВУ или команды).
Перед запуском мониторинга блокируется NMI watchdog, для разблокировки требуется выгрузить модуль ядра.
Внеочередное исполнение инструкций в современных ЦП не позволяет привязать данные с точностью до команды.
Записывается не каждое событие, а одно из N событий (каждый счётчик имеет ограничение на N снизу).
При уменьшении N увеличивается побочная нагрузка на систему вплоть до зависания
(при уменьшении N с 30000 до 3000 время расчёта увеличилось вдвое (на 20%), доля потерь отсчётов в 1.5 раза (в 8 раз);
при увеличении - уменьшается точность (потери отсчётов из-за переполнения буфера пропали при увеличении до 50000
на AMD K10 с частотой 2800MHz при нагрузке на все 24 ядра).
Заброшена в пользу perf.
Модуль ядра oprofile имеет параметры: p4force, timer (использовать только прерывания от таймера).
По умолчанию, счётчик 0 отслеживает событие CPU_CLK_UNHALTED (для Core2/K10).
Для управления используется файловая система в каталоге /dev/oprofile/, в котором можно посмотреть текущее состояние,
задать параметры мониторинга и взять результаты (почему он в /dev, а не в /proc или /sys?).
Максимальное количество одновременно используемых счётчиков определяется моделью ЦП, нумеруются с 0,
каждый счётчик имеет подкаталог в /dev/oprofile/ (отсюда можно определить их число):
- /dev/oprofile/cpu_type - тип ЦП с точки зрения модуля
- /dev/oprofile/cpu_buffer_size - размер буфера ядра
- /dev/oprofile/buffer_size - размер буфера
- /dev/oprofile/stats/ - статистика сбора информации (количество потерянных отсчётов)
- /dev/oprofile/0/enabled - счётчик включён
- /dev/oprofile/0/count - количество событий между прерываниями
- /dev/oprofile/0/event - тип событий
- /dev/oprofile/0/unit_mask - маска
- /dev/oprofile/0/kernel - учитывать события в режиме ядра
- /dev/oprofile/0/user - учитывать события в режиме пользователя
"ophelp -r" выдаёт тип ЦП.
ophelp с указанием имени счётчика выдаёт его номер.
ophelp без параметров выдаёт список допустимых счётчиков и масок, например,
для Intel Xeon 55xx (Nehalem, i7; 5 счётчиков, 31 bit? не получается задать больше 1 счётчика):
- счётчики тактов
- CPU_CLK_UNHALTED - такты, в которых ЦП не был в состоянии останова
(по умолчанию, маска 0x00 - циклы ядра; 0x01 - циклы шины, 0x02 - при остановленных остальных ядрах)
- счётчики инструкций, микроопераций, прерываний
- INST_RETIRED_ANY_P - количество выполненных инструкций
- SEGMENT_REG_LOADS
- FLOPS - микрокоманд плавающей арифметики
- MUL - число умножений
- DIV - число делений
- EIST_TRANS_ALL - количество переходов Intel Enhanced SpeedStep Technology
- THERMAL_TRIP - количество температурных переходов
- RS_UOPS_DISPATCHED - количество микрокоманд, запланированных к выполнению
- RS_UOPS_DISPATCHED_NONE - количество пустых микрокоманд, запланированных к выполнению
- MACRO_INSTS - количество декодированных команд (по умолчанию, маска 0x9; 1 - команд, 8 - команд CISC)
- SIMD_UOPS_EXEC - количество выполненных SIMD команд
- SIMD_SAT_UOP_EXEC - количество выполненных "насыщающих" (saturating?) SIMD команд
- SIMD_UOP_TYPE_EXEC - количество пакованных SIMD команд (по умолчанию, маска 0x3f;
1 - умножений, 2 - сдвигов, 4 - паковок, 8 - распаковок, 0x10 - логических, 0x20 - арифметических)
- SIMD_INST_RETIRED - команд SSE/SSE2 (по умолчанию, маска 0x1f; 1 - SSE packed-single, 2 - SSE scalar-single,
4 - SSE2 packed-double, 8 - SSE2 scalar-double, 0x10 - SSE2 vector integer)
- SIMD_COMP_INST_RETIRED - команд SSE/SSE2 (по умолчанию, маска 0xf; 1 - SSE packed-single, 2 - SSE scalar-single,
4 - SSE2 packed-double, 8 - SSE2 scalar-double)
- SIMD_INSTR_RET - количество команд SIMD
- SIMD_SAT_INSTR_RET - количество "насыщающих" (saturating?) SIMD команд
- INST_RETIRED - количество выполненных инструкций (по умолчанию, маска 0x00 - любых;
0x01 - команд загрузки, 0x02 - команд записи,
0x04 - других)
- X87_OPS_RETIRED - количество команд с плавающей точкой
- UOPS_RETIRED - количество микрокоманд (по умолчанию, маска 0xf;
1 - слитых "загрузка и операция" или "загрузка и косвенный переход";
2 - слитых "запись адреса и адреса";
4 - пара команд слитых в одну микрокоманду;
8 - неслитых микрокоманд)
- FP_MMX_TRANS - преобразований между FP и MMX (по умолчанию, маска 3; 1 - из FP в MMX, 2 - из MMX в FP)
- MMX_ASSIST - количество команд EMMS
- HW_INT_RCV - количество аппаратных прерываний
- CYCLES_INT_MASKED - количество циклов с замаскированными прерываниями (по умолчанию, маска 2;
1 - с замаскированными прерываниями; 2 - с замаскированными прерываниями при наличии прерываний0
- BR_INST_DECODED - декодированных команд перехода
- BR_BOGUS - количество фиктивных переходов
- BR_INST_EXEC - выполненных команд перехода
- BR_MISSP_EXEC - неправильно предсказанных выполненных команд перехода
- BR_BAC_MISSP_EXEC - неправильно предсказанных на входе (at Front End, BAC) выполненных команд перехода
- BR_CND_EXEC и BR_CND_MISSP_EXEC - условных переходов и неправильно предсказанных условных переходов
- BR_IND_EXEC и BR_IND_MISSP_EXEC - косвенных переходов и неправильно предсказанных косвенных переходов
- BR_RET_EXEC, BR_RET_MISSP_EXEC, BR_RET_BAC_MISSP_EXEC - команд возврата, неправильно предсканных, непраильно
предсказанных на входе
- BR_CALL_EXEC, BR_CALL_MISSP_EXEC - вызовов функций и неправильно предсказанных вызовов функций
- BR_IND_CALL_EXEC - косвенных вызовов
- BR_TKN_BUBBLE_1, BR_TKN_BUBBLE_2 - предсказанных переходов
- BR_INST_RETIRED - команд перехода (по умолчанию, маска 0xa - неправильно предсказанных)
- BR_MISS_PRED_RETIRED - неправильно предсказанных команд перехода
- эффективность кеширования
- L1D_CACHE_LD - количество кешированных чтений данных (по умолчанию, маска 0xf - MESI)
- L1D_CACHE_ST - количество кешированных записей данных (по умолчанию, маска 0xf - MESI)
- L1D_CACHE_LOCK - количество кешированных чтений данных с блокировкой (по умолчанию, маска 0xf - MESI)
- L1D_CACHE_LOCK_DURATION - длительность кешированных операций с блокировкой
- L1D_ALL_REF - обращений к L1D
- L1D_ALL_CACHE_REF - кешированных чтений и записей
- L1D_REPL - количество строк, резервированных в L1D
- L1D_M_REPL - количество изменённых строк, резервированных в L1D
- L1D_M_EVICT - количество изменённых строк, изгнанных из L1D
- L1D_PEND_MISS - количество промахов в L1D в ожидании
- L1D_SPLIT - количество разбитых строк L1D (по умолчанию, маска 0x1 - загрузок; 2 - сохранений)
- L1I_READS - количество загрузок инструкций из L1I
- L1I_MISSES - количество загрузок инструкций из L1I с промахом
- L1D_PREFETCH - количество команд предзагрузки L1D
- L2_RQSTS - запросов управления L2 (по умолчанию, маска 0x7f - от этого ядра)
- LLC_MISSES - промахов L2 от этого ядра
- LLC_REFS - требований к L2
- L2_ADS - циклов, в которых шина адреса L2 занята (по умолчанию, маска 0x40 - это ядро)
- L2_DBUS_BUSY_RD - циклов, в которых L2 передат данные в ядро (по умолчанию, маска 0x40 - это ядро)
- L2_LINES_IN - количество строк, резервированных в L2 (по умолчанию, маска 0x70;
маска 0xc0 - все ядра, 0x40 - это ядро,
0x30 - любые предзагрузки, 0x10 - аппаратные предзагрузки, 0x00 - предзагрузки, кроме аппаратных)
- L2_M_LINES_IN - количество изменённых строк, резервированных в L2 (по умолчанию, маска 0x40 - это ядро)
- L2_LINES_OUT - количество строк, явно выведенных из L2 (по умолчанию, маска 0x70 - это ядро, все prefetch)
- L2_M_LINES_OUT - количество изменённых строк, явно выведенных из L2
(по умолчанию, маска 0x70 - это ядро, все prefetch)
- L2_IFETCH - количество загрузок команд из L2 (по умолчанию, маска 0x4f - это ядро)
- L2_LD - число загрузок в L2 (по умолчанию, маска 0x7f - это ядро)
- L2_ST - число записей из L2 (по умолчанию, маска 0x4f - это ядро)
- L2_LOCK - число заблокированных обращений L2 (по умолчанию, маска 0x4f - это ядро)
- L2_REJECT_BUSQ - число отвергнутых запросов L2 (по умолчанию, маска 0x7f - это ядро)
- L2_NO_REQ - количество циклов без ожидания L2 (по умолчанию, маска 0x40 - это ядро)
- PREF_RQSTS_UP - количество предзагрузок вперёд
- PREF_RQSTS_DN - количество предзагрузок назад
- EXT_SNOOP - внешних snoop (по умолчанию, маска 0xb - всех для этого агента)
- CMP_SNOOP - snoop L1D другими ядрами (по умолчанию, маска 0x40 - это ядро)
- SSE_PRE_EXEC - количество команд загрузки кеша (по умолчанию, маска 0 - NTA; 1 - T1; 2 - T1 и T2;
3 - SSE weakly-ordered stores)
- SSE_PREF_MISS - команды предзагрузки SSE промахнувшиеся мимо всех кешей (по умолчанию, маска 0 - PREFETCHNTA;
1 - PREFETCHT0; 2 - PREFETCHT1/PREFETCHT2)
- TLB
- DTLB_MISSES - промахов DTLB (по умолчанию, маска 0xf;
маска 0x01 (ANY) - любых, 0x02 (MISS_LD) - промахов команд загрузки,
0x04 (L0_MISS_LD) - промахов L0 DTLB (?) команд загрузки, 0x08 (MISS_ST) - промахов команд записи
- ITLB - промахов ITLB (по умолчанию, маска 0x12; 0x02 - промах малой страницы; 0x10 - промах большой страницы;
0x40 - сбросов ITLB)
- ITLB_MISS_RETIRED - промахов ITLB
- проблемы
- MISALIGN_MEM_REF - невыровненных адресов памяти
- MACHINE_NUKES_SMC - количество сбросов конвейера (по умолчанию, маска 0x5; 1 - самомодифицирующийся код;
4 - конфликт доступа к памяти)
- RAT_STALLS - циклов, блокированных из-за частичного заполнения регистров (по умолчанию, маска 0xf - все виды)
- RESOURCE_STALLS - блокировок из-за проблем с ресурсами (по умолчанию, маска 0xf - все)
- SNOOP_STALL_DRV - Bus stalled for snoops (по умолчанию, маска 0x40 - это ядро)
- INST_QUEUE_FULL - количество циклов, в которых очередь команд переполнена
- IFU_MEM_STALL - количество циклов, в которых конвейер загрузки команд застрял
- ILD_STALL - количество циклов, в которых декодер длины команд застрял
- запросы к памяти, в/в и другим ЦП
- MEM_LOAD_RETIRED - количество загрузок (по умолчанию, маска 0x1; 1 - загрузок мимо L1D,
2 - загрузок строки кеша мимо L1D, 4 - загрузок мимо L2, 8 - загрузок строки кеша мимо L2,
0x10 - загрузок мимо DTLB
- LOAD_BLOCK - блокировок загрузки (по умолчанию, маска 0x3e - все)
- STORE_BLOCK - блокировок записи (по умолчанию, маска 0xb - все)
- BUS_REQ_OUTSTANDING - длительность кешируемых запросов чтения шины в очереди (по умолчанию, маска 0x40 - это ядро)
- BUS_BNR_DRV - количество сигналов Bus Not Ready
- BUS_DRDY_CLOCKS - количество циклов шины, когда по ней пересылаются данные
- BUS_LOCK_CLOCKS - количество сигналов LOCK на шине (по умолчанию, маска 0x40 - это ядро)
- BUS_DATA_RCV - количество циклов шины, когда процессор получает данные (по умолчанию, маска 0x40 - это ядро)
- BUS_TRAN_BRD - количество уплотнённых (burst) транзакций чтения шины (по умолчанию, маска 0x40 - это ядро)
- BUS_TRAN_RFO (read for ownership), BUS_TRAN_WB (writeback), BUS_TRAN_IFETCH (загрузка инструкций),
BUS_TRAN_INVAL (invalidate), BUS_TRAN_PWR (partial write), BUS_TRANS_P (partial), BUS_TRANS_IO,
BUS_TRANS_DEF (completed defer), BUS_TRAN_BURST (completed burst), BUS_TRAN_MEM (completed memory),
BUS_TRAN_ANY (любых завершённых) - количество соответствующих транзакций шины (по умолчанию, маска 0x40 - это ядро)
- BUS_HIT_DRV - количество сигналов HIT на шине
- BUS_HITM_DRV - количество сигналов HITM на шине
- BUSQ_EMPTY - очередь шины пуста (по умолчанию, маска 0x40 - это ядро)
- BUS_IO_WAIT - запросы в/в ждут в очереди шины
ophelp для AMD K10 (все счётчики универсальные;
4 счётчика по 40 bit? не получается задать более 3):
- счётчики тактов
- CPU_CLK_UNHALTED (единственный счётчик с одинаковым именем для AMD и Intel)
- счётчики инструкций, микроопераций, прерываний
- RETIRED_INSTRUCTIONS (не перепутайте с INST_RETIRED для Intel ;)
- DISPATCHED_FPU_OPS (по умолчанию, маска 0x3f - все команды)
- RETIRED_SSE_OPS (по умолчанию, маска 0x7f - все команды)
- RETIRED_MOVE_OPS (по умолчанию, маска 0xf - все команды)
- RETIRED_SERIALIZING_OPS (по умолчанию, маска 0xf - все команды)
- RETIRED_UOPS
- RETIRED_BRANCH_INSTRUCTIONS
- RETIRED_MISPREDICTED_BRANCH_INSTRUCTIONS
- RETIRED_TAKEN_BRANCH_INSTRUCTIONS
- RETIRED_TAKEN_BRANCH_INSTRUCTIONS_MISPREDICTED
- RETIRED_FAR_CONTROL_TRANSFERS
- RETIRED_BRANCH_RESYNCS
- RETIRED_NEAR_RETURNS
- RETIRED_NEAR_RETURNS_MISPREDICTED
- RETIRED_INDIRECT_BRANCHES_MISPREDICTED
- RETIRED_MMX_FP_INSTRUCTIONS (по умолчанию, маска 0x7; 1 - инструкции x87, 2 - MMX и 3DNow, 4 - SSE)
- RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS (по умолчанию, маска 0x7)
- INTERRUPTS_TAKEN
- INTERRUPTS_MASKED_CYCLES (циклы с маскированными прерываниями)
- INTERRUPTS_MASKED_CYCLES_WITH_INTERRUPT_PENDING
- DR0_BREAKPOINTS, DR1_BREAKPOINTS, DR2_BREAKPOINTS, DR3_BREAKPOINTS
- SIZED_COMMANDS(по умолчанию, маска 0x3f)
- эффективность кеширования
- LS_BUFFER_2_FULL_CYCLES
- DATA_CACHE_ACCESSES
- DATA_CACHE_MISSES
- DATA_CACHE_REFILLS_FROM_L2_OR_NORTHBRIDGE (по умолчанию, маска 0x1e - All cache states except refill from northbridge;
1 - Refill from northbridge; 2 - Shared-state line from L2, 4 - Exclusive-state line from L2,
8 - Owner-state line from L2, 0x10 - Modified-state line from L2)
- DATA_CACHE_REFILLS_FROM_NORTHBRIDGE (по умолчанию, маска 0x1f - All cache states)
- DATA_CACHE_LINES_EVICTED (по умолчанию, маска 0x1f)
- INEFFECTIVE_SW_PREFETCHES (по умолчанию, маска 0x9)
- DATA_PREFETCHES (аппаратные; по умолчанию, маска 0x3)
- REQUESTS_TO_L2 (по умолчанию, маска 0x3f)
- L2_CACHE_MISS (по умолчанию, маска 0xf)
- L2_CACHE_FILL_WRITEBACK (по умолчанию, маска 0x3)
- INSTRUCTION_CACHE_FETCHES
- INSTRUCTION_CACHE_MISSES
- INSTRUCTION_CACHE_REFILLS_FROM_L2
- INSTRUCTION_CACHE_REFILLS_FROM_SYSTEM
- INSTRUCTION_CACHE_VICTIMS
- INSTRUCTION_CACHE_INVALIDATED (по умолчанию, маска 0xf)
- CACHE_BLOCK_COMMANDS (по умолчанию, маска 0x3d)
- READ_REQUEST_L3_CACHE (по умолчанию, маска 0xf7)
- L3_CACHE_MISSES (по умолчанию, маска 0xf7)
- L3_FILLS_CAUSED_BY_L2_EVICTIONS (по умолчанию, маска 0xff)
- L3_EVICTIONS (по умолчанию, маска 0xf)
- TLB
- L1_DTLB_MISS_AND_L2_DTLB_HIT
- L1_DTLB_AND_L2_DTLB_MISS
- L1_DTLB_HIT
- L1_ITLB_MISS_AND_L2_ITLB_HIT
- L1_ITLB_MISS_AND_L2_ITLB_MISS
- GLOBAL_TLB_FLUSHES
- ITLB_RELOADS
- ITLB_RELOADS_ABORTED
- проблемы
- PIPELINE_RESTART_DUE_TO_SELF_MODIFYING_CODE
- PIPELINE_RESTART_DUE_TO_PROBE_HIT
- LOCKED_OPS (маска 1 - locked instructions, 2 - Cycles in speculative phase,
4 - Cycles in non-speculative phase (including cache miss penalty), 8 - Cache miss penalty in cycles)
- MISALIGNED_ACCESSES
- 1_BIT_ECC_ERRORS (по умолчанию, маска 0xf)
- PIPELINE_RESTART_DUE_TO_INSTRUCTION_STREAM_PROBE
- INSTRUCTION_FETCH_STALL
- RETURN_STACK_HITS
- RETURN_STACK_OVERFLOWS
- DECODER_EMPTY
- DISPATCH_STALLS
- DISPATCH_STALL_FOR_BRANCH_ABORT
- DISPATCH_STALL_FOR_SERIALIZATION
- DISPATCH_STALL_FOR_SEGMENT_LOAD
- DISPATCH_STALL_FOR_REORDER_BUFFER_FULL
- DISPATCH_STALL_FOR_RESERVATION_STATION_FULL
- DISPATCH_STALL_FOR_FPU_FULL
- DISPATCH_STALL_FOR_LS_FULL
- DISPATCH_STALL_WAITING_FOR_ALL_QUIET
- DISPATCH_STALL_FOR_FAR_TRANSFER_OR_RESYNC
- FPU_EXCEPTIONS (по умолчанию, маска 0xf)
- THERMAL_STATUS (по умолчанию, маска 0x7c)
- запросы к памяти, в/в и другим ЦП
- MEMORY_REQUESTS (по умолчанию, маска 0x83)
- NORTHBRIDGE_READ_RESPONSES (по умолчанию, маска 0x17)
- OCTWORD_WRITE_TRANSFERS
- DRAM_ACCESSES (по умолчанию, маска 0xff; 0x7 - DCT0, 0x38 - DCT1, 0x40 - запись, 0x80 - чтение)
- MEMORY_CONTROLLER_PAGE_TABLE_OVERFLOWS
- MEMORY_CONTROLLER_SLOT_MISSED
- MEMORY_CONTROLLER_TURNAROUNDS
- MEMORY_CONTROLLER_BYPASS_COUNTER_SATURATION
- CPU_IO_REQUESTS_TO_MEMORY_IO (по умолчанию, маска 0xa2 - Local I/O to Local Memory;
0xa8 - Local CPU to Local Memory; 0x98 - Local CPU to Remote Memory; ...)
- PROBE_RESPONSES_AND_UPSTREAM_REQUESTS (по умолчанию, маска 0xff)
- GART_EVENTS (по умолчанию, маска 0xff)
- MEMORY_CONTROLLER_REQUESTS (по умолчанию, маска 0x78 - чтение или запись 32 или 64 байт)
- CPU_DRAM_REQUEST_TO_NODE (зпрос к памяти определённого узла; по умолчанию, маска 0xff;
1 - к узлу 0; 2 - к узлу 1, 4 - к узлу 2, 8 - к узлу 3)
- IO_DRAM_REQUEST_TO_NODE
- CPU_READ_COMMAND_LATENCY_NODE_0_3 (задержка между локальным и удалённым узлом; по умолчанию, маска 0xff)
- CPU_READ_COMMAND_REQUEST_NODE_0_3 (число запросов, задержка которых подсчитывается; по умолчанию, маска 0xff)
- CPU_READ_COMMAND_LATENCY_NODE_4_7 (задержка между локальным и удалённым узлом; по умолчанию, маска 0xff)
- CPU_READ_COMMAND_REQUEST_NODE_4_7 (число запросов, задержка которых подсчитывается; по умолчанию, маска 0xff)
- CPU_COMMAND_LATENCY_TARGET
- CPU_REQUEST_TARGET
- HYPERTRANSPORT_LINK0_TRANSMIT_BANDWIDTH (по умолчанию, маска 0xbf)
- HYPERTRANSPORT_LINK1_TRANSMIT_BANDWIDTH (по умолчанию, маска 0xbf)
- HYPERTRANSPORT_LINK2_TRANSMIT_BANDWIDTH (по умолчанию, маска 0xbf)
- HYPERTRANSPORT_LINK3_TRANSMIT_BANDWIDTH (по умолчанию, маска 0xbf)
Демон oprofiled запускается и останавливается утилитой opcontrol,
периодически считывает собранные данные из аппаратных счётчиков
(/dev/oprofile/) и сохраняет их в файлах (/var/lib/oprofile/samples/current).
Журнал - /var/lib/oprofile/samples/oprofile.log (обратить внимание на количество потерь отсчётов в связи
с переполнением буфера).
opcontrol - управление демоном |
Утилита opcontrol позволяет управлять сбором данных. Требуются права суперпользователя.
Загрузка модуля и прочая инициализация:
opcontrol --init
Настройка демона:
opcontrol --setup ключи-настройки
- --vmlinux=/usr/lib/debug/lib/modules/2.6.18-164.15.1.el5/vmlinux (для профилирования ядра
требуется несжатое ядро, которое можно взять из пакетов
kernel-debuginfo и kernel-debuginfo-common (файл /usr/lib/debug/lib/modules/версия-ядра/vmlinux) -
для CentOS с http://debuginfo.centos.org/5/x86_64/)
- --no-vmlinux (профилирование ядра не требуется)
- --buffer-size=отсчётов (размер буфера ядра)
- --buffer-watershed=отсчётов (рекомендуется от 0.25 до 0.5 размера буфера)
- --cpu-buffer-size=отсчётов (буферизация отсчётов для каждого ЦП, увеличение уменьшает потери отсчётов)
)
- --event={описание-регистрируемого-события|default} (чтобы задействовать несколько счётчиков необходимо описать
несколько событий в одной строке; после изменений необходимо перезапустить сервис oprofiled;
формат описания - имя-счётчика:число-событий:маска:считать-в-ядре:считать-в-пространстве-пользователя;
не могу поставить более одного счётчика для Xeon 55xx в RHEL 5.4
("ophelp --check-events" проходит;
пересборка пользовательской части 0.9.5 не помогла - модуль ядра возвращает i386/core_2;
в /dev/oprofile только 1 счётчик)
- --separate=тип-разделения-отсчётов (список через запятую; рекомендуется lib)
- none (по умолчанию, все отсчёты, для которых счётчик адреса указывает на определённую программу, записываются в один
файл для каждой программы)
- lib (отсчёты, попавшие в динамическую библиотеку, распределяются по приложениям)
- kernel (отсчёты, попавшие в ядро и модули ядра, распределяются по приложениям; подразумевает lib;
асинхронные события (обработка прерываний) приписывается текущему процессу)
- thread (отсчёты распределяются по потокам и процессам; не стоит оставлять надолго; приходится сливать в opreport?)
- cpu (отсчёты распределяются по ЦП; приходится сливать в opreport?)
- all
- --callgraph=глубина (отслеживать дерево вызовов указанной максимальной глубины; 0 - отключить)
- --image={абсолютный-путь|all} (список через запятую; профилировать только указанные программы)
- --verbose (не советую использовать под нагрузкой)
- --kernel-range=начало,конец
Запуск демона и сбора статистики:
opcontrol --start
Запуск только демона:
opcontrol --start-daemon
Посмотреть список событий, доступных для наблюдения:
opcontrol --list-events
Посмотреть настройки:
opcontrol --status
Записать накопленную статистику (в /var/lib/oprofile):
opcontrol --dump
Остановить сбор статистики:
opcontrol --stop
Остановить сбор статистики и остановить демона:
opcontrol --shutdown
Сохранить данные текущей сессии:
opcontrol --save=имя-сессии
Сброс статистики текущей сессии (сохранённые сессии не теряются):
opcontrol --reset
Остановить демон, выгрузить модуль oprofile и размонтировать oprofilefs:
opcontrol --deinit
Конфигурационный файл, который заполняет opcontrol (т.е. при
следующем запуске параметры повторять не обязательно) - /root/.oprofile/daemonrc:
- SESSION_DIR=/var/lib/oprofile
- NR_CHOSEN=0
- SEPARATE_LIB=1
- SEPARATE_KERNEL=1
- SEPARATE_THREAD=0
- SEPARATE_CPU=0
- VMLINUX=/usr/lib/debug/lib/modules/2.6.18-128.7.1.el5/vmlinux
- IMAGE_FILTER=
- CPU_BUF_SIZE=0
- CALLGRAPH=5
- KERNEL_RANGE=ffffffff80000000,ffffffff8026f6af
- XENIMAGE=none
Запуск демона:
opcontrol --start
oprof_start из пакета oprofile-gui позволяет выбрать счётчики в графическом режиме (QT).
oparchive позволяет архивировать накопленные данные. Архив самодостаточен и может быть
использован на другом компьютере. Ключи:
- --exclude-dependent | -x (не включать данные о связанных с программой библиотеках и модулях ядра)
- --image-path | -p пути (список путей поиска для программ и модулей ядра - /lib/modules/2.6.18-164.15.1.el5/kernel/)
- --root | -r путь
- --output-directory | -o каталог
opimport конвертирует накопленные данные для их исследования на
компьютере другой архитектуры.
Интересные комбинации для AMD K10
# сбор данных о среднем времен выполнения инструкции (AMD K10):
opcontrol --setup --event=CPU_CLK_UNHALTED:300000 --event=RETIRED_INSTRUCTIONS:300000 --event=RETIRED_UOPS:300000
# выяснение используемых режимов плавающей арифметики:
opcontrol --setup --event=RETIRED_MMX_FP_INSTRUCTIONS:300000:1 \
--event=RETIRED_MMX_FP_INSTRUCTIONS:300000:2 \
--event=RETIRED_MMX_FP_INSTRUCTIONS:300000:4
# насколько хорошо кеширование L1D:
opcontrol --setup --event=DATA_CACHE_ACCESSES:300000 --event=DATA_CACHE_MISSES:300000 \
--event=DATA_CACHE_REFILLS_FROM_L2_OR_NORTHBRIDGE:300000
# насколько хорошо кеширование L1I и L2:
opcontrol --setup --event=REQUESTS_TO_L2:300000 --event=L2_CACHE_MISS:300000 --event=INSTRUCTION_CACHE_MISSES:300000
# насколько хорошо кеширование L3:
opcontrol --setup --event=READ_REQUEST_L3_CACHE:300000 --event=L3_CACHE_MISSES:300000 --event=L3_EVICTIONS:300000
# возможные проблемы, тормозящие вычисления:
opcontrol --setup --event=PIPELINE_RESTART_DUE_TO_SELF_MODIFYING_CODE:500 \
--event=MISALIGNED_ACCESSES:300000 --event=1_BIT_ECC_ERRORS:500
# проблемы декодирования команд и планирования запуска:
opcontrol --setup --event=INSTRUCTION_FETCH_STALL:300000 --event=DECODER_EMPTY:300000 --event=DISPATCH_STALLS:300000
# эффективность работы DTLB:
opcontrol --setup --event=L1_DTLB_HIT:300000 --event=L1_DTLB_MISS_AND_L2_DTLB_HIT:300000 --event=L1_DTLB_AND_L2_DTLB_MISS:300000
# эффективность работы ITLB:
opcontrol --setup --event=L1_ITLB_MISS_AND_L2_ITLB_HIT:300000 --event=L1_ITLB_MISS_AND_L2_ITLB_MISS:300000
# сбросы TLB:
opcontrol --setup --event=GLOBAL_TLB_FLUSHES:500 --event=ITLB_RELOADS:500 --event=ITLB_RELOADS_ABORTED:500
# доступ к памяти:
opcontrol --setup --event=MEMORY_REQUESTS:300000 --event=DRAM_ACCESSES:300000 --event=CPU_IO_REQUESTS_TO_MEMORY_IO:300000:0xa8
# доля команд перехода и ошибочных предсказаний
opcontrol --setup --event=RETIRED_INSTRUCTIONS:300000 \
--event=RETIRED_BRANCH_INSTRUCTIONS:300000 --event=RETIRED_MISPREDICTED_BRANCH_INSTRUCTIONS:300000
Интересные комбинации для Core2
- декодер команд ждёт данные: CYCLES_L1I_MEM_STALLED / CPU_CLK_UNHALTED.CORE
- промах ITLB: ITLB_MISS_RETIRED / INST_RETIRED.ANY
- промах L1I: L1I_MISSES / INST_RETIRED.ANY
- промах L2 при загрузке инструкций: L2_IFETCH.SELF.I_STATE / INST_RETIRED.ANY
- нагрузка на чтение из памяти: L1D_CACHE_LD.MESI / CPU_CLK_UNHALTED.CORE
- запись блокирована предыдущей записью: STORE_BLOCK.ORDER / CPU_CLK_UNHALTED.CORE
- чтение в L1D блокировано недостаткой ресурсов: LOAD_BLOCK.L1D / CPU_CLK_UNHALTED.CORE
- промахи L1D: L1D_REPL / INST_RETIRED.ANY
- промахи L2: L2_LINES_IN.SELF.ANY / INST_RETIRED.ANY
opreport - генератор отчётов |
Утилита opreport считывает собранные в /var/lib/oprofile/samples/ данные, фильтрует, сливает,
анализирует их и выводит в человеколюбивом формате. Не требуются права суперпользователя.
Необходимо задать спецификацию профиля для фильтрации (по умолчанию - пустая спецификация,
т.е. использовать все накопленные данные) и опции вывода:
- --accumulated | -a (нарастающим итогом)
- --debug-info | -g (выводить имя исходного файла и номер строки, если есть отладочная информация)
- --demangle | -D {none|smart|normal} (приводить имена функций C++ к человеческому виду)
- --callgraph | -c (выводить граф вызовов функций, если собрана необходимая информация
- --details | -d (выводить не только суммарную информацию для прошраммы/библиотеки/модуля целиком,
но и детализированную информацию для интервалов адресов)
- --exclude-dependent | -x (не включать данные о связанных с программой библиотеках и модулях ядра)
- --exclude-symbols | -e список-символов (не включать данные о перечисленных символах, требуется --symbols)
- --global-percent | -% (все процентные данные выводить относительно общей суммы)
- --image-path | -p пути (список путей поиска для программ и модулей ядра - /lib/modules/2.6.18-164.15.1.el5/kernel/)
- --root | -r путь
- --include-symbols | -i список-символов (включать данные только о перечисленных символах, требуется --symbols)
- --long-filenames | -f (выводить полные пути)
- --merge | -m {lib,cpu,tid,tgid,unitmask,all} (слить данные, собранные с ключом --separate;
tgid - по задачам, tid - по нитям)
- --no-header
- --reverse-sort | -r
- --session-dir имя-каталога (по умолчанию - /var/lib/oprofile)
- --show-address | -w (показать виртуальные адреса; требуется --symbols)
- --sort | -s {vma,sample,symbol,debug,image}
- --symbols | -l (вывести посимвольную информацию)
- --threshold | -t процентов (не выводить малозначимые данные)
- --xml | -X (в формате XML; opreport.xsd)
Спецификация профиля (фильтр отбора данных) состоит из комбинации следующих параметров через пробел:
- archive:имя-архива (см. утилиту oparchive)
- session:список-сессий (по умолчанию - current)
- session-exclude:список-сессий
- image:список-программ (можно использовать полные имена, относительные имена, шаблоны)
- image-exclude:список-программ
- lib-image:список-программ
- lib-image-exclude:список-программ
- event:имя-события
- count:количество-отсчётов
- unit-mask:маска
- cpu:список-ЦП (нумерация с нуля; требуется сбор данных с --separate=cpu)
- tgid:список-номеров-процессов (tgid - task group id; требуется сбор данных с --separate=thread)
- tid:список-номеров-потоков (требуется сбор данных с --separate=thread)
opreport позволяет сравнить 2 профиля (не забывайте пробелы и экранировку от bash):
opreport ключи общая-часть-спецификации { отличия-первого-профиля } { отличия-второго-профиля }
opannotate - дизассемблер |
opannotate создаёт размеченный (аннотированный) листинг исходного кода программы
(приложение должны быть скомпилировано с отладочной информацией - "gcc -g") и/или
листинг дизассемблера, в который добавляется информация о значении счётчиков.
Спецификация профиля задаётся аналогично команде opreport.
Ключи:
- --assembly (вывести аннотированный листинг дизассемблера)
- --base-dirs=список-каталогов (удалить указанную строку их абсолютных имён файлов с исходных кодом перед поиском)
- --demangle | -D {none|smart|normal} (приводить имена функций C++ к человеческому виду)
- --exclude-dependent | -x (не включать данные о связанных с программой библиотеках и модулях ядра)
- --exclude-file список-шаблонов
- --exclude-symbols | -e список-символов (не включать данные о перечисленных символах)
- --image-path | -p пути (список путей поиска для программ и модулей ядра - /lib/modules/2.6.18-164.15.1.el5/kernel/)
- --include-file список-шаблонов
- --include-symbols | -i список-символов (включать данные только о перечисленных символах)
- --objdump-params параметры-objdump
- --output-dir=каталог (разбить аннотированный листинг по файлам; несовместим с --assembly)
- --root | -r путь
- --search-dirs=список-каталогов (где искать исходный код)
- --source (выести аннотированный листинг исходного кода)
- --threshold | -t процентов (не выводить малозначимые данные)
Расширение OProfile для Eclipse CDT позволяет исследовать особенности поведения разрабатываемой программы,
не выходя из среды Eclipse.
|
Bog BOS: oprofile - исследование особенностей вычислительной производительности с использованием аппаратных счётчиков событий
|
Copyright © 1996-2024 Sergey E. Bogomolov; www.bog.pp.ru