Концепция глобальной видимости для нагрузок сложна, поскольку нагрузка не изменяет общее состояние памяти, и другие потоки не могут напрямую наблюдать его.
Но однаждыпыль оседает после неупорядоченного / умозрительного выполнения, мы можем сказать, какое значение получила нагрузка, если поток где-то ее хранит, или ветвится на ее основе.Это наблюдаемое поведение потока - вот что важно.(Или мы можем наблюдать это с помощью отладчика и / или просто рассуждать о том, какие значения могла бы видеть нагрузка, если эксперимент труден.)
По крайней мере на сильно упорядоченных процессорах, таких как x86, все процессоры могут договориться о том, что общий порядок магазинов станет глобально видимым , обновив состояние единого связного + согласованного кэша + памяти.На x86, если Переупорядочение StoreStore не разрешено, этот TSO (Total Store Order) согласуется с программным порядком каждого потока.(Т.е. общий порядок - это некоторое чередование программного порядка из каждого потока).SPARC TSO также строго упорядочен.
(Для хранилищ с обходом кэша глобальная видимость - это когда они сбрасываются из некогерентных буферов объединения записи в DRAM.)
На слабомВ упорядоченном ISA потоки A и B могут не совпадать по порядку хранилищ X и Y, выполняемых потоками C и D, даже если потоки чтения используют acqu-load, чтобы убедиться, что их собственные нагрузки не переупорядочены.т. е. не может быть глобального порядка хранилищ вообще, не говоря уже о том, чтобы он не совпадал с порядком программ.
IBM POWER ISA настолько слаб, как и CМодель памяти ++ 11 ( Будут ли две атомарные записи в разные места в разных потоках всегда рассматриваться в одном и том же порядке другими потоками? ).Это может вступить в противоречие с моделью хранилищ, которая становится видимой глобально, когда они фиксируются из буфера хранилища в кэш L1d.Но @BeeOnRope говорит в комментариях , что кэш действительно согласован и позволяет восстанавливать последовательную согласованность с барьерами.Эти эффекты многократного порядка происходят только из-за того, что SMT (несколько логических ЦП на одном физическом ЦП) вызывает необычное локальное переупорядочение.
(Один из возможных механизмов - позволить другим логическим потокам отслеживать не спекулятивные хранилища из хранилища.буферизировать даже до того, как они перейдут на L1d, сохраняя приватность только для еще не списанных хранилищ для логического потока. Это может немного уменьшить задержку между потоками. x86 не может этого сделать, потому что это сломало бы сильную модель памяти; статические разделы HT от Intelбуфер хранилища, когда два ядра активны на ядре. Но, как отмечает @BeeOnRope, абстрактная модель разрешенных переупорядочений, вероятно, является лучшим подходом для рассуждений о корректности. Просто потому, что вы не можете думать о механизме HWвызывать переупорядочение не означает, что это не может произойти. )
Слабо упорядоченные ISA, которые не так слабы, как POWER, по-прежнему переупорядочивают в буфере локального хранилища каждого ядра, если существуют барьерыили релиз-магазины не используются, хотя.На многих процессорах существует глобальный порядок для всех магазинов, но это не чередование порядка программ.ЦП OoO должны отслеживать порядок памяти, поэтому одному потоку не нужны барьеры, чтобы видеть свои собственные хранилища по порядку, но разрешение хранилищ зафиксировать хранилища из буфера хранилища в L1d вне порядка программы, безусловно, может улучшить пропускную способность (особенно если имеется несколько хранилищв ожидании той же строки, но программный порядок вытеснит строку из ассоциативно-множественного кэша между каждым хранилищем (например, неприятный шаблон доступа к гистограмме.)
Давайте проведем мысленный эксперимент о том, откуда поступают данные загрузкис
Вышесказанное относится только к видимости магазина, а не к нагрузкам. Можем ли мы объяснить значение, видимое каждой загрузкой как считываемое из глобальной памяти / кэша в какой-то момент (без учета каких-либо правил упорядочения нагрузки)?
Если это так, то все результаты загрузки можно объяснить, поместив все хранилища и загрузку всеми потоками в некоторый комбинированный порядок, считав и записав согласованное глобальное состояние памяти.
Оказывается, нет, мы не можем, буфер хранилища ломает это : частичная пересылка из хранилища в загрузку дает нам контрпример (на x86, например).Узкое хранилище, за которым следует широкая загрузка, может объединить данные из буфера хранилища с данными из кэша L1d до того, как хранилище станет глобально видимым. Реальные x86-процессоры на самом деле делают это, и у нас есть реальные эксперименты, чтобы доказать это.
Если вы посмотрите только на полную пересылку хранилища, где загрузка берет свои данные только из одного хранилища вбуфер хранилища, вы можете утверждать, что загрузка задерживается буфером хранилища.то есть, что загрузка появляется в глобальном общем порядке хранения загрузки сразу после хранилища, которое делает это значение глобально видимым.
(Этот глобальный общий порядок загрузки загрузки не является попыткой создать альтернативный порядок в памятимодель; у нее нет никакого способа описать действительные правила упорядочения загрузки x86.)
Частичная пересылка хранилища обнажает тот факт, что данные загрузки не всегда поступают из глобальной области когерентного кэша.
Если хранилище из другого ядра изменяет окружающие байты, атомная загрузка может считывать значение, которое никогда не существовало, и никогда не будет существовать в глобальном когерентном состоянии.
См. Мой ответ на Может ли x86 переупорядочить узкое хранилище с более широкой загрузкой, которая полностью его содержит? , и ответ Алекса для экспериментального доказательства того, что такое переупорядочение может произойти, что делает предложенную схему блокировки в этом вопросенедействительным. Магазин, а затем перезагрузка с того же адреса не является барьером памяти StoreLoad .
Некоторые люди (например, Линус Торвальдс) описывают это, говоря, что буфер хранилища некогерентное .(Линус отвечал кому-то еще, кто независимо придумал ту же самую недопустимую идею блокировки.)
Еще один вопрос-ответ, касающийся буфера хранения и когерентности: Как эффективно установить биты битового вектора параллельно? .Вы можете сделать неатомарное ИЛИ для установки битов, а затем вернуться и проверить наличие пропущенных обновлений из-за конфликтов с другими потоками.Но вам нужен барьер StoreLoad (например, x86 lock or
), чтобы убедиться, что вы не просто видите свои собственные магазины при перезагрузке.
Загрузка становится видимой глобально, когда она читает свои данные.Обычно из L1d, но буфер хранения, MMIO или не кэшируемая память являются другими возможными источниками.
Это определение согласуется с руководствами x86, в которых говорится, что нагрузки не переупорядочиваются с другими нагрузками.то есть они загружаются (в программном порядке) из представления памяти локального ядра.
Сама загрузка может стать видимой глобально независимо от того, может ли какой-либо другой поток загрузить это значение изэтот адрес.