Библиотека сайта rus-linux.net
Что каждый программист должен знать о памяти.
Часть 9: Приложения и библиография
Назад | Оглавление | Вперед |
10.3 Запуск профилирования
Когда начинается анализ тела кода, то, несомненно, нужно начинать искать в программе те места, на которые затрачивается больше всего времени. Этот код, безусловно, должны быть оптимизирован настолько, насколько это окажется возможным. Но что происходит дальше? На что в программе излишне тратится время? На этот вопрос ответить не так просто.
Одна из проблем в этой ситуации в том, что абсолютные значения, на самом деле, ни о чем не говорят. На один циклов в программе может быть затрачена большая часть времени, и это будет нормально. Однако, возможных причин высокой загрузки процессора много. Но, обычно ситуация такова, что процессор более или менее равномерно используется во всей программе. В этом случае, абсолютные значения указывают на множество мест, из-за чего от них пользы мало.
Во многих ситуациях полезно взглянуть на отношения двух событий. Например, измерение количества ошибочных ветвлений в функции может оказаться бессмысленным в случае, если не измерено, как часто выполнялась функция. Да, абсолютное значение важно для выполнения программы. Отношение ошибочных ветвлений на один вызов более важно для качества кода функции. В руководстве по оптимизации Intel для архитектуры x86 и x86-64 [intelopt] описаны относительные значения, которые следует измерять (Приложение B.7 в упомянутом документе для событий Core 2).Ниже описываются некоторые из отношений, относящиеся к управлению памятью.
Instruction Fetch Stall |
| Отношение числа циклов, в течение которых декодер инструкций ждет новых данных из-за промахов в ITLB (буфер ассоциативной трансляции инструкций). |
ITLB Miss Rate |
| Промахи ITLB на одну инструкцию. Если этот показатель высокий, то это значит, что код распределен по очень большому количеству страниц. |
L1I Miss Rate |
| Промахи L1i на одну инструкцию. Поток выполнения команд непредсказуем или размер кода слишком большой. В первом случае может помочь отказ от косвенных переходов. В последнем случае может помочь переупорядочивание блоков или отказ от использования inline - инструкций. |
L2 Instruction Miss Rate |
| Промахи L2 кода программы на одну инструкцию. Любое значение, большее нуля, указывает на локальные проблемы с кодом, что хуже, чем промахи L1i. |
Load Rate |
| Число операций, читаемых за один цикл. Ядро Core 2 может обслуживать одну операцию загрузки. Высокий показатель означает, что выполнение связано с чтением данных из памяти. |
Store Order Block |
| Показывает, блокируется ли память из-за того, что что-то запоминалось в памяти ранее; из-за этого возникают промахи кэш-памяти. |
L1d Rate Blocking Loads |
| Загрузка из L1d блокирована из-за отсутствия ресурсов. Обычно это означает, что к L1d осуществляется слишком много параллельных обращений. |
L1d Miss Rate |
| Промахи L1d на одну инструкцию. Высокий показатель означает, что предварительная загрузка неэффективна и что кэш-память L2 используется слишком часто. |
L2 Data Miss Rate |
| Промахи L2 для данных на одну инструкцию. Если значение существенно больше нуля, то аппаратная и программная предварительные загрузки неэффективны. Процессору требуется большая (или более ранняя) помощь при использовании предварительной программной загрузки. |
L2 Demand Miss Rate |
| Промахи L2 для данных на одну инструкцию, при которых аппаратная предварительная загрузка вообще не используется. Это означает, что предварительная загрузка даже не начиналась. |
Useful NTA Prefetch Rate |
| Отношение полезной предварительной загрузки данных NTA (многократно используемых данных) к общему количеству предварительно загружаемых данных NTA. Маленькое значение означает, что большая часть данных уже находятся в кэш-памяти. Это отношение также можно вычислить для других видов предварительных загрузок. |
Late NTA Prefetch Rate |
| Отношение запросов данных, загружаемых в текущий момент с помощью предварительной загрузки, к общему числу всех предварительных загрузок данных NTA. Высокий показатель указывает, что инструкции предварительной программной загрузки выдаются слишком поздно. Это отношение также можно вычислить для других видов предварительных загрузок. |
Для всех этих показателей программа должна запускаться вместе с oprofile, причем для последней нужно указать, что дожны измеряться оба необходимых события. Это гарантирует, что значения двух счетчиков можно будет сравнивать. Прежде, чем выполнять деление, нужно убедиться, что в результате не возникнет переполнения. Самый простой способ, позволяющий избежать этого, состоит в домножении каждого из значений так, чтобы переполнение не возникало.
Эти показатели относятся сразу ко всей программе целиком - на уровне исполняемого кода / DSO и даже на функциональном уровне. Чем глубже анализировать программу, тем больше в полученном значении будет ошибочных составляющих./p>
Для понимания смысла эти показателей нужно опираться на базовые значения. Это не так просто, как может показаться. Различный программный код имеет различные характеристические значения и значения показателей, которые могут считаться плохими для одной программы и могут быть нормальными для другой программы.
Назад | Оглавление | Вперед |