Programowanie współbieżne, Języki programowania, Aplikacje, Gry

Memory ordering cd.

Miesiąc temu poruszyłem problem „przestawiania operacji odczytu i zapisu” w procesorach z rodziny x86. Dzisiaj postaram się rozszerzyć ten temat na inne architektury. W tym wpisie będę odnosił się przede wszystkim do dokumentu Memory Barriers: a Hardware View for Software Hackers. Najbardziej istotny jest tutaj rozdział 7 i tabela 5 na stronie 16. Znajduje się tam porównanie różnych architektur pod kątem możliwych zamian kolejności operacji odczytu i zapisu. Nie zamierzam tutaj tłumaczyć całego rozdziału, skupię się tylko na kilku ważnych faktach:

  • Istnieją architektury ze zdecydowanie luźniejszym modelem pamięci niż ten w procesorach x86.
  • Niektóre architektury pozwalają na wybranie jednego z kilku możliwych modeli pamięci przez system operacyjny.
  • Niespójność widoku pamięci różnych wątków może wywodzić się nie tylko z istnienia write buffera ale także np z luźniejszego modelu synchronizacji pamięci cache.
  • Wykonanie instrukcji atomowej nie implikuje uzyskania „total order”
  • Do wymuszania zachowania kolejności określonych operacji służą instrukcje typu „memory barrier”. Architektury o luźniejszym modelu oferują przeważnie kilka różnych instrukcji tego typu do uzyskania różnego poziomu spójności widoków pamięci.

Ten kto obejrzał film z poprzedniego wpisu wie, że model pamięci x86 pozwala na bezpieczne publikowanie obiektu. Przez publikację obiektu należy rozumieć sytuację:

mov a, r1;
mov gotowe, 1;

W powyższych przykładach agotowe to zmienne w pamięci, r1 to rejestr procesora. Zakładamy, że obiekt gotowe przed rozpoczęciem wykonywania tego kodu zawierał wartość 0. Zakładamy też, że przypisanie wartości 1 do obiektu gotowe oznacza, że obiekt a zawiera już nową poprawną wartość i ta wartość może być odczytana przez inny wątek. W takim wypadku inny wątek programu może co jakiś czas odczytywać wartość gotowe aż odczyta wartość 1. Wtedy wie że obiekt a zawiera poprawną wartość i może ją odczytać. Niestety takie rozwiązanie nie zadziała np. na procesorach z rodziny Power PC. Dla nich proces publikacji powinien wyglądać tak:

mov a, r1;
lwsync; //memory barrier
mov gotowe, 1;

W następnym poście opiszę jak informacje zawarte w tym wpisie odnoszą się do publikowania obiektów w C++.

Leave a Reply