Что касается процессоров Intel, нет. Это упоминается в руководстве по оптимизации Intel, раздел 7.3.3:
PREFETCH может обеспечить большую производительность, чем предварительная загрузка, потому что:
- Не имеет регистра назначения, он только обновляет строки кэша.
- Не завершает собственное выполнение, если это может вызвать ошибку.
- Не останавливает нормальное отставание инструкции.
- Не влияет на функциональное поведение программы.
- Нет доступа к разделенным строкам кэша.
- Не вызывает исключений, кроме случаев, когда используется префикс LOCK. Префикс LOCK не является допустимым префиксом для использования с PREFETCH.
- Не завершает собственное выполнение, если это может вызвать ошибку.
Преимущества PREFETCH перед инструкциями предварительной загрузки зависят от процессора. Это может измениться в будущем.
Кроме того, в разделе 3.7.1 говорится:
Программные операции PREFETCH работают так же, как и загрузка из памяти
операции, со следующими исключениями:
- Инструкции PREFETCH программного обеспечения удаляются после завершения преобразования виртуального адреса в физический.
- Если для предварительной выборки данных требуется исключение, например сбой страницы, то команда предварительной выборки программного обеспечения удаляется без
предварительная выборка данных.
Я экспериментально проверил обе эти точки на Хэсвелле и Бродвелле.
Все пропускают TLB: все инструкции предварительной выборки пропускают все кеши MMU и данных, но страница находится в основной памяти (без мелких или серьезных сбоев страницы).
Все обращения к TLB. Все команды предварительной выборки обращаются к L1 TLB и кэшу данных.
Ошибка на разных страницах: все инструкции предварительной выборки пропускают все кэши MMU и данных, а дескриптор страницы приводит к ошибке страницы. Каждая инструкция предварительной выборки обращается к отдельной виртуальной странице.
Ошибка на той же странице: все инструкции предварительной выборки пропускают все кэши MMU и данных, а дескриптор страницы приводит к ошибке страницы. Каждая инструкция предварительной выборки обращается к одной и той же виртуальной странице.
Для графика Бродвелла показаны результаты как для PREFETCH0
, так и для PREFETCHW
. PREFETCHW
не поддерживается в Haswell. Частота на Haswell и Broadwell была установлена на 3,4 ГГц и 1,7 ГГц, соответственно, и я использовал драйвер масштабирования мощности intel_pstate для обоих. Все аппаратные prefetchers были включены. Обратите внимание, что задержка PREFETCHW
на сбое страницы не зависит от того, доступна ли запись на целевой странице. Страница только для чтения приводит к ошибке, которая имеет то же влияние, что и ошибка по любой другой причине. Кроме того, в моих экспериментах рассматривается только случай, когда ни у одного ядра нет копии строки кэша.
Ожидается пропускная способность 1 цикла из-за цепочки зависимостей 1c:
loop:
prefetcht0 (%rax)
add $0x1000,%rax
cmp %rbx,%rax
jne loop
В Broadwell дело "ошибка на одной странице" выглядит несколько медленнее, чем дело "ошибка на разных страницах". Это в отличие от Haswell. Я не знаю почему. Вероятно, это зависит от уровня структуры подкачки, которая содержит недопустимую запись, на которой в основном обходчик страниц обнаруживает ошибку страницы. Это зависит от ОС.
Я думаю, что причина, по которой инструкции предварительной выборки не могут немедленно удалиться из-за пропуска TLB, заключается в том, что у единицы загрузки нет логики после вывода из строя, как у единицы хранения. Идея здесь заключается в том, что, поскольку, скорее всего, будет доступ по требованию к странице, следующей за предварительной выборкой (что, вероятно, объясняет, почему предварительная выборка существует), в любом случае произойдет остановка из-за пропуска TLB либо при доступе по запросу, либо при предварительной выборке. Возможно, остановка предварительной выборки лучше, особенно если инструкции, следующие непосредственно за предварительной выборкой, не обращаются к той же странице.
Кроме того, Я экспериментально проверил, что инструкции предварительной выборки могут быть отменены до завершения операции предварительной выборки , поместив LFENCE
после инструкции предварительной выборки и наблюдая, что время на команду предварительной выборки увеличивается незначительно (стоимость ограждения) по сравнению с использованием загрузки вместо предварительной выборки.
Инструкции предварительной выборки программного обеспечения на процессорах Xeon Phi выполняются так же, как на Haswell / Broadwell 1 , но прочтите также раздел об Itanium ниже.
В разделе 7.3.3 также сказано:
В некоторых случаях PREFETCH не выполняет предварительную выборку данных.
К ним относятся:
- В более старых микроархитектурах PREFETCH, вызывающий промах Data Transfer Lookaside Buffer (DTLB), будет пропущен. В процессорах на основе
Nehalem, Westmere, Sandy Bridge и более новые микроархитектуры, Intel
Процессоры Core 2 и Intel Atom, PREFETCH, вызывающие DTLB
Мисс может быть найден через границы страницы.
- Доступ к указанному адресу, который вызывает ошибку / исключение.
- PREFETCH предназначается для области без кэширования памяти (например, USWC и UC).
- Если в подсистеме памяти заканчиваются буферы запросов между кешем первого уровня и кешем второго уровня.
- Используется префикс LOCK. Это вызывает недопустимое исключение кода операции.
Второй пункт был проверен экспериментально на Хэсвелле, Бродвелле и Скайлэйке. Мой код не способен обнаружить четвертую точку, в которой говорится, что запросы на предварительную выборку могут быть отброшены при исчерпании LFB. Результаты AMD , похоже, указывают на то, что AMD также отбрасывает запросы на предварительную выборку. Но время на доступ к AMD все еще намного меньше, чем на Intel. Я думаю, что AMD отбрасывает запросы предварительной выборки, когда заполненные буферы заполнения TLB заполнены, в то время как Intel отбрасывает их, когда заполненные буферы заполнения L1D. Мой код никогда не переполняет буферы заполнения L1D, что объясняет результаты AMD и Intel.
Первый пункт говорит о том, что на микроархитектурах Core2 и Atom и более поздних программные предварительные выборки не сбрасываются при промахе TLB. В соответствии с более старой версией руководства по оптимизации, процессоры Pentium 4 с моделью № 3 и выше также не сбрасывают предварительную выборку программного обеспечения при пропадании TLB. Это также может иметь место в микроархитектуре Intel Core и (некоторых) процессорах Pentium M (я не смог найти источник Intel относительно этих процессоров). Процессоры Pentium III и Pentium 4 с номером модели, меньшим 3, определенно отбрасывают программные предварительные выборки при промахе TLB. Процессоры, предшествующие Pentium III, не поддерживают инструкции предварительной загрузки программного обеспечения.
Предварительно извлеченные мопы отправляются на порт 2 или 3 и распределяются в буферах загрузки. Предварительная загрузка в одну и ту же строку кэша не объединяется. То есть каждый моп получит свой собственный буфер загрузки. Я думаю (но я не проверял экспериментально), что записи ROB выделены для предварительных выборок. Просто ROB никогда не останавливается при предварительном извлечении мопов, если они отправлены в порт загрузки.
Сам запрос предварительной выборки (отправляемый на L1d или внешние уровни кэша) - это не то, что uop предварительной выборки должен ждать, пока он не будет помечен как завершенный в ROB и готов к удалению, в отличие от обычной загрузки.
Существует интересный патент 2011 , в котором обсуждается усовершенствование предварительной выборки программного обеспечения на процессорах Itanium 2 . В нем упоминается, что предыдущие процессоры Itanium должны были зависнуть, когда программная предварительная выборка пропустила TLB, потому что они были разработаны, чтобы не отбрасывать какие-либо запросы программной предварительной выборки, и более поздние инструкции не могли проходить мимо него, потому что они были процессорами по порядку. Патент предложил конструкцию, которая позволяет программным запросам предварительной выборки выполнять неупорядоченно по отношению к более поздним инструкциям, не отбрасывая их. Это делается путем добавления очереди предварительной выборки данных (DPQ), которая используется для постановки в очередь запросов предварительной выборки программного обеспечения, которые пропускают TLB. Предварительная выборка в DPQ затем повторно выдается после завершения обхода таблицы страниц оборудования. Кроме того, добавлено несколько обходчиков таблиц аппаратных страниц, которые потенциально позволяют выполнять последующие обращения по требованию, даже если они пропускают TLB. Однако, если DPQ заполняется инструкциями предварительной выборки, конвейер останавливается при следующей инструкции предварительной выборки. Также, согласно патенту, запросы на предварительную выборку программного обеспечения не сбрасываются даже при ошибках страницы. Это в отличие от больших ядер и Xeon Phi. В патенте также рассматриваются аппаратные устройства предварительной выборки, реализованные в Itanium.
В вышестоящих микроархитектурах с большой загрузкой буфер загрузки, естественно, играет роль DPQ. Я не знаю, есть ли у Xeon Phi такая структура.
В разделе 5.6 руководства по оптимизации AMD говорится следующее:
На инструкции предварительной выборки могут влиять ложные зависимости от
магазины. Если есть магазин по адресу, который соответствует запросу, то
запрос (инструкция предварительной выборки) может быть заблокирован до тех пор, пока
записано в кеш. Поэтому код должен предварительно выбирать данные, которые
находится на расстоянии не менее 64 байт от данных любого окружающего магазина
адрес.
Мне было любопытно проверить это на процессорах Intel (на Haswell), поставив две инструкции предварительной выборки и одну инструкцию сохранения (за которыми следует фиктивная add rax, rax
), и я заметил следующее:
UOPS_RETIRED.STALL_CYCLES
значительно больше, чем число циклов ядра, что не имеет смысла.
- Общее количество мопов, отправленных на порты 2 и 3, примерно на 16% выше, чем должно быть. Это указывает на то, что предварительная выборка выполняется повторно.
RESOURCE_STALLS.ANY
сообщает, что в основном нет киосков. Это отличается от случая, когда есть две инструкции предварительной выборки, за которыми следуют две фиктивные инструкции ALU (конвейер останавливается в буферах загрузки).
Однако я наблюдал эти эффекты только в том случае, если хранилище находится на той же странице 4K, что и инструкции предварительной выборки. Если хранилище находится на другой странице, код работает аналогично коду с двумя фиктивными ALU. Похоже, что магазины взаимодействуют с инструкциями предварительной выборки на процессорах Intel.
(1) Но они по-разному взаимодействуют с аппаратными устройствами предварительной выборки. Однако это эффект после выхода на пенсию.
(2) Itanium - это семейство процессоров IA-64, поэтому он не совсем подходит для вопроса.