Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

На главную -> MyLDP -> Тематический каталог -> Аппаратное обеспечение

Что каждый программист должен знать о памяти.

Часть 9: Приложения и библиография


Назад Оглавление Вперед

10.3 Запуск профилирования

Когда начинается анализ тела кода, то, несомненно, нужно начинать искать в программе те места, на которые затрачивается больше всего времени. Этот код, безусловно, должны быть оптимизирован настолько, насколько это окажется возможным. Но что происходит дальше? На что в программе излишне тратится время? На этот вопрос ответить не так просто.

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

Во многих ситуациях полезно взглянуть на отношения двух событий. Например, измерение количества ошибочных ветвлений в функции может оказаться бессмысленным в случае, если не измерено, как часто выполнялась функция. Да, абсолютное значение важно для выполнения программы. Отношение ошибочных ветвлений на один вызов более важно для качества кода функции. В руководстве по оптимизации Intel для архитектуры x86 и x86-64 [intelopt] описаны относительные значения, которые следует измерять (Приложение B.7 в упомянутом документе для событий Core 2).Ниже описываются некоторые из отношений, относящиеся к управлению памятью.

Instruction Fetch Stall
(Простои при выборке инструкций)

CYCLES_L1I_MEM_STALLED/ CPU_CLK_UNHALTED.CORE

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

ITLB Miss Rate
(Показатель промахов в ITLB)

ITLB_MISS_RETIRED/ INST_RETIRED.ANY

Промахи ITLB на одну инструкцию. Если этот показатель высокий, то это значит, что код распределен по очень большому количеству страниц.

L1I Miss Rate
(Показатель промахов в L1I)

L1I_MISSES/ INST_RETIRED.ANY

Промахи L1i на одну инструкцию. Поток выполнения команд непредсказуем или размер кода слишком большой. В первом случае может помочь отказ от косвенных переходов. В последнем случае может помочь переупорядочивание блоков или отказ от использования inline - инструкций.

L2 Instruction Miss Rate
(Показатель промахов в L2)

L2_IFETCH.SELF.I_STATE/ INST_RETIRED.ANY

Промахи L2 кода программы на одну инструкцию. Любое значение, большее нуля, указывает на локальные проблемы с кодом, что хуже, чем промахи L1i.

Load Rate
(Показатель загрузки)

L1D_CACHE_LD.MESI/ CPU_CLK_UNHALTED.CORE

Число операций, читаемых за один цикл. Ядро Core 2 может обслуживать одну операцию загрузки. Высокий показатель означает, что выполнение связано с чтением данных из памяти.

Store Order Block
(Блокировка, связанная с порядком запоминания)

STORE_BLOCK.ORDER/ CPU_CLK_UNHALTED.CORE

Показывает, блокируется ли память из-за того, что что-то запоминалось в памяти ранее; из-за этого возникают промахи кэш-памяти.

L1d Rate Blocking Loads
(Блокирование загрузки показателя L1d)

LOAD_BLOCK.L1D/ CPU_CLK_UNHALTED.CORE

Загрузка из L1d блокирована из-за отсутствия ресурсов. Обычно это означает, что к L1d осуществляется слишком много параллельных обращений.

L1d Miss Rate
(Показатель промахов в L1d)

L1D_REPL/ INST_RETIRED.ANY

Промахи L1d на одну инструкцию. Высокий показатель означает, что предварительная загрузка неэффективна и что кэш-память L2 используется слишком часто.

L2 Data Miss Rate
(Показатель промахов данных в L2)

L2_LINES_IN.SELF.ANY/ INST_RETIRED.ANY

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

L2 Demand Miss Rate
(Показатель промахов при доступе в L2 по требованию)

L2_LINES_IN.SELF.DEMAND/ INST_RETIRED.ANY

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

Useful NTA Prefetch Rate
(Показатель полезной предварительной загрузки данных NTA)

SSE_PRE_MISS.NTA/ SSS_PRE_EXEC.NTA

Отношение полезной предварительной загрузки данных NTA (многократно используемых данных) к общему количеству предварительно загружаемых данных NTA. Маленькое значение означает, что большая часть данных уже находятся в кэш-памяти. Это отношение также можно вычислить для других видов предварительных загрузок.

Late NTA Prefetch Rate
(Показатель предварительной загрузки данных NTA с опозданием)

LOAD_HIT_PRE/ SSS_PRE_EXEC.NTA

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

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

Эти показатели относятся сразу ко всей программе целиком - на уровне исполняемого кода / DSO и даже на функциональном уровне. Чем глубже анализировать программу, тем больше в полученном значении будет ошибочных составляющих./p>

Для понимания смысла эти показателей нужно опираться на базовые значения. Это не так просто, как может показаться. Различный программный код имеет различные характеристические значения и значения показателей, которые могут считаться плохими для одной программы и могут быть нормальными для другой программы.


Назад Оглавление Вперед