Какой оптимален больший размер кеша блока или меньший?
Учитывая размер кэша с постоянной емкостью и ассоциативностью, для данного кода, чтобы определить среднее значение элементов массива, предпочтительнее ли будет кэш с большим размером блока?
[из комментариев]
Изучите приведенный ниже код, чтобы вычислить среднее значение массива:
total = 0;
for(j=0; j < k; j++) {
sub_total = 0; /* Nested loops to avoid overflow */
for(i=0; i < N; i++) {
sub_total += A[jN + i];
}
total += sub_total/N;
}
average = total/k;
3 ответа
Связано: в более общем случае типичных схем доступа с некоторой, но ограниченной пространственной локализацией, более крупные линии помогают до определенной точки. Эти слайды "Иерархия памяти: ассоциативно-множественный кэш" (powerpoint) Хонг Цзяна и / или Ифэн Чжу (штат Мэн) имеют график AMAT (среднее время доступа к памяти) в зависимости от размера блока, показывающего кривую, а также разбивающей ее Снижение количества пропущенных промахов по сравнению с частотой промахов (для простой модели, я думаю, для простого процессора в порядке, который сосет при сокрытии задержки памяти. Например, возможно, даже не конвейеризует несколько независимых промахов (промах при промахе))
На этих слайдах есть много хороших вещей, в том числе раздел оптимизации компилятора, в котором упоминается обмен циклами (для исправления вложенных циклов с порядком мажорных столбцов и строк), и даже блокировка кэша для большего повторного использования. Многое в Интернете - это дерьмо, но я просмотрел эти слайды, и у них есть некоторая достоверная информация о том, как спроектированы кэши и каковы компромиссы. Анализ производительности очень точен только для простых процессоров, но не для современных процессоров с неправильным порядком работы, которые могут перекрывать некоторые вычисления с задержкой пропуска кэша, поэтому более короткие пропуски отличаются от меньших более длительных пропусков.
Конкретный ответ на этот вопрос:
Таким образом, единственная рабочая нагрузка, о которой вы заботитесь - это линейный обход ваших элементов? Это делает размер строки кэша практически несущественным для производительности при условии хорошей аппаратной предварительной выборки. (Таким образом, более крупные линии означают меньшую сложность и энергопотребление при одинаковой производительности.)
При программной предварительной выборке более крупные строки означают меньшие издержки предварительной выборки (хотя в зависимости от конструкции ЦП это может не сказаться на производительности, если вы по-прежнему максимально используете пропускную способность памяти).
Без предварительной выборки больший размер строки / блока будет означать больше хитов после каждого промаха по требованию. Одиночный обход массива имеет идеальную пространственную локальность и не имеет временной локализации. (На самом деле не совсем идеальная пространственная локальность в начале / конце, если массив не выровнен по началу строки кэша и / или заканчивается в середине строки.)
Если промах должен ждать, пока вся строка не появится в кеше, прежде чем нагрузка, вызвавшая промах, может быть удовлетворена, это немного уменьшает преимущество больших блоков. (Но большая часть задержки при отсутствии кэша связана с передачей служебных сигналов и запросов, а не с ожиданием завершения пакетной передачи после того, как она уже началась.)
Больший размер блока означает меньшее количество запросов в полете с той же пропускной способностью и задержкой, а ограниченный параллелизм является реальным ограничивающим фактором пропускной способности памяти в реальных процессорах. (См. Часть этого ответа, посвященную платформам с задержкой, о пропускной способности памяти x86: многоядерные Xeon с более высокой задержкой к кэшу L3 имеют меньшую однопоточную пропускную способность, чем двух- или четырехъядерные с одинаковой тактовой частотой. Каждое ядро имеет только 10 буферы заполнения строки для отслеживания выдающихся пропусков L1, и bandwidth = concurrency / latency
.)
Если ваша обработка ошибок кэширования имеет ранний дизайн перезапуска, даже этой дополнительной задержки можно избежать. (Это очень часто, но Пол говорит, что теоретически возможно не использовать его в конструкции процессора). Нагрузка, вызвавшая промах, получает свои данные, как только прибывает. Остальная часть заполнения строки кэша происходит "в фоновом режиме", и, надеюсь, более поздние загрузки также могут быть выполнены из частично полученной строки кэша.
Критическое слово first - это связанная функция, где необходимое слово отправляется первым (для использования с ранним перезапуском), а затем пакетная передача оборачивается, чтобы передать более ранние слова блока. В этом случае критическое слово всегда будет первым словом, поэтому никакой специальной аппаратной поддержки после раннего перезапуска не требуется. (Слайды U. Maine, которые я связал выше, упоминают вначале ранний перезапуск / критическое слово и указывают, что это уменьшает штраф за промах для больших строк кэша.)
Неиспользуемый исполнительный ЦП (или конвейерная обработка программного обеспечения в обычном ЦП) может дать вам эквивалент предварительной выборки HW при наличии нескольких невыполненных запросов одновременно. Если процессор "видит" нагрузки на другую строку кэша, в то время как пропуск текущей строки кэша все еще остается невыполненным, пропуски по требованию могут быть переданы по конвейеру, снова скрывая некоторую разницу между большими или меньшими строками.
Если линии слишком малы, вы столкнетесь с ограничением количества пропущенных пропусков по разным линиям, которые может отслеживать ваш L1D. С большими линиями или меньшими неупорядоченными окнами может возникнуть некоторая "слабость", когда нет ожидающего запроса на следующую строку кэша, поэтому вы не используете максимальную пропускную способность. И вы платите за это пузырями в конвейере, когда добираетесь до конца строки кэша, а начало следующей строки еще не наступило, потому что она началась слишком поздно (в то время как исполнительные блоки ALU использовали данные из слишком близко к конец текущей строки кэша.)
Связанный: эти слайды не говорят много о компромиссе между большими и меньшими линиями, но выглядят довольно хорошо.
Упрощенный ответ заключается в том, что предпочтительнее использовать более крупные блоки кеша, поскольку рабочая нагрузка не имеет временной локализации (данных) (повторное использование данных отсутствует), идеальной пространственной локализации (исключая потенциально неадекватное выравнивание массива для первого блока и недостаточный размер массива для последний блок, каждая часть каждого блока данных будет использоваться), и один поток доступа (нет возможности пропустить конфликт).
Более детальный ответ будет учитывать размер и выравнивание массива (доля первого и последнего блоков кэша, которые будут неиспользованы, и какая часть времени передачи памяти, которая представляет; для массива 1 ГиБ даже 4 блока по КиБ будут потрачены впустую менее 0,0008% пропускной способности памяти), способность системы сначала использовать критическое слово (если массив имеет скромный размер и не поддерживается раннее использование данных, поскольку они становятся доступными, а не ожидают, пока весь блок заполнение, то накладные расходы при запуске устранят большую часть преимуществ предварительной выборки более крупных блоков кэша), использование предварительной выборки (программная или аппаратная предварительная выборка уменьшает преимущество больших блоков кэша, и эта рабочая нагрузка чрезвычайно удобна для предварительной выборки), конфигурация системы памяти (например, использование DRAM с политикой контроллера немедленного закрытия страницы увеличило бы преимущество больших блоков кэша, потому что каждый доступ включал бы активацию строки и закрытие строки, часто к одной и той же DRAM банк, предотвращающий перекрытие задержки), используется ли один и тот же размер блока для обращений к инструкциям и таблицам страниц и совместно используют ли эти доступы кэш-память (доступы к командам обеспечивают второй "поток", который может вносить пропуски конфликтов); при совместном кэшировании двухуровневой иерархической таблицы страниц TLB пропустил бы доступ к двум блокам кэша), используется ли простой способ прогнозирования (больший блок увеличил бы точность прогнозирования, сократив издержки при неправильном прогнозировании), и, возможно, другие факторы.
Из вашего примера кода мы не можем сказать ни того, ни другого, если аппаратный предварительный выборщик может поддерживать поток памяти при максимальной пропускной способности памяти.
В сценарии произвольного доступа предпочтительнее использовать более короткую строку кэша, так как вам не нужно заполнять всю строку. Но общий объем кешируемой памяти уменьшится, так как вам потребуется больше цепей для тегов и потенциально больше времени для сравнения.
Поэтому необходимо пойти на компромисс: Intel выбрала 64 байта на строку (и получает 2 строки), остальные выбрали 32 байта на строку.