Создание 64-байтового чтения PCIe TLP из процессора x86

При записи данных на устройство PCIe можно использовать сопоставление с объединением записи, чтобы указать ЦП, что он должен генерировать 64-байтовые TLP для устройства.

Можно ли сделать что-то подобное для чтения? Как-то намекнуть процессору на чтение целой строки кэша или большего буфера вместо чтения по одному слову за раз?


person haggai_e    schedule 19.08.2018    source источник


Ответы (2)


У Intel есть технический документ по копированию из видеопамяти. в основную память; это должно быть похоже, но намного проще (потому что данные умещаются в 2 или 4 векторных регистрах).

Он говорит, что загрузка NT будет извлекать целую строку кэша данных из памяти WC в LFB:

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

Используйте AVX2 _ 1_ или 128-битная версия SSE4.1 / AVX1.

Буферы заполнения - это ограниченный ресурс, поэтому вы определенно хотите, чтобы компилятор сгенерировал asm, который выполняет две выровненные загрузки 64-байтовой строки кэша последовательно, затем сохраняя в обычной памяти.

Если вы обрабатываете более одного 64-байтового блока за раз, см. Технический документ Intel, в котором есть предложение по использованию небольшого буфера отказов, который остается горячим в L1d, чтобы избежать смешивания хранилищ в DRAM с загрузками NT. (Вытеснения L1d в DRAM, как и хранилища NT, также требуют буферов заполнения строк, LFB).


Обратите внимание, что _ 2_ бесполезен вообще для типов памяти, отличных от WC. Подсказка NT игнорируется на текущем оборудовании, но в любом случае требует дополнительной нагрузки ALU по сравнению с обычной нагрузкой. Есть prefetchnta, но это совсем другой зверь.

person Peter Cordes    schedule 19.08.2018
comment
Загрузки NT могут использовать буферы, отличные от LFB. См .: Невременные нагрузки и предварительная выборка оборудования , они работают вместе?. - person Hadi Brais; 20.08.2018

Корпорация Intel опубликовала технический документ о том, как выполнять передачи PCIe 64B: Как реализовать пакетную передачу данных PCIe * 64 байт на архитектуре Intel®.

Принципы:

  1. Сопоставьте регион как WC.
  2. Используйте следующий код для записи 64B

    _mm256_store_si256(pcie_memory_address, ymm0);
    _mm256_store_si256(pcie_memory_address+32, ymm1);
    _mm_mfence();
    

Где _mm256_store_si256 является внутренним элементом (v)movdqa, а mfence используется для заказа магазинов с более новыми и очистить буфер WC.


Что касается моего ограниченного понимания части WC подсистемы кеширования, есть ряд предположений:

  1. # P6 #
    # P7 #
    # P8 #
  2. Тип кэша WC гарантирует, что ядро ​​записывает пакетную транзакцию, но uncore также должен иметь возможность обрабатывать эту транзакцию в целом.
    В частности, после субтрактивного декодирования корневой комплекс должен иметь возможность обрабатывать ее как транзакцию 64B .
    Из того же сообщения на форуме выше, кажется, что uncore может объединить последовательные записи WC в один TLP, но играет с порядком записи (например, меняя местами два _mm256_store_si256 или оставляя дыру для размеров меньше 64B) может выпасть из возможностей Root Complex.

person Margaret Bloom    schedule 19.08.2018
comment
OP говорит, что они уже знают, как выполнять пакетную запись. Тем не менее, это выглядит как полезный сборник, позволяющий избежать ошибок. Но вы уверены, что вам действительно нужен mfence? Это довольно медленно; Разве sfence не должно быть достаточно для заказа хранилищ в памяти WC с обычными хранилищами? Вам понадобится только mfence (или операция locked, которая не блокирует OoO exec, просто переупорядочивает память), чтобы убедиться, что сохранение произошло до чтения с устройства. Но см. Имеет ли lock xchg такое же поведение, что и mfence?: загрузка NT из WC может быть одним из случаев, когда есть различие. - person Peter Cordes; 19.08.2018
comment
@PeterCordes Да, думаю, sfence будет достаточно. Я не уверен, почему Intel использует mfence. Кстати, что я считаю более ценным в своем ответе, так это связанный документ. То, что ядро ​​выполняет пакетную запись, не означает, что корневой комплекс будет передавать TLP размером 64 байт. Аааа ... вы правы, про прочитанную часть забыл: D Я доработаю этот ответ, как только у меня появится свободное время. - person Margaret Bloom; 20.08.2018
comment
mfence будет следить за тем, чтобы последующие загрузки не конкурировали за заполнение буферов. Возможно, это зависит от окружающего кода, полезно или вредно mfence. - person Peter Cordes; 20.08.2018
comment
Что, если это код модуля ядра, в котором нельзя использовать встроенные функции? - person Alexis; 17.03.2020
comment
@Alexis_FR_JP Вероятно, ядро ​​имеет свои собственные функции или некоторую встроенную сборку, охраняемую соответствующим определением. Попробуйте поискать имя инструкции в исходном коде дерева ядра, что-то должно выскочить. - person Margaret Bloom; 17.03.2020
comment
Роджер, для пространства ядра: stackoverflow.com/q/60699914/4748326 - person Alexis; 17.03.2020