Оптимизированы ли современные кэши ЦП для работы с постоянными шагами? Через темы?

Скажем, у меня большой массив и несколько потоков, читающих из массива. Каждый поток перебирает массив, выполняя скачок постоянной величины, но начинается с другого смещения. Таким образом, поток 1 может начинаться с элемента 0, затем считывать элементы 32, 64, 96 и т. Д. Но поток 2 начинается с элемента 1 и считывать элементы 33, 65, 97 и т. Д. (Имея в виду, что "элемент" может составлять больше, чем один байт или слово) Я знаю, что обычно пространственная локальность желательна для получения наилучшей производительности кеша, но я также читал, что современные процессоры имеют аппаратные средства предварительной выборки, которые ищут шаблоны в доступах, и шаг для меня выглядит как очевидная закономерность

  • Так это кеш дружественный на современной коробке или нет?
  • Что если я увеличу шаг до чего-то большего, чем строка кеша?
  • Влияет ли на ответ использование нескольких потоков (поэтому, несмотря на доступ к одной и той же памяти, они могут работать на разных ядрах с разными кэшами)?

1 ответ

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

Во-первых, кеш-память является ассоциативной по адресу. Если часть памяти адресована, "строка кэша" для этого адреса загружается в кэш. В зависимости от конструкции процессора длина может составлять 4, 8, 16 или 32 байта. (Может быть, и больше.) Это, скорее всего, будет основано на "сглаживании" аппаратных адресов; другими словами, 32-байтовая строка будет находиться на границе, которая выравнивается по адресу, делимому на 32. Ссылка на вашу память может находиться в начале, середине или конце этой строки кэша.

Как только он находится в кэше, адрес используется как "поиск" для поиска кэшированных данных.

Справочная информация поможет вам, если строка кэша достаточно велика, чтобы ссылаться на "соседний" элемент, который, как оказалось, был кэширован как часть строки кэша. Прыжки через ваш массив победят это.

Дизайн кэша сильно различается в зависимости от поставщика, линейки продуктов, цены процессора и многого другого. Идеальная оптимизация кэша будет очень труднодостижимой, если (1) вы не знаете много о машине, на которой собираетесь работать, и (2) вы действительно не заинтересованы в работе на любой другой машине.

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

Предварительная загрузка - это больше колдовство, чем наука. Извлечение памяти из данных в кеш стоит дорого, даже если она асинхронна от выполнения процессора (хотя она никогда не может быть слишком отделена от выполнения). Локальная ссылка - хорошее правило, хотя оно будет основано на аппаратной архитектуре таким образом, что это не обязательно будет соответствовать выполнению кода на микроуровне. LRU (используется в последнее время) - это распространенный метод определения того, что загружать из кэша, но удаление чего-либо из кэша, чтобы освободить место для чего-то, что в итоге не используется никогда, не является такой хорошей оптимизацией. Так что предварительная загрузка будет разумной, если не сказать больше.

РЕДАКТИРОВАТЬ: проблемы с виртуальной памятью, переключение задач и т. Д.

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

Кроме того, некоторые конструкции кэша имеют "общий" кэш, и большинство или все имеют кэш-память, относящуюся к процессору и ядру. Если кэш назначен определенному процессору или ядру и это ядро ​​меняет задачу, весь кэш, вероятно, будет очищен во избежание повреждения новым процессом. Это не включает переключение потоков, поскольку потоки выполняются в одном и том же процессе и в одном и том же адресном пространстве. Настоящая проблема здесь заключается в том, что высокая активность в других приложениях в системе может повлиять на производительность вашего кэша. Разделяемый кеш в некоторой степени облегчает эту проблему, но требует более тщательного управления, чтобы избежать повреждений.

Другие вопросы по тегам