Czym różni się spinlock od odpytywania?

41

Czy blokada i odpytywanie to to samo?

Wikipedia:

spinlock to blokada, która powoduje, że nić próbująca ją zdobyć, po prostu czeka w pętli („spin”), jednocześnie wielokrotnie sprawdzając, czy blokada jest dostępna

Brzmi to okropnie podobnie do:

while(!ready);

Nauczono mnie, aby unikać ankiet, gdy tylko jest to możliwe, ponieważ było to całkowicie nieoptymalne. Czy więc spinlock to wymyślna nazwa złego, starego głosowania? Czym różni się blokada od odpytywania?

Lord Loh.
źródło

Odpowiedzi:

85

Sondowanie odnosi się do wielokrotnego sprawdzania, czy zasób ( dowolny rodzaj zasobu) jest gotowy.

Blokada polega na tym, że badany zasób jest blokadą.

Pamiętaj, że odpytywanie nie jest złe. W szczególności odpytywanie jest skuteczne, gdy dane są zwykle gotowe podczas odpytywania. Sondowanie jest nieefektywne tylko wtedy, gdy zrobisz to bez uzyskiwania w zamian jakichkolwiek danych.

Z drugiej strony, przerwania są nieefektywne, jeśli jest tak dużo danych, że ciągle się przerywasz. Są wydajne, jeśli dane docierają na tyle rzadko, że można faktycznie wykonać pożyteczną pracę przed przerwaniem.

Mogę dać ci prawdziwy przykład z własnego doświadczenia: 15 lat temu miałem program poczty elektronicznej skonfigurowany tak, aby przeszkadzał mi za każdym razem, gdy przychodzi nowy e-mail. To się zdarzało raz lub dwa razy w tygodniu. Ciągłe sprawdzanie mojej skrzynki odbiorczej byłoby ogromną stratą czasu.

Obecnie mam wyłączone wszystkie powiadomienia. Ja wiem , że kiedy patrzę w mojej skrzynce odbiorczej, że nie będzie tam nowe e-maile. Sondowanie jest teraz znacznie wydajniejsze.

Blokady są skuteczne, gdy: a) prawdopodobieństwo, że zamek zostanie przejęty, jest niskie, i b) jeśli zamek zostanie przejęty, będzie utrzymywany tylko przez krótki czas. Innymi słowy: jest skuteczny w przypadku większości niezamkniętych zamków drobnoziarnistych, ale nieefektywny w przypadku mocno rywalizowanych zamków gruboziarnistych.

(I oczywiście spinlocki działają tylko wtedy, gdy istnieje prawdziwa równoległość, w przeciwnym razie drugi wątek nie będzie miał szansy zwolnić blokady. Myślę, że to trochę oczywiste, ale i tak chciałem to stwierdzić.)

Jörg W Mittag
źródło
5
Spinlocki mogą być doskonale wyczuwalne w środowisku pracy wielozadaniowej. Musisz tylko upewnić się, że poddajesz się kontroli w pętli.
Kevin,
4
Świetny przykład z e-mailami. Przypomina mi, że zawsze masz e-maila ...
Petr Pudlák
2
@Kevin: Mam bardzo purystyczny pomysł na spinlock, dosłownie zamek, który po prostu obraca się w pustej pętli. ( atomically_do { while (lock.is_locked?); lock.acquire! }) Jeśli się poddaje, nie jest to pusta pętla, a zatem nie blokada w tym purystycznym widoku :-D Ale oczywiście pewna hybrydyzacja z innymi rodzajami zamków lub relaksacji / dodatków do ideału platońskiego ma sens w prawdziwym świecie.
Jörg W Mittag
3
@bakakazouba: Blokada działa poprzez dosłowne „obracanie” w pustej pętli i sprawdzanie „Czy blokada jest już zwolniona? Czy blokada jest już zwolniona? Czy blokada jest już zwolniona? Czy blokada jest już zwolniona? Czy blokada jest już zwolniona?” w kółko. Jeśli nie ma równoległości, nie ma w tym samym czasie innego wątku, który mógłby zwolnić blokadę, dzięki czemu masz efektywnie nieskończoną pętlę! Zobacz komentarz bezpośrednio nad twoim.
Jörg W Mittag
1
@kasperd: Nadal widać wielozadaniowość kooperacyjną w oprogramowaniu serwerowym sterowanym zdarzeniami, takim jak nginx. W takim przypadku istnieje jeden wątek i brak blokady, co oznacza, że ​​możesz wykorzystać tylko jeden rdzeń. Według mojej najlepszej wiedzy dosłownie nie ma prawdziwych przykładów prawdziwej wielordzeniowej współpracy wielozadaniowej. Taki system byłby głupi, ponieważ uzyskałbyś wszystkie wady współpracy wielozadaniowej bez plusów braku zamków.
Kevin,
10

Blokada jest rodzajem zamka, w szczególności tego uzyskanego przez odpytywanie.

Sondowanie to metoda sprawdzania statusu czegoś (poprzez zapytanie o status, w przeciwieństwie do oczekiwania na status).

Nie wszystkie odpytywanie jest blokadą, na przykład odpytuje status klawiszy klawiatury.


Również odpytywanie nie jest z natury złe. Bardzo krótkie okresy odpytywania pozwalają uniknąć kosztownych przesunięć kontekstu, których wymagałoby użycie przerwań, nie wspominając już o tym, że odpytywanie może czasem być prostsze do wdrożenia, a zatem łatwiejsze w utrzymaniu, szczególnie na niższych poziomach. Jak zwykle, absoluty są okropną rzeczą i powinieneś użyć metody, która zapewnia odpowiedni kompromis wydajności / złożoności dla twoich potrzeb, tak jak je zmierzyłeś , zamiast ślepo używać lub odrzucać opcje.

8bittree
źródło
5

Spinlock różni się od odpytywania, ponieważ występuje tylko przez bardzo krótki czas, rzędu kilku milisekund lub mniej. Sondowanie może trwać bez końca.

W programowaniu równoległym krótki odcinek wirowania jest często lepszy niż blokowanie, ponieważ pozwala uniknąć kosztów przełączania kontekstu i przejścia jądra.

Dalsza lektura
SpinLock i SpinWait w C # Blokady i blokady do
odczytu i zapisu w C

Robert Harvey
źródło
Myślę, że chciałeś powiedzieć mikrosekundy. Dla blokady trwającej całą milisekundę powinniśmy zastosować implementację blokady, która wywołuje konflikt z jądra.
Peter,
@Peter Być może to właśnie oznaczało Albahari. Tak mówi jego tekst.
Robert Harvey
4

Różnica polega na tym, że blokada jest (miejmy nadzieję) używana tylko w sytuacjach, w których jest to właściwe, i w tych sytuacjach jest bardzo skuteczna.

Blokady używasz, jeśli spodziewasz się, że zasób zostanie zablokowany tylko na bardzo krótki czas - na przykład, jeśli blokada jest używana tylko do aktualizacji zmiennej. Blokada odpytuje zamek z maksymalną prędkością, ale mam nadzieję, że krócej niż mikrosekundy. Normalny muteks wymagałby wywołania OS. JEŻELI blokada jest utrzymywana tylko przez krótki czas, wówczas blokada zużywa tylko niewielką ilość czasu procesora, podczas gdy wywołanie systemu operacyjnego potrwa dłużej. Ale jeśli to oczekiwanie jest błędne, wówczas blokada jest bardzo nieefektywna - zużyje 100% czasu procesora na jednym procesorze, podczas gdy normalny muteks zajmuje tylko czas na wejście do systemu operacyjnego i powrót.

Czasami oba są połączone; uruchamiasz blokadę na krótki czas i przełączasz się na inną strategię, jeśli blokada nie działa.

gnasher729
źródło
2

Nadmierne odpytywanie jest czymś, czego nie powinieneś robić, ponieważ marnuje zasoby systemowe. Wynika z tego, że odpytywanie jest w porządku, jeśli nie marnuje zasobów systemowych .

Na przykład nadmierne odpytywanie spowoduje zwiększenie obciążenia procesora do 100% w przypadkach, gdy faktyczna praca spowodowałaby jedynie obciążenie 2%.

Sondowania można używać do innych celów niż while(!ready). Na przykład oznacza to regularne sprawdzanie, czy użytkownik nacisnął klawisz. Rozsądna implementacja będzie sprawdzać najwyżej raz na 15 milisekund, więc jest to jedno sprawdzenie co ~ 20 milionów cykli zegara. Ten rodzaj odpytywania jest świetny, ponieważ nie marnuje zasobów systemowych.

SpinLock nie jest przypadkiem specjalnym. Jeśli mamy SpinLock i jeden wątek wejdzie do blokady, a inny musi czekać, SpinLock jest złym wyborem, jeśli tylko oczekujący wątek marnuje zasoby systemowe. Wątek oczekujący zmarnuje zasoby systemowe wtedy i tylko wtedy, gdy będzie musiał czekać znaczną ilość czasu, zanim będzie mógł uzyskać zamek.

Dlatego używanie SpinLocka do ochrony czegokolwiek, co wymaga kilku tysięcy cykli zegara lub więcej, zanim ponownie się odblokuje (np. Kompilacja i wykonanie fragmentu javascript w locie) jest złe, dokładnie z tego powodu, który podałeś. Ale użycie SpinLocka do ochrony czegoś, co szybko się kończy, na przykład uzyskanie dostępu do prawidłowo zaimplementowanej mapy skrótu jest w porządku, ponieważ oczekujący wątek obraca się tylko 2-3 razy, a zatem nie marnuje zasobów systemowych.

Piotr
źródło