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

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

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

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

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

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

Sandy Bridge Intel CPU - кеш L1:

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

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

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

введите описание изображения здесь

Ответ 1

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

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

Обновление: см. этот Q & A для некоторых экспериментальных испытаний пропускной способности и латентности.


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

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


Два потока, выполняющиеся на одном и том же ядре с гиперпотоком, могут видеть перезагрузку StoreLoad, если они не используют блокировки памяти, потому что пересылка хранилища не происходит между потоками. код Jeff Preshing Memory Reordering Caught in the Act может быть использован для проверки на практике, используя сродство к процессору для запуска потоков на разных логических процессорах одного и того же физического ядра.

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

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

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

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


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

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

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


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

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

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

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

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

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


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

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

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

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

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