Что будет использоваться для обмена данными между потоками, выполняющимися на одном ядре с HT?

Технология Hyper-Threading - это форма технологии одновременной многопоточности, представленная Intel.

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

В процессоре Intel с Hyper-Threading одно CPU-Core (с несколькими ALU) может выполнять инструкции из 2 потоков в одно и то же время. И оба общих потока: хранилище-буфер, кеши L1/L2 и системная шина.

Но если два потока выполняются одновременно на одном Ядре, поток-1 сохраняет атомарное значение, а поток-2 загружает это значение, что будет использоваться для этого обмена: общий буфер хранилища, общий кэш L1/L2 или как обычный кэш L3?

Что произойдет, если оба потока будут из одного и того же процесса (одно и то же виртуальное адресное пространство) и из двух разных процессов (другое виртуальное адресное пространство)?

Процессор Intel Sandy Bridge - кеш L1:

  • 32 КБ - размер кеша
  • 64 B - размер строки кэша
  • 512 - строки (512 = 32 КБ / 64 В)
  • 8-полосная
  • 64 - количество наборов путей (64 = 512 линий / 8-способ)
  • 6 бит [11:6] - виртуального адреса (индекса) определяет номер текущего набора (это тег)
  • 4 K - каждый одинаковый (виртуальный адрес / 4 K) конкурирует за один и тот же набор (32 КБ / 8-полосная)
  • младшие 12 битов - значимы для определения текущего номера набора

  • 4 КБ - стандартный размер страницы

  • младшие 12 битов - одинаковые в виртуальных и физических адресах для каждого адреса

1 ответ

Решение

Я думаю, вы получите туда-обратно до L1. (Не то же самое, что store-> forward forwarding в одном потоке, что даже быстрее.)

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

Обновление: см. Этот раздел вопросов и ответов для некоторого экспериментального тестирования пропускной способности и задержки.


Хранилище должно завершить работу в потоке записи, а затем зафиксировать его в L1 из буфера / очереди хранилища через некоторое время после этого. В этот момент он будет виден другому потоку, и загрузка по этому адресу из любого потока должна ударить в L1. Перед этим другой поток должен получить удар L1 со старыми данными, а поток хранения должен получить сохраненные данные через store-> forward forwarding.

Данные хранилища поступают в буфер хранилища, когда выполняется store uop, но они не могут зафиксировать L1 до тех пор, пока не станет известно, что они не являются спекулятивными, то есть удаляются. Но буфер магазина также не связывает удаление из ROB (буфер ReOrder в ядре не в порядке) с обязательством к L1, что отлично подходит для магазинов, которые пропускают кеш. Ядро вышедшего из строя может продолжать работать, пока буфер хранилища не заполнится.


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

Атомарная операция чтения-изменения-записи должна сделать свое хранилище глобально видимым (зафиксировать в L1) как часть своего выполнения, иначе оно не будет атомарным. Пока данные не пересекают границу между строками кэша, они могут просто заблокировать эту строку кэша. (AFAIK, именно так процессоры обычно реализуют атомарные операции RMW, такие как lock add [mem], 1 или же lock cmpxchg [mem], rax.)

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

Я подозреваю, что два гиперпотока делают атомарные приращения к общему счетчику (или любому другому lock операция, как xchg [mem], eax) достигнет примерно той же пропускной способности, что и один поток. Это намного выше, чем для двух потоков, работающих на отдельных физических ядрах, где строка кэша должна проходить между кэшами L1 двух ядер (через L3).

movNT (Временные) слабо упорядоченные хранилища обходят кеш и помещают свои данные в буфер заполнения строк. Они также высвобождают строку из L1, если она была горячей в кеше для начала. Возможно, им придется удалиться до того, как данные попадут в буфер заполнения, поэтому загрузка из другого потока, вероятно, вообще не увидит его, пока не войдет в буфер заполнения. Тогда, вероятно, это то же самое, что и хранилище movnt, за которым следует загрузка внутри одного потока. (т. е. туда и обратно в DRAM, несколько сотен циклов задержки). Не используйте хранилища NT для небольшого фрагмента данных, который, как вы ожидаете, будет сразу же прочитан другим потоком.


Хиты L1 возможны из-за того, что процессоры Intel совместно используют кэш L1. Корпорация Intel использует практически индексированные, физически помеченные (VIPT) кэши L1 в большинстве (всех?) Своих разработок. (например, семейство Sandybridge.) Но так как биты индекса (которые выбирают набор из 8 тегов) находятся ниже смещения страницы, он ведет себя точно так же, как кэш PIPT (воспринимайте его как преобразование младших 12 битов в отсутствие op), но с преимуществом скорости кеша VIPT: он может извлекать теги из набора параллельно с поиском TLB для преобразования старших битов. См. "L1 также использует трюки скорости, которые не сработали бы, если бы он был больше" в этом ответе.

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

Предыдущая версия этого ответа содержала параграф, основанный на неверной идее, что Скайлэйк уменьшил ассоциативность L1. Это L2 Скайлэйк, который с 4 путями, против 8 с Бродвеллом и ранее. Тем не менее, обсуждение более недавнего ответа может представлять интерес.


В руководстве Intel x86 vol3, глава 11.5.6 указано, что Netburst (P4) может не работать таким образом. По умолчанию используется "Адаптивный режим", который позволяет логическим процессорам внутри ядра совместно использовать данные.

Существует "общий режим":

В режиме совместного использования кэш данных L1 конкурентно распределяется между логическими процессорами. Это верно, даже если логические процессоры используют идентичные регистры CR3 и режимы подкачки.

В режиме совместного использования линейные адреса в кэше данных L1 могут быть псевдонимами, что означает, что один линейный адрес в кэше может указывать на разные физические местоположения. Механизм разрешения псевдонимов может привести к сбою. По этой причине IA32_MISC_ENABLE[бит 24] = 0 является предпочтительной конфигурацией для процессоров на основе микроархитектуры Intel NetBurst, поддерживающей технологию Intel Hyper-Threading.

Об этом ничего не сказано для гиперпоточности в Uhaches Nehalem / SnB, поэтому я предполагаю, что они не включили поддержку "медленного режима", когда они внедрили поддержку HT в другом уарче, так как они знали, что получили "быстрый режим" для правильно работать в сети. Интересно, этот бит режима существует только в том случае, если они обнаружили ошибку и должны были отключить ее с помощью обновлений микрокода.

В остальной части этого ответа рассматриваются только нормальные настройки для P4, и я уверен, что именно так работают процессоры Nehalem и семейства SnB.


Теоретически было бы возможно создать ядро ​​CPU SMT OOO, которое делало хранилища из одного потока видимыми для другого, как только они выходили на пенсию, но до того, как они покидали буфер хранилища и фиксировали L1d (т.е. до того, как они станут глобально видимыми). Это не то, как работают проекты Intel, так как они статически разделяют очередь магазина, а не делят ее конкурентно.

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

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

Некоторые процессоры POWER могут это делать; это кажется наиболее вероятным объяснением того, что не все потоки согласны на единый глобальный заказ для магазинов. Будут ли две атомарные записи в разные места в разных потоках всегда рассматриваться в одном и том же порядке другими потоками?,

Как указывает @BeeOnRope, это не сработает для процессора x86, только для ISA, который не гарантирует Total Store Order, потому что это позволит родным братьям SMT увидеть ваш магазин, прежде чем он станет глобально видимым для другие ядра.

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

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