koszt operacji atomowych

Jaki jest koszt operacji atomowej (dowolny z porównań i zamiany lub atomowych add/decrement)? Ile cykli zużywa? Wstrzyma inne procesory na SMP lub NUMA, czy zablokuje dostęp do pamięci? Czy przepuści bufor zmiany kolejności w procesorze out-of-order?

Jakie będą efekty w pamięci podręcznej?

Interesują mnie nowoczesne, popularne procesory: x86, x86_64, PowerPC, SPARC, Itanium.

Author: Peter Cordes, 2010-03-29

3 answers

Szukałem aktualnych danych z ostatnich dni i nic nie znalazłem. Jednak zrobiłem kilka badań, które porównują koszt operacji atomowych z kosztami uszkodzeń pamięci podręcznej.

Koszt prefiksu blokady x86, lub CAS, przed PentiumPro (jak opisano w doc), to dostęp do pamięci (jak brak pamięci podręcznej), + zatrzymanie operacji pamięci przez inne procesory, + wszelkie spory z innymi procesorami próbującymi zablokować magistralę. Jednak od PentiumPro, dla pamięci Writeback (tj. cacheable) (wszystkie pamięć, którą zajmuje się aplikacja, chyba że rozmawiasz bezpośrednio ze sprzętem), zamiast blokować wszystkie operacje na pamięci, blokowana jest tylko odpowiednia pamięć podręczna (na podstawie linku zamieszczonego powyżej).

Właściwie sprawa CAS może być bardziej skomplikowana, jak wyjaśniono na tej stronie, bez terminów, ale wnikliwy opis przez godnego zaufania inżyniera.

Zanim przejdę do zbyt wielu szczegółów, powiem, że zablokowana operacja kosztuje jeden Cache miss + ewentualny spór z innym procesorem na tej samej linii cacheline, podczas gdy CAS + poprzedzające Ładowanie (które jest prawie zawsze wymagane, z wyjątkiem mutexów, gdzie zawsze CAS 0 i 1) może kosztować dwa chybienia pamięci podręcznej.

Wyjaśnia, że load + CAS w jednej lokalizacji może faktycznie kosztować dwa chybienia pamięci podręcznej, takie jak Load-Linked / Store-Conditional(zobacz tam dla tego ostatniego). Jego wyjaśnienie opiera się na znajomości protokołu MESI cache coherence protocol. Używa 4 stanów dla cacheline: M( odified), E (xclusive), S (hared), I (nvalid) (oraz dlatego nazywa się MESI), wyjaśnione poniżej w razie potrzeby. Scenariusz, wyjaśniony, jest następujący:

  • Ładowanie powoduje brak pamięci podręcznej - odpowiednia cacheline jest ładowana z pamięci w stanie współdzielonym (tzn. inne procesory nadal mogą przechowywać tę cacheline w pamięci; żadne zmiany nie są dozwolone w tym stanie). Jeśli lokalizacja znajduje się w pamięci, ta miss pamięci podręcznej jest pomijana. możliwy koszt: 1 Brak pamięci podręcznej. (pomijane, jeśli cacheline jest w stanie współdzielonym, wyłącznym lub zmodyfikowanym, tzn. dane znajdują się w pamięci podręcznej L1 tego procesora).
  • program oblicza nowe wartości do przechowywania,
  • i uruchamia atomową instrukcję CAS.
    • musi unikać jednoczesnej modyfikacji, więc musi usunąć kopie cacheline z pamięci podręcznej innych procesorów, aby przenieść cacheline do stanu wyłącznego. możliwy koszt: 1 Brak pamięci podręcznej. nie jest to potrzebne, jeśli jest już wyłączną własnością, tj. w stanie wyłącznym lub zmodyfikowanym. W obu stanach żaden inny procesor nie posiada cacheline, ale w stanie wyłącznym nie została zmodyfikowana (jeszcze).
    • po tej komunikacji zmienna jest modyfikowana w lokalnej pamięci podręcznej naszego procesora, w którym to momencie jest globalnie widoczna dla wszystkich innych procesorów (ponieważ ich pamięci podręczne są spójne z naszymi). W końcu zostanie zapisany do pamięci głównej zgodnie ze zwykłymi algorytmami.
    • inne procesory próbujące odczytać lub zmodyfikować tę zmienną będą musiały najpierw uzyskać tę cacheline w trybie współdzielonym lub wyłącznym, a w tym celu skontaktuj się z tym procesorem i otrzymaj zaktualizowaną wersję cacheline. Operacja zablokowana może kosztować tylko brak pamięci podręcznej (ponieważ cacheline zostanie zażądana bezpośrednio w stanie wyłącznym).

We wszystkich przypadkach żądanie cacheline może zostać wstrzymane przez inne procesory już modyfikujące dane.

 51
Author: Blaisorblade,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-18 01:04:55

Zrobiłem kilka profilów z następującą konfiguracją: maszyna testowa (AMD Athlon64 x2 3800+) została uruchomiona, przełączona na tryb długi (przerwania wyłączone) i interesująca instrukcja została wykonana w pętli, 100 iteracji rozwiniętych i 1000 cykli pętli. Ciało pętli zostało wyrównane do 16 bajtów. Czas mierzony był instrukcją rdtsc przed i za pętlą. Dodatkowo wykonano pętlę bez instrukcji (która mierzyła 2 cykle na iterację pętli i 14 cykli dla reszta), a wynik został odjęty od wyniku instrukcji czasu profilowania.

Zmierzono następujące instrukcje:

  • "lock cmpxchg [rsp - 8], rdx" (zarówno z porównaniem, jak i niedopasowaniem),
  • "lock xadd [rsp - 8], rdx",
  • "lock bts qword ptr [rsp - 8], 1"

We wszystkich przypadkach mierzony czas wynosił około 310 cykli, błąd wynosił około + / - 8 cykli

Jest to wartość powtarzającego się wykonania na tej samej (buforowanej) pamięci. Przy dodatkowym braku pamięci podręcznej czasy są znacznie wyżej. Również to zostało zrobione tylko z jednym z 2 rdzeni aktywnych, więc pamięć podręczna była wyłącznie własnością, i nie była wymagana synchronizacja pamięci podręcznej.

Aby ocenić koszt zablokowanej instrukcji na brak pamięci podręcznej, dodałem wbinvld instrukcję przed zablokowaną instrukcją i umieściłem wbinvld plus add [rsp - 8], rax W pętli porównawczej. W obu przypadkach koszt wyniósł około 80 000 cykli na parę instrukcji! W przypadku blokady BTS różnica czasu wynosiła około 180 cykli na instrukcję.

Zauważ, że jest to wzajemna przepustowość, ale ponieważ operacje zablokowane są operacjami serializującymi, prawdopodobnie nie ma różnicy w opóźnieniu.

Wniosek: zablokowana operacja jest ciężka, ale brak pamięci podręcznej może być znacznie cięższy. Ponadto: zablokowana operacja nie powoduje braków w pamięci podręcznej. Może powodować ruch synchronizacji pamięci podręcznej tylko wtedy, gdy cacheline nie jest wyłącznie własnością.

Aby uruchomić maszynę, użyłem wersji x64 FreeLdr z projektu ReactOS. Oto źródło asm kod:

#define LOOP_COUNT 1000
#define UNROLLED_COUNT 100

PUBLIC ProfileDummy
ProfileDummy:

    cli

    // Get current TSC value into r8
    rdtsc
    mov r8, rdx
    shl r8, 32
    or r8, rax

    mov rcx, LOOP_COUNT
    jmp looper1

.align 16
looper1:

REPEAT UNROLLED_COUNT
    // nothing, or add something to compare against
ENDR

    dec rcx
    jnz looper1

    // Put new TSC minus old TSC into rax
    rdtsc
    shl rdx, 32
    or rax, rdx
    sub rax, r8

    ret

PUBLIC ProfileFunction
ProfileFunction:

    cli

    rdtsc
    mov r8, rdx
    shl r8, 32
    or r8, rax
    mov rcx, LOOP_COUNT

    jmp looper2

.align 16
looper2:

REPEAT UNROLLED_COUNT
    // Put here the code you want to profile
    // make sure it doesn't mess up non-volatiles or r8
    lock bts qword ptr [rsp - 8], 1
ENDR

    dec rcx
    jnz looper2

    rdtsc
    shl rdx, 32
    or rax, rdx
    sub rax, r8

    ret
 33
Author: Timo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-22 09:23:51

Atomic prefix LOCK zapewnia (włącza) sygnał przewodowy magistrali LOCK#. Zakazuje korzystania z niego innym procesorom/urządzeniom na magistrali.

Ppro & P2 book http://books.google.com/books?id=3gDmyIYvFH4C&pg=PA245&dq=lock+instruction+pentium&lr=&ei=_E61S5ehLI78zQSzrqwI&cd=1#v=onepage&q=lock%20instruction%20pentium&f=false{[6]strony 244-246

Zablokowane instrukcje to serializacja, synchronizacja operacji.... / about Out-of-order / locked RMW/ read-modify-write = Atomic itself / instruction zapewnia, że procesor wykona wszystkie instrukcje przed zablokowaną instrukcją przed jej wykonaniem. / about yet not flushed writes / wymusza to przepłukanie wszystkich zapisów w procesorze do pamięci zewnętrznej przed wykonaniem następnej instrukcji.

/ about SMP / SEMAFOR is in cache in S state... wydanie odczytu i unieważnienia transakcji dla 0 bajtów daty (Jest to kill / udostępnionych kopii linii bufora w sąsiednie Procesory/)

 4
Author: osgx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-02 02:41:05