Zoptymalizowałem kod C++, w którym napotkałem sytuację, którą można uprościć w następujący sposób.Efekt optymalizacji gcc na pętlach z pozornie stałą zmienną
Rozważmy następujący kod:
#include <iostream>
#include <thread>
using namespace std;
bool hit = false;
void F()
{
this_thread::sleep_for(chrono::seconds(1));
hit = true;
}
int main()
{
thread t(F);
while (!hit)
;
cout << "finished" << endl;
t.join();
return 0;
}
Zasadniczo rozpoczyna wątek, który po chwili zmieni wartość hit
do true
. W tym samym czasie kod wchodzi w pustą pętlę, która będzie kontynuowana, dopóki wartość hit
nie zmieni się na true
. Skompilowałem to przy pomocy gcc-5.4
przy użyciu flagi -g
i wszystko było w porządku. Kod wyświetli kod finished
i zakończy się. Ale potem skompilowałem go z flagą -O2
i tym razem kod utknął w pętli w nieskończoność.
Patrząc na demontażu, kompilator wygenerował następujące dane, które jest przyczyną nieskończonej pętli:
jmp 0x6ba6f3! 0x00000000006ba6f3
OK, więc wyraźnie, kompilator wywnioskować, że hit
„s wartość false
i to nie zmieni się w pętli, więc dlaczego nie założyć, że jest to pętla nieskończona, nie biorąc pod uwagę, że inny wątek może zmienić swoją wartość ! Ten tryb optymalizacji jest dodawany na wyższym poziomie (-O2
). Ponieważ nie jestem ekspertem od optymalizacji, czy ktoś może mi powiedzieć, który z nich jest odpowiedzialny za ten wynik, więc mogę go wyłączyć? A wyłączenie go ma jakieś poważne koszty wydajności dla innych kawałków kodu? Chodzi mi o to, jak bardzo ten wzór kodu jest rzadki?
użyj 'std :: atomic'. –
Jarod42
Co się stanie, jeśli zadeklarujesz "trafienie" jako niestabilne? – Milack27
@ Milack27 tak, to rozwiązuje problem! Człowieku, jest wiele rzeczy w C++, o których wciąż nie wiem! – Sinapse