2010-01-22 9 views
5

Oto kod C++, do którego można uzyskać dostęp z wielu wątków równolegle. Ma sekcję krytyczną:Zmiana kolejności instrukcji za pomocą blokad

lock.Acquire(); 
current_id = shared_id; 
// small amounts of other code 
shared_id = (shared_id + 1) % max_id; 
lock.Release(); 
// do something with current_id 

Klasa zmiennej blokującej jest opakowaniem wokół implementacji mutex POSIX. Ze względu na operacje modułu nie można korzystać z operacji atomowych.

Czy możliwe jest, że kompilator gcc z flagą O3 optymalizuje kod tak, aby przypisanie current_id zostało przeniesione przed blokadą?

Odpowiedz

3

Możliwe jest skompilowanie z O3!

Kompilator nigdy nie będzie optymalizowany dla wywołania funkcji, chyba że funkcja jest oznaczona jako czysty przy użyciu atrybutów funkcji.

Funkcje mutex nie są czyste, więc używanie ich z O3 jest absolutnie bezpieczne.

+1

Masz na myśli "chyba że funkcja jest oznaczona jako czysta ** lub kompilator jest w stanie ustalić, że jest to bezpieczne **. , wynik końcowy jest taki sam, kompilator generalnie nie dokona optymalizacji, chyba że będzie w stanie zweryfikować, czy jest ona bezpieczna. – jalf

+0

Jeśli "current_id" i "shared_id" są zmiennymi lokalnymi, które nie zostały zmienione z bieżącego zakresu (adres nie zostało to dane komukolwiek innemu itd.), wtedy optymalizator mógłby zmienić kolejność tych linii, ignorując możliwą mutację z zewnętrznych wywołań funkcji. Zakładam, że tak nie jest w tym przypadku, – ephemient

+0

@ephemient: ale jeśli są one lokalne i nie ma ich wcale. jeden na zewnątrz wie, w jaki sposób zewnętrzne wywołanie funkcji może je zmodyfikować? – Kosi2801

1

Zwykle kompilator nie powinien wykonywać tak szkodliwych optymalizacji. Jeśli nadal nie masz pewności, możesz użyć słowa kluczowego volatile, aby zapobiec optymalizacji tych zmiennych identyfikacyjnych.

+0

volatile nie zapobiega wszystkim odpowiednim optymalizacjom. Zapobiega buforowaniu wartości w rejestrze, ale praktycznie nic więcej. Czytanie/zapisywanie wciąż może być zmienione. – jalf

+0

Dobre podejście do tego, kiedy używać niestabilnego, w ramach dokumentacji jądra Linuksa: http://www.mjmwired.net/kernel/Documentation/volatile-considered-harmful.txt – asveikau

+0

@jalf: ale kompilatory naprawdę zmieniają kolejność czytają/pisze tak, że przekraczają granice funkcji? Przydzielone zadania i wywołania funkcji są dość powszechne i przypuszczam, że byłoby dużo problemów w całym miejscu, gdyby przypisanie zmiennych mogło zmienić porządek za pomocą wywołań funkcji. – Kosi2801

Powiązane problemy