[C++] std::atomic, a działanie std::memory_order_relaxed
Ostatnio zmodyfikowano 2013-06-05 12:27
Elaine |
» 2013-06-04 23:58:13 Ja bym eksperymentalnie zapuścił np. milion razy wykonanie tego kodu i sprawdził czy choć raz zachodzi Assert. |
Na x86 to nie ma sensu, ta architektura ma bardzo silny model pamięci, wszystko zachowuje się jak memory_order_seq_cst. Jeśli masz dostęp do maszyny na ARMie, MIPSie, PowerPC czy w zasadzie dowolnej w miarę nowoczesnej architekturze innej niż x86, to tak, taki eksperyment można przeprowadzić.
W każdym razie wydaje mi się nieco dziwne, aby zmienna modyfikowana później była 'synchronizowana' przed zmienną modyfikowaną wcześniej w tym samym wątku |
W tym nie ma nic dziwnego, procesory i kontrolery pamięci lubią zmieniać kolejność operacji i nawet udawać, że operacja zaszła, podczas gdy ma dopiero zajść, to wszystko w imię wydajności. Znowu, to "wina" x86, gdzie kolejności widoczności operacji między procesorami dotyczą bardzo silne gwarancje. Na innych architekturach takich gwarancji "z urzędu" nie ma, trzeba o nie poprosić podając odpowiedni memory ordering przy operacjach atomowych. I dlatego ten kod, choć niepoprawny, będzie "działał" na typowym desktopie używającym x86, ale przestanie po skompilowaniu na telefon oparty o ARM. |
|
DejaVu |
» 2013-06-05 00:19:19 Podsumowując: dopóki nie ma się pełnej wiedzy i świadomości na temat różnic w działaniu memory ordering to najlepiej korzystać z domyślnego zachowania std::atomic, tj. std::memory_order_seq_cst, bowiem mamy gwarancję, że na każdej architekturze aplikacja zachowa się tak samo. Racja?
No i wniosek z tego co napisałeś płynie również taki, że w przypadku pracy na architekturze x86 nie ma sensu stosować innego memory orderingu niż domyślny, bowiem nawet nie będziemy w stanie przetestować poprawności przyjętego rozwiązania.
/edit: Jeszcze jedno: skoro ten cały std::memory_order_relaxed ma tylko i wyłącznie własność atomic, to w jakim konkretnym przypadku będzie istniało uzasadnienie i wymierne korzyści płynące z użycia wspomnianego memory orderingu? |
|
usmiech |
» 2013-06-05 01:21:32 << offtop >> |
|
Elaine |
» 2013-06-05 12:27:07 Podsumowując: dopóki nie ma się pełnej wiedzy i świadomości na temat różnic w działaniu memory ordering to najlepiej korzystać z domyślnego zachowania std::atomic, tj. std::memory_order_seq_cst, bowiem mamy gwarancję, że na każdej architekturze aplikacja zachowa się tak samo. Racja? |
Tak. Jeszcze jedno: skoro ten cały std::memory_order_relaxed ma tylko i wyłącznie własność atomic, to w jakim konkretnym przypadku będzie istniało uzasadnienie i wymierne korzyści płynące z użycia wspomnianego memory orderingu? |
Choćby przy zliczaniu referencji. Dodawanie nowych referencji nie potrzebuje żadnych szczególnych gwarancji, o synchronizację trzeba zatroszczyć się dopiero przy zmienjszaniu licznika. class Foo { private: std::atomic < unsigned > referenceCount { 0 }; friend void intrusive_ptr_add_ref( Foo * obj ) { obj->referenceCount.fetch_add( 1, std::memory_order_relaxed ); } friend void intrusive_ptr_release( Foo * obj ) { if( obj->referenceCount.fetch_sub( 1, std::memory_order_release ) == 1 ) { std::atomic_thread_fence( std::memory_order_acquire ); delete obj; } } }; Dowód poprawności pozostawiam jako ćwiczenie dla czytelnika. |
|
1 « 2 » |