Повлияет ли большой двоичный файл с частями кода, которые не выполняются в данный момент, на использование памяти ЦП уровня 2?

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


person j riv    schedule 11.01.2011    source источник


Ответы (1)


Правда несколько сложнее, я постараюсь вам ее обрисовать.

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

  1. Prefetcher, по одному на каждое ядро ​​(без задержки)
  2. Кэш L1, один или два (комбинированный или код и данные, 2 * 64 КБ на AMD K10) для каждого ядра (задержка, скажем, три клика)
  3. Кэш L2, по одному (512 КБ на AMD K10) на каждое ядро ​​(задержка, скажем, 10)
  4. Кэш L3, один (ncores*1 МБ на AMD K10) на процессор, используемый всеми ядрами (скажем, задержка 30)
  5. Системная оперативная память, по одной на систему, используемую всеми процессорами (задержка, скажем, 100)
  6. Синхронизация (или блокировка шины), один метод на систему, используемый всеми устройствами управления шиной (задержка не менее 300 циклов до 1 мкс, если старая карта PCI использует все 32 доступных такта при управлении шиной с тактовой частотой 33 МГц - на Процессор 3 ГГц, что означает 3000 тактовых циклов)

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

Я использую синхронизацию как уровень памяти, потому что иногда вам нужно синхронизировать и память, а это стоит времени.

Язык, который вы используете, будет иметь большое влияние на производительность. Программа, написанная на C, C++ или ForTran, будет меньше по размеру и будет выполняться быстрее, чем интерпретируемая программа, такая как Basic, C# и Java. C и Fortran также дадут вам лучший контроль при организации ваших областей данных и программном доступе к ним. Некоторые функции в объектно-ориентированных языках (C++, C# и Java), такие как инкапсуляция и использование стандартных классов, приведут к созданию большего объема кода.

То, как написан код, также оказывает большое влияние на производительность, хотя некоторые несведущие люди скажут, что в наши дни компиляторы настолько хороши, что нет необходимости писать хороший исходный код. Отличный код будет означать отличную производительность, а Garbage In всегда приведет к Garbage Out.

В контексте вашего вопроса маленькое написание обычно лучше для производительности, чем безразличие. Если вы привыкли кодировать эффективно (маленький/быстрый код), то вы будете делать это независимо от того, пишете ли вы редко или часто используемые последовательности.

Кэш, скорее всего, не будет загружать всю вашу программу (хотя это может быть), а скорее многочисленные 32- или 64-байтовые фрагменты («кэш-строки») данных, извлеченных даже из 32- или 64-байтовых адресов в вашем коде. Чем больше информации в одном из этих фрагментов используется, тем дольше он будет удерживать строку кэша, в которой он находится. Если ядру нужен один фрагмент, которого нет в L1, он будет искать его на всем пути до ОЗУ, если это необходимо, и подвергаясь штрафным часам. циклы при этом.

Таким образом, небольшие, компактные и встроенные последовательности кода будут выполняться быстрее, потому что они меньше влияют на кеш. Код, который делает много обращений к другим областям кода, будет иметь большее влияние на кеш, как и код с неоптимизированными переходами. Деления чрезвычайно вредны, но только для выполнения рассматриваемого ядра. Судя по всему, AMD справляется с ними намного лучше, чем Intel (http://gmplib.org/~tege/x86-timing.pdf).

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

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

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

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

person Olof Forshell    schedule 03.03.2011