2010-03-22 2 views
16

Понятно об использовании MemoryBarrier, но не о том, что происходит за кулисами во время выполнения. Может ли кто-нибудь дать хорошее объяснение тому, что происходит?Может ли кто-нибудь дать простое объяснение того, как «Полные заборы» реализованы в .NET с помощью Threading.MemoryBarrier?

ответ

14

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

Запоминания памяти необходимы, потому что текущие общие архитектуры do not provide a strong memory model - x86/x64 может, например, переупорядочить чтение относительно записи. (Более тщательный источник "Intel® 64 and IA-32 Architectures Software Developer’s Manual, 8.2.2 Упорядочение памяти в Р6 и более современных семейств процессоров»). В качестве примера из gazillions, Dekker's algorithm will fail on x86/x64 без заборов.

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

. Рискуя чрезмерное упрощение: это может помочь визуализировать нагрузки и магазины в результате потока инструкций как громоподобное стадо wil d животных. Когда они пересекают узкий мост (ваш процессор), вы никогда не можете быть уверены в порядках животных, так как некоторые из них будут медленнее, быстрее, некоторые обгоняют, некоторые отстают. Если в начале - когда вы испускаете машинный код - вы разбиваете их на группы, помещая между ними бесконечно длинные ограждения, вы можете по крайней мере быть уверены, что группа A подходит к группе B.

Заборы обеспечивают порядок чтения и пишет.Формулировка не является точной, но:

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

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

На моей машине x64, с .NET 4.0 RC, это lock or.

  int a = 0; 
00000000 sub   rsp,28h 
      Thread.MemoryBarrier(); 
00000004 lock or  dword ptr [rsp],0 
      Console.WriteLine(a); 
00000009 mov   ecx,1 
0000000e call  FFFFFFFFEFB45AB0 
00000013 nop 
00000014 add   rsp,28h 
00000018 ret 

Intel® 64 and IA-32 Architectures Software Developer’s Manual Глава 8.1.2:

  • "... заблокированные операции сериализации все невыполненные загрузки и сохранения операций (то есть, ждать их завершения)" ... «заблокированные операции являются атомарными в отношении всех других операций с памятью и все внешне видимые события. Получать только инструкции и таблицы страниц имеет доступ, могут пройти заблокированные инструкции. Заблокированные инструкции могут быть использованы для синхронизации данных, записанных на одной процессор и чтение другим процессором ».

  • заказ на хранение инструкция адрес эта специфическая потребность. MFENCE мог бы использоваться как полный барьер в вышеуказанном случае (по крайней мере теоретически - для одного, locked operations might be faster, для двух это might result in different behavior). MFENCE и его друзьям можно найти в разделе Глава 8.2.5 «Усиление или ослабление модели порядка памяти».

Есть еще несколько способов сериализации магазинов и нагрузки, хотя они непрактичны или медленнее, чем выше методы:

  • В разделе 8.3 вы можете найти полный сериализации инструкции как CPUID , Эти команды сериализовать также: «Ничто не может передавать инструкцию по сериализации и инструкция сериализации не может передавать какую-либо другую инструкцию (чтение, запись, инструкция выборка или ввод-вывод)».

  • Если вы создали память, как сильная некэшированную (UC), it will give you a strong memory model: нет спекулятивной или вне порядка доступов будут разрешено, и все доступы будут появляться на автобусе, поэтому нет необходимости испускать инструкции. :) Конечно, это будет чуть медленнее, чем обычно.

...

Так это зависит от того.Если бы был компьютер с сильными гарантиями порядка, JIT, вероятно, ничего не испустил бы.

IA64 и другие архитектуры имеют свои собственные модели памяти - и, таким образом, гарантируют порядок памяти (или их отсутствие) - и их собственные инструкции/способы работы с хранением или загрузкой памяти.

+0

Отличное объяснение. Хорошие ссылки на другие ресурсы. Спасибо! – Kilhoffer

4

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

программных команд переупорядочения может происходить в несколько этапов:

  1. C#/VB.NET/F # оптимизации компилятора
  2. JIT-компилятор оптимизации
  3. CPU оптимизации.

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

  1. нагрузки заборов - обеспечить не нагрузок команды процессора двигаться через заборы
  2. магазин заборы - убедиться в отсутствии инструкции магазина CPU не двигаться через заборы
  3. Полных заборы - обеспечить нет команды загрузки или магазин CPU двигаться через заборы

в .NET Framework существует множество способов испускают заборы: интерлок, монитор, ReaderWriterLockSlim и т.д.

Thread.MemoryBarrier испускает полный забор как на компиляторе JIT, так и на уровне процессора.

+0

Ваше последнее предложение - это то, что я ищу. Я знаю, что такое заборы и почему они нужны, но как это испускается на компиляторе JIT и что на самом деле выводится? – Kilhoffer