Dokładniej, potrzebuję tylko zwiększyć podwójność o kolejne podwójne i chcę, aby był bezpieczny dla wątków. Nie chcę używać do tego muteksa, ponieważ prędkość wykonywania dramatycznie spadłaby.Jak wykonać podstawowe operacje z std :: atomic, gdy typ nie jest integralny?
Odpowiedz
Z reguły biblioteka standardowa C++ próbuje zapewnić tylko te operacje, które można skutecznie wdrożyć. W przypadku std::atomic
oznacza to operacje, które można wykonywać bez blokady w instrukcji lub dwóch na "typowych" architekturach. "Wspólne" architektury mają instrukcje atomowego pobierania i dodawania dla liczb całkowitych, ale nie dla typów zmiennoprzecinkowych.
Jeśli chcesz realizować operacje matematyczne dla atomowych pływających rodzajów punktów, będziesz musiał zrobić sobie z CAS (porównaj i swap) pętla (Live at Coliru):
std::atomic<double> foo{0};
void add_to_foo(double bar) {
auto current = foo.load();
while (!foo.compare_exchange_weak(current, current + bar))
;
}
Dziękuję za odpowiedź, nie zdawałem sobie sprawy, że aby to zrobić (dodam dwa podwójne wątki bezpiecznie) potrzebowałbym takiego brudnego (a przynajmniej wygląda na to) obejścia. – Noozen
Jestem trochę zdezorientowany. Dlaczego ten kod nie wejdzie w nieskończoną pętlę, jeśli foo! = Current z powodu modyfikowania foo przez inny wątek między ładunkiem a CAS? – Joe
@Joe 'compare_exchange_weak' pobiera swój pierwszy argument przez odniesienie i aktualizuje go do obserwowanej wartości w przypadku niepowodzenia. Więc jeśli CAS nie powiedzie się becayse 'foo! = Current' pętla oblicza nowy' current + bar' ze zaktualizowanego 'current' i próbuje ponownie. – Casey
Używaj więc całki atomowej jako bariery pamięci. Oto strona ze źródłem i wyjaśnieniem: http://preshing.com/20121019/this-is-why-they-call-it-a-weakly-ordered-cpu/
Bariera pamięci pomaga tylko w zamawianiu, a nie w atomizacji. Właśnie dlatego potrzebujesz CAS (lub LL/SC), aby stworzyć cały atomowy read-modify-write. –
related: [Atomowej podwójne pływający punkt lub ładowanie/przechowywanie wektorów SSE/AVX na x86_64] (https://stackoverflow.com/questions/45055402/atomic-double-floating-point-or-sse-avx-vector-load-store-on-x86-64). Zasadniczo ta sama odpowiedź, ale z szczegółami asm x86. (Niektóre kompilatory dość nieefektywnie pobierają dane z XMM na liczbę całkowitą dla 'compare_exchange' lub nawet ładują/przechowują z' atomowym ', niestety.) –