Бар'єр пам'яті
Бар'єр пам'яті (англ. Memory barrier) — різновид комп'ютерної інструкцї типу бар'єр, що дає команду центральному процесору (CPU) або компілятору накласти обмеження на впорядкування операцій по роботі з пам'яттю, які відбуваються перед і після інструкції бар'єру. Це як правило означає, що операції, описані перед бар'єром гарантовано будуть виконані перед тим, як будуть виконуватися операції після бар'єру.
Бар'єри пам'яті є необхідними оскільки більшість сучасних CPU застосовують оптимізацію для підвищення продуктивності, що може призвести до позачергового виконання інструкцій. Це перевпорядкування операцій по роботі з пам'яттю (зчитування і запис) як правило відбувається непомітно для програми із єдиним потоком виконання, але може призвести до неочікуваної поведінки при паралельному виконанні і в драйверах пристроїв, якщо це уважно не контролювати. Точна реалізація обмеження щодо впорядкування залежить від апаратного втілення і визначається архітектурою моделі впорядкування пам'яті. В деяких архітектурах існує декілька бар'єрів, що накладають різні обмеження щодо впорядкування інструкцій.
Бар'єри пам'яті як правило використовуються при реалізації низько-рівневого машинного коду, який працює із пам'яттю що спільно використовується декількома пристроями. Такий код містить примітиви синхронізації і lock-free структури даних на багатопроцесорних системах, і драйвери пристроїв, що взаємодіють із обладнанням комп'ютера.
Приклад
Коли програма використовується на комп'ютері із одним процесором, обладнання забезпечує усі необхідні процедури аби бути впевненими що виконуватиметься так, що всі операції із пам'яттю будуть виконані в тому ж порядку, як вони були вказані в програмному коді, тому бар'єри пам'яті не є потрібними. Однак, коли пам'ять розподілена між декількома пристроями, наприклад, між декількома процесорами на багатопроцесорній системі, або периферійним обладнанням із мапінгом пам'яті, невпорядкований доступ до пам'яті може впливати на поведінку програми. Наприклад, другий процесор може бачити зміни у пам'яті виконані першим процесором у такій послідовності, що відрізняється від порядку програми.
Наступний приклад програми, що виконується двома процесорами приводить приклад того, як позачергове виконання може вплинути на поведінку програми:
Спочатку, області пам'яті x
і f
обидві мають записане значення 0
. Програма, що виконується на процесорі #1 виконуватиме цикл while поки значення f
дорівнюватиме нулю, після чого вона друкує значення змінної x
. Програма, що виконується на процесорі #2 записує значення 42
у x
і після того записує значення 1
в f
. Псевдокод цих двох фрагментів програми наведений далі. Кроки виконання програми відповідають окремим інструкціям процесора.
Процесор #1:
while (f == 0);
// Тут потрібний бар'єр пам'яті
print x;
Процесор #2:
x = 42;
// Тут потрібний бар'єр пам'яті
f = 1;
Програміст очікує, що в результаті програма завжди друкуватиме число "42"; однак, операції, що зберігає процесор #2 будуть виконуватися поза встановленим порядком, може бути так, що значення f
буде змінене перед зміною x
, і в результаті програма надрукує значення "0". Аналогічним чином, операції завантажені на процесор #1 можуть виконатися позачергово і читання значення x
може відбутися перед перевіркою значення f
, і знову таки в результаті може бути надруковане неочікуване значення. Для більшості програм жодна з цих ситуацій не є прийнятною. Таким чином бар'єр пам'яті варто додати перед тим як процесор #2 задає значення f
аби бути впевненими, що нове значення x
буде видимим іншим процесорам до того як зміниться значення f
. Інший бар'єр пам'яті можна додати перед тим як процесор #1 здійснюватиме доступ до x
аби переконатися, що значення x
не зчитується до того як програма побачить зміну значення f
.
Примітки
Посилання
- Memory Barriers: a Hardware View for Software Hackers
- Multiprocessor Considerations for Kernel-Mode Drivers - Preliminary Version - October 28, 2004
- HP technical report HPL-2004-209: Threads Cannot be Implemented as a Library
- Linux kernel memory barrier issues on multiple types of CPUs
- Documentation on memory barriers in the Linux kernel
- Handling Memory Ordering in Multithreaded Applications with Oracle Solaris Studio 12 Update 2: Part 1, Compiler Barriers
- Handling Memory Ordering in Multithreaded Applications with Oracle Solaris Studio 12 Update 2: Part 2, Memory Barriers and Memory Fences
- User-space RCU: Memory-barrier menagerie