Как работают заборы памяти? - PullRequest
24 голосов
/ 02 сентября 2011

Мне нужно понять, как работает память на многоядерных машинах. Скажи, у меня есть этот код

Core 1

mov [_x], 1; mov r1, [_y]    

Core 2

mov [_y], 1; mov r2, [_x]

Теперь неожиданные результаты без ограждений памяти могут заключаться в том, что и r1, и r2 могут быть 0 после выполнения. По моему мнению, чтобы противостоять этой проблеме, мы должны поставить забор памяти в обоих кодах, так как использование только одного из них все равно не решит проблему. Что-то вроде следующего ...

Core 1

mov [_x], 1; memory_fence; mov r1, [_y]  

Core 2

mov [_y], 1; memory_fence; mov r2, [_x]

Мое понимание верно, или я все еще что-то упускаю? Предположим, архитектура x86. Кроме того, кто-то может сказать мне, как поместить заборы памяти в коде C ++?

Ответы [ 2 ]

14 голосов
/ 02 сентября 2011

Ограждения сериализуют операцию, которую они ограждают (загружают и хранят), то есть никакая другая операция не может начаться до тех пор, пока ограждение не будет выполнено, но ограждение не будет выполняться, пока все предыдущие операции не будут завершены. цитирование intel делает смысл этого более точным (взято из инструкции MFENCE, стр. 3-628, том 2A, справочник Intel):

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

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

Использовать ограждения в C ++ сложно (C ++ 11 может иметь семантику ограждения где-то, может быть, у кого-то есть информация об этом), так как это зависит от платформы и компилятора. Для x86 с использованием MSVC или ICC вы можете использовать _mm_lfence, _mm_sfence & _mm_mfence для загрузки, сохранения и загрузки + сохранения ограждения (обратите внимание, что некоторые из них являются инструкциями SSE2).

Примечание: это предполагает перспективу Intel, то есть одну, использующую процессор x86 (32 или 64 бит) или IA64

4 голосов
/ 18 октября 2011

C ++ 11 ( ISO / IEC 14882: 2011 ) определяет модель памяти с поддержкой многопоточности. Хотя я не знаю ни одного компилятора, который в настоящее время реализует новую модель памяти, Параллелизм C ++ в действии Энтони Уильямса очень хорошо документирует это. Вы можете проверить Глава 5 - Модель памяти C ++ и операции с атомарными типами , где он объясняет расслабленные операции и ограничения памяти. Кроме того, он является автором библиотеки just :: thread, которую можно использовать до тех пор, пока мы не получим поддержку от нового стандарта от поставщика компилятора. just :: thread является базой для библиотеки boost :: thread.

...