2011-02-09 19 views
19

Nadal nie jestem pewien, czy to ja nie rozumiem, czy dokumentacja nie jest jasno sformułowana. Poniższy fragment został wzięty z najnowszej wersji roboczej (N3126, rozdział 29.6)std :: atomowy | compare_exchange_weak vs. compare_exchange_strong

bool atomic_compare_exchange_weak(volatile A* object, C * expected, C desired); 
bool atomic_compare_exchange_weak(A* object, C * expected, C desired); 
bool atomic_compare_exchange_strong(volatile A* object, C * expected, C desired); 
bool atomic_compare_exchange_strong(A* object, C * expected, C desired); 
bool atomic_compare_exchange_weak_explicit(volatile A* object, C * expected, C desired, memory_order success, memory_order failure); 
bool atomic_compare_exchange_weak_explicit(A* object, C * expected, C desired, memory_order success, memory_order failure); 
bool atomic_compare_exchange_strong_explicit(volatile A* object, C * expected, C desired, memory_order success, memory_order failure); 
bool atomic_compare_exchange_strong_explicit(A* object, C * expected, C desired, memory_order success, memory_order failure); 
bool A::compare_exchange_weak(C & expected, C desired, memory_order success, memory_order failure) volatile; 
bool A::compare_exchange_weak(C & expected, C desired, memory_order success, memory_order failure); 
bool A::compare_exchange_strong(C & expected, C desired, memory_order success, memory_order failure) volatile; 
bool A::compare_exchange_strong(C & expected, C desired, memory_order success, memory_order failure); 
bool A::compare_exchange_weak(C & expected, C desired, memory_order order = memory_order_seq_cst) volatile; 
bool A::compare_exchange_weak(C & expected, C desired, memory_order order = memory_order_seq_cst); 
bool A::compare_exchange_strong(C & expected, C desired, memory_order order = memory_order_seq_cst) volatile; 
bool A::compare_exchange_strong(C & expected, C desired, memory_order order = memory_order_seq_cst); 

uwaga: Słabe-porównywana i wymiany operacji może nie fałszywie, że jest zwraca fałsz pozostawiając zawartość pamięci wskazywana przez , oczekiwana przed operacją, jest taka sama, jak w przypadku obiektu obiektu i taka sama, jak oczekiwana po operacji . [Uwaga: Ta fałszywa awaria umożliwia implementację porównania i zamiany na szerszej klasie komputerów, np. Z blokadą obciążenia maszyn warunkowo-sklepowych. Konsekwencją fałszywego niepowodzenia jest , że prawie wszystkie zastosowania słabej porównywania i wymiany będą w pętli .

Co to oznacza? Po pierwsze, może "zawieść" fałszywie ?! Dlaczego to robi? A jak definiują "może"? Po drugie, nie wiem dlaczego, ale wciąż nie mam pojęcia, jaka jest różnica pomiędzy funkcjami z przyrostkiem "_strong" i "_weak".

Mam nadzieję, że ktoś może pomóc;) Pozdrawiam.

EDIT: To co znalazłem w libstdC++ - wdrożenie (atomic_0.h):

bool compare_exchange_weak(
    __integral_type& __i1, 
    __integral_type __i2, 
    memory_order __m1, 
    memory_order __m2 
) 
{ 
    __glibcxx_assert(__m2 != memory_order_release); 
    __glibcxx_assert(__m2 != memory_order_acq_rel); 
    __glibcxx_assert(__m2 <= __m1); 
    return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1); 
} 

bool compare_exchange_strong(
    __integral_type& __i1, 
    __integral_type __i2, 
    memory_order __m1, 
    memory_order __m2 
) 
{ 
    __glibcxx_assert(__m2 != memory_order_release); 
    __glibcxx_assert(__m2 != memory_order_acq_rel); 
    __glibcxx_assert(__m2 <= __m1); 
    return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1); 
} 
+0

Dodałem znacznik STL, z nadzieją, że przyniesie tam Howarda Hinnanta, pracował nad wprowadzeniem ich w libC++, więc powinien o tym wiedzieć. –

Odpowiedz

7

Ma do czynienia z pamięci współdzielonej konsystencji model, który implementuje sprzętowe. Dla tych architektur sprzętowych, które implementują pewien rodzaj luźnego modelu spójności (np. Semantyka uwolnienia), silne operacje, o których wspomniałeś powyżej, mogą mieć duży narzut, a zatem eksperci mogą używać słabszych formularzy do implementacji algorytmów, które dobrze sprawdzają się również w tych zrelaksowanych konsekwencjach. architektury.

Aby uzyskać więcej informacji, zobacz np.

http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-95-7.pdf

Rozdział 12 i Załącznik C w http://kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.html

+1

Ale czy nie jest to sens parametru memory_order, aby wzmocnić lub osłabić model zamawiania pamięci? – 0xbadf00d

+0

Nie, jest to określone przez sprzęt Parametr ten określa minimalną kolejność wymaganą przez twój algorytm, aby działał poprawnie.Do tego dochodzi implementacja C++ 0x, aby upewnić się, że przynajmniej podana kolejność jest pod warunkiem, dla mocno zamówionego architekta ectures takich jak x86, jest prawdopodobne, że zarówno silne, jak i słabe implementacje są takie same. – janneb

+0

Sry, ale nadal nie ma to dla mnie sensu. Czy nie jest zbyteczne określanie kolejności za pomocą parametru memory_order i silnych lub słabych metod? Być może pomogłoby to dowiedzieć się, jaka jest główna (abstrakcyjna) różnica między słabą a silną porównywarką. – 0xbadf00d

25

Nota daje wskazówkę, odnosząc się do LL/SC architektur. Z artykułu z Wikipedii:

Jeśli wystąpiły jakiekolwiek aktualizacje, warunkowe warunki przechowywania nie powiodły się, nawet jeśli odczytywana przez load-link wartość została odtworzona. W związku z tym para LL/SC jest silniejsza od odczytu, a następnie porównywania i zamiany (CAS), która nie wykryje aktualizacji, jeśli przywrócono poprzednią wartość (patrz problem ABA).

Rzeczywiste implementacje LL/SC nie zawsze kończą się pomyślnie, jeśli nie ma równoczesnych aktualizacji danej lokalizacji pamięci. Wszelkie wyjątkowe zdarzenia między dwiema operacjami, takie jak przełączanie kontekstu, inne łącze ładowania, a nawet (na wielu platformach) inne obciążenie lub operacja przechowywania, spowoduje, że warunki przechowywania w pamięci będą nieudane.

Na LL żetonów/sc compare_exchange będą realizowane w kategoriach LL/SC, które mogą fałszywie nie, więc compare_exchange_strong potrzeb ekstra napowietrznych, aby ponowić próbę w przypadku awarii. Zapewnienie zarówno compare_exchange_strong i compare_exchange_weak pozwala programiście decydować, czy chcą, aby biblioteka obsłużyła fałszywe niepowodzenia (w takim przypadku użyliby one compare_exchange_strong, czy też chcą zająć się tym w swoim własnym kodzie (w takim przypadku użyliby compare_exchange_weak)

+0

Dobra odpowiedź. Jedną z rzeczy do omówienia jest "ponowienie próby w przypadku niepowodzenia", czy powinno być "ponowienie w przypadku *** fałszywej *** awarii"? Jeśli jest to prawdziwe niepowodzenie z powodu rywalizacji (wartość dest nie jest równa oczekiwanemu), 'compare_exchange_strong' powinno zwracać' false 'natychmiast bez jakiegokolwiek ponowienia. Czy sie zgadzasz? –

+0

Napisałem pytanie dotyczące 'compare_exchange_weak' [tutaj] (http://stackoverflow.com/questions/25199838/understanding-of-stdatomiccompare-exchange-weak-in-c11). Czy mógłbyś rzucić okiem i podzielić się z nami wiedzą, którą znasz? Dzięki. –

+0

Tak, silna forma ponawia próbę w przypadku fałszywego niepowodzenia, a nie, gdy obiekt nie ma oczekiwanej wartości. –

Powiązane problemy