Jak pamięć podręczna może być tak szybka?

37

Oto zrzut ekranu testu pamięci podręcznej:

Wyniki testu porównawczego pamięci podręcznej i pamięci AIDA64

W teście porównawczym szybkość odczytu pamięci podręcznej L1 wynosi około 186 GB / s, a opóźnienie wynosi około 3-4 cykli zegara. W jaki sposób osiąga się taką prędkość?

Rozważmy tutaj pamięć: teoretyczna maksymalna prędkość wynosi 665 MHz (częstotliwość pamięci) x 2 (podwójna szybkość danych) x 64 bit (szerokość magistrali), co stanowi około 10,6 GB / s, co jest bliższe wartości odniesienia wynoszącej 9,6 GB / s .

Ale z pamięcią podręczną L1, nawet gdybyśmy mogli czytać w każdym cyklu z procesorem przy jego maksymalnej częstotliwości (3 GHz), potrzebowalibyśmy około 496 linii danych, aby osiągnąć taką przepustowość, która brzmi nierealnie. Dotyczy to również innych pamięci podręcznych.

czego mi brakuje? Jak obliczyć przepustowość pamięci podręcznej na podstawie jej parametrów?

Rycerz
źródło
14
czy zastanawiałeś się nad tym, jak mała jest pamięć podręczna L1,2,3 i gdzie jest ona fizycznie zlokalizowana? Wskazówka: nie musisz
przejmować się
2
Ponadto: Czy test porównawczy wie wystarczająco dużo o tym, co robi, aby upewnić się, że niektóre dane, które testuje, nie są przechowywane bezpośrednio w rejestrze?
rackandboneman
7
@rackandboneman: AIDA64 jest szanowanym testem porównawczym, a nie czymś, co ktoś włamał się w C i pozwolił kompilatorowi zoptymalizować niektóre obciążenia! Zakładam, że części znaku microbenchmark są napisane w asemblerze, w wersjach SSE lub AVX.
Peter Cordes,
1
@Peter Cordes satysfakcjonująca odpowiedź - na niezbędne pytanie.
rackandboneman
1
Wystarczy spojrzeć na myśli z perspektywy fizycznej: w 1,4 nanosekundy światło przemieszcza się około półtorej stopy. Oznacza to, że jeśli pamięć podręczna znajduje się po drugiej stronie płyty głównej, takie opóźnienie może przerwać względność. Lub być błędem pomiaru .
Arthur

Odpowiedzi:

35

Ten procesor ma ...

2 rdzenie Instrukcja 32 KB i pamięć podręczna pierwszego poziomu 32 KB dla każdego rdzenia

Ponieważ istnieją dwa rdzenie, możemy oczekiwać, że test porównawczy uruchomi dwa wątki równolegle. Ich strona internetowa zawiera jednak niezwykle niewiele informacji, ale jeśli spojrzymy tutaj , procesory z większą liczbą rdzeni wydają się zapewniać odpowiednio wyższą przepustowość L1. Myślę więc, że wyświetlany jest całkowity przepływ przy wszystkich rdzeniach pracujących równolegle. Tak więc dla twojego procesora powinniśmy podzielić przez dwa dla jednego rdzenia i jednej pamięci podręcznej:

Read   93 GB/s
Write  47 GB/s
Copy   90 GB/s

Teraz fakt, że „kopiowanie” jest 2x szybszy niż „pisanie”, jest wysoce podejrzany. Jak może kopiować szybciej, niż potrafi pisać? Założę się, że to, co test porównawczy wyświetla jako „kopiowanie”, jest sumą przepustowości odczytu + zapisu, w tym przypadku zarówno czytałby, jak i zapisywał z prędkością 45 GB / s, ale wyświetlałby 90, ponieważ jest to test porównawczy i kto do diabła ufa testom? Zignorujmy więc „kopiuj”.

Read   93 GB/s => 30 bytes/clock
Write  47 GB/s => 15 bytes/clock

Teraz jeden rejestr 128-bitowy ma 16 bajtów, wystarczająco blisko, więc wygląda na to, że ta pamięć podręczna może wykonać dwa 128-bitowe odczyty i jeden zapis na zegar.

To jest dokładnie to, co naprawdę chcesz usprawnić te instrukcje dotyczące łamania liczb SSE: dwa odczyty i jeden zapis na cykl.

Najprawdopodobniej byłoby to zaimplementowane z wieloma równoległymi liniami danych, co jest zwykłym sposobem na bardzo szybkie przenoszenie dużej ilości danych wewnątrz mikroukładu.

peufeu
źródło
4
Na stronie 55 dokumentu @ next-hack linki do niego brzmią: „Dostęp wewnętrzny ma do 16 bajtów. [...] W każdym cyklu można obsługiwać dwie operacje ładowania i jedną operację przechowywania”. To wyjaśnia, dlaczego odczyt jest dwa razy szybszy - może wykonać dwa odczyty w tej samej operacji, jednocześnie wykonując jeden zapis.
Tom Carpenter
2
Tak, wyraźnie liczy się kopia BW = odczyt i zapis. Wydaje się to tak samo ważne jak alternatywa, ponieważ jest wskazane, że odczyty i zapisy mogą być wykonywane równolegle. Zauważ, że liczby OP dla L2 / L3 mają kopię niewiele wyższą niż zapis, a niższą dla pamięci. Magistrala pamięci DDR3 nie ma pełnego dupleksu: te same linie danych są potrzebne do odczytu i zapisu. (Więcej informacji na temat przepustowości memcpy / memset x86 w sklepach NT w porównaniu ze zwykłymi sklepami można znaleźć na stronie stackoverflow.com/questions/43343231/... ).
Peter Cordes,
6
Zgadujesz, że IvyBridge może wykonać 2 odczyty i 1 zapis w tym samym cyklu zegara. Masz rację, ale tylko w bardzo ograniczonych okolicznościach. IvB ma tylko 2 porty AGU, więc zwykle ogranicza się do 2 operacji pamięci na zegar, z których jeden może być sklepem . Ale 256b AVX ładuje / przechowuje zajmuje 2 cykle, aby wykonać w portach ładowania / przechowywania, podczas gdy potrzebuje tylko AGU w pierwszym cyklu. Zatem UOP adresu sklepu może działać na porcie 2/3 podczas drugiego cyklu obciążenia 256b bez kosztowania przepustowości obciążenia. ( Ups -przechowywania danych działają na porcie 4.) Źródło: agner.org/optimize microarch pdf
Peter Cordes
2
Rodzina procesorów AMD Bulldozer lub Ryzen dałaby ci taki sam odczyt = 2x liczba zapisów, ale tak naprawdę są one ograniczone do 2 operacji pamięci na zegar (maksymalnie jeden może być zapis) bez żadnych luk. odczyt / zapis / kopia nie wykrywa różnicy, ale Triad może ( a[i] = b[i] + c[i]). BTW, Intel Haswell, a później mają AGU magazynu na porcie 7, który może obsługiwać proste (nieindeksowane) tryby adresowania, dzięki czemu mogą wykonywać 2 obciążenia + 1 zapisy w pamięci na zegar. (Ścieżka danych do L1D to 256b, więc podwaja przepustowość L1D.) Zobacz zapis Davida Kantera: realworldtech.com/haswell-cpu/5
Peter Cordes
1
@AliChen: OP wyraźnie wspomniał o 4-cyklowym opóźnieniu obciążenia IvyBridge zaraz po przepustowości, zanim zapytał, jak może być tak szybki.
Peter Cordes,
27

Odpowiedź @ peufeu wskazuje, że są to ogólnosystemowe łączne przepustowości. L1 i L2 to prywatne pamięci podręczne na rdzeń w rodzinie Intel Sandybridge, więc liczby są dwa razy większe niż jeden rdzeń. Ale to wciąż pozostawia nam imponująco wysoką przepustowość i niskie opóźnienia.

Pamięć podręczna L1D jest wbudowana bezpośrednio w rdzeń procesora i jest bardzo ściśle sprzężona z jednostkami wykonującymi obciążenie (i buforem pamięci) . Podobnie pamięć podręczna L1I znajduje się tuż obok części pobierania / dekodowania instrukcji rdzenia. (Właściwie nie spojrzałem na krzemowy plan podłogi Sandybridge, więc może to nie być dosłownie prawda. Część wydania / zmiany nazwy w interfejsie jest prawdopodobnie bliższa zdekodowanej pamięci podręcznej UOP, która oszczędza energię i ma lepszą przepustowość niż dekodery).

Ale z pamięcią podręczną L1, nawet jeśli moglibyśmy czytać w każdym cyklu ...

Po co się tu zatrzymywać? Intel od Sandybridge i AMD, ponieważ K8 może wykonywać 2 obciążenia na cykl. Wieloportowe pamięci podręczne i TLB to coś.

Zapis mikroarchitektury Davida Kantera w Sandybridge ma ładny schemat (który dotyczy również twojego procesora IvyBridge):

(„Ujednolicony program planujący” wstrzymuje operacje ALU i zmiany pamięci czekające na gotowe dane wejściowe i / lub oczekiwanie na ich port wykonawczy. (Np. vmovdqa ymm0, [rdi]Dekoduje do zmiany obciążenia, która musi poczekać, rdijeśli poprzednie add rdi,32jeszcze nie zostało wykonane, dla przykład). Intel planuje zrzuty do portów w momencie wydania / zmiany nazwy . Ten diagram pokazuje tylko porty wykonania dla zrzutu pamięci, ale również niewykonane kopie ALU również o to konkurują. Stopień wydania / zmiany nazwy dodaje zrzuty do ROB i harmonogramu Pozostają w ROB do wycofania, ale w harmonogramie tylko do wysyłki do portu wykonawczego (to terminologia Intela; inne osoby używają wystawiania i wysyłania inaczej). AMD stosuje osobne harmonogramy dla liczb całkowitych / FP, ale tryby adresowania zawsze używają rejestrów liczb całkowitych

Schemat pamięci SnB Davida Kantera

Jak to pokazuje, istnieją tylko 2 porty AGU (jednostki generujące adresy, które przyjmują tryb adresowania jak [rdi + rdx*4 + 1024]i wytwarzają adres liniowy). Może wykonywać 2 operacje pamięci na zegar (po 128b / 16 bajtów każdy), przy czym jeden z nich jest sklepem.

Ale ma swoją sztuczkę: SnB / IvB uruchamia 256b AVX ładuje / przechowuje jako pojedynczy pakiet, który zajmuje 2 cykle w porcie ładowania / przechowywania, ale potrzebuje tylko AGU w pierwszym cyklu. Pozwala to na uruchomienie UOP adresu sklepu na AGU na porcie 2/3 podczas tego drugiego cyklu bez utraty przepustowości obciążenia. Dzięki AVX (który nie obsługuje procesorów Intel Pentium / Celeron: /), SnB / IvB może (teoretycznie) wytrzymać 2 obciążenia i 1 sklep na cykl.

Twój procesor IvyBridge jest znacznie mniejszy od Sandybridge (z pewnymi ulepszeniami mikroarchitekturalnymi, takimi jak eliminacja mov , ERMSB (memcpy / memset) i wstępne pobieranie sprzętu na następnej stronie). Generacja po tym (Haswell) podwoiła przepustowość L1D na zegar, rozszerzając ścieżki danych z jednostek wykonawczych do L1 z 128b do 256b, aby obciążenia AVX 256b mogły utrzymać 2 na zegar. Dodano także dodatkowy port AGU sklepu dla prostych trybów adresowania.

Szczytowa przepustowość Haswell / Skylake wynosi 96 bajtów + zapisanych na zegar, ale podręcznik optymalizacji Intela sugeruje, że średnia średnia wydajność Skylake (przy założeniu braku błędów L1D lub TLB) wynosi ~ 81B na cykl. (Skalarna pętla liczb całkowitych może wytrzymać 2 obciążenia + 1 pamięć na zegar zgodnie z moimi testami na SKL, wykonując 7 (unused-domain) uops na zegar z 4 uops w domenie fused. Ale zwalnia nieco z 64-bitowymi operandami zamiast 32-bit, więc najwyraźniej istnieje pewien limit zasobów mikroarchitektonicznych i nie jest to tylko kwestia planowania zmian adresu sklepu do portu 2/3 i kradzieży cykli z obciążeń).

Jak obliczyć przepustowość pamięci podręcznej na podstawie jej parametrów?

Nie możesz, chyba że parametry obejmują praktyczne liczby przepustowości. Jak wspomniano powyżej, nawet L1D Skylake nie nadąża za jednostkami wykonawczymi ładowania / przechowywania dla wektorów 256b. Chociaż jest blisko i może mieć 32-bitowe liczby całkowite. (Nie ma sensu mieć więcej jednostek ładujących niż pamięć podręczna miała porty do odczytu lub odwrotnie. Po prostu pomijałby sprzęt, którego nigdy nie można w pełni wykorzystać. Zauważ, że L1D może mieć dodatkowe porty do wysyłania / odbierania linii do / z innych rdzeni, a także do odczytu / zapisu z wnętrza rdzenia.)

Samo spojrzenie na szerokości i zegary magistrali danych nie daje ci całej historii. Przepustowość L2 i L3 (i pamięci) może być ograniczona liczbą zaległych braków, które L1 lub L2 mogą śledzić . Przepustowość nie może przekroczyć opóźnienia * max_concurrency, a układy z wyższym opóźnieniem L3 (podobnie jak wielordzeniowy Xeon) mają znacznie mniejszą przepustowość jednordzeniowego L3 niż dwurdzeniowy / czterordzeniowy procesor tej samej mikroarchitektury. Zobacz sekcję „Platformy związane z opóźnieniami” w tej odpowiedzi SO . Procesory z rodziny Sandybridge mają 10 buforów wypełniania linii do śledzenia braków L1D (używanych również w sklepach NT).

(Łączna przepustowość L3 / pamięci z wieloma aktywnymi rdzeniami jest ogromna na dużym Xeonie, ale jednowątkowy kod widzi gorsze pasmo niż na czterordzeniowym rdzeniu przy tej samej szybkości zegara, ponieważ więcej rdzeni oznacza więcej przystanków na szynie pierścieniowej, a zatem wyższe opóźnienie L3.)


Opóźnienie pamięci podręcznej

W jaki sposób osiąga się taką prędkość?

Opóźnienie 4-cyklowego ładowania pamięci podręcznej L1D jest dość niesamowite , szczególnie biorąc pod uwagę, że musi zacząć się od trybu adresowania takiego jak [rsi + 32], więc musi dodać, zanim będzie miał adres wirtualny . Następnie musi to przełożyć na język fizyczny, aby sprawdzić dopasowanie tagów pamięci podręcznej.

(Tryby adresowania inne niż [base + 0-2047]dodatkowy cykl w rodzinie Intel Sandybridge, więc w AGU znajduje się skrót do prostych trybów adresowania (typowe dla przypadków ścigania wskaźnika, gdzie prawdopodobnie małe opóźnienie użycia obciążenia jest najważniejsze, ale także ogólnie) (Zobacz Podręcznik optymalizacji Intela , sekcja Sandybridge 2.3.5.2 L1 DCache.) Zakłada to również brak zastąpienia segmentu i adres podstawowy segmentu 0, co jest normalne.)

Musi także sondować bufor sklepu, aby sprawdzić, czy pokrywa się on z wcześniejszymi sklepami. I musi to rozgryźć, nawet jeśli wcześniejszy (w kolejności programowej) adres sklepu nie został jeszcze wykonany, więc adres sklepu nie jest znany. Ale przypuszczalnie może się to zdarzyć równolegle ze sprawdzeniem trafienia L1D. Jeśli okaże się, że dane L1D nie były potrzebne, ponieważ przekazywanie do sklepu może dostarczyć dane z bufora sklepu, to nie jest to strata.

Intel używa pamięci podręcznej VIPT (wirtualnie indeksowane fizycznie oznaczone) jak prawie wszyscy inni, stosując standardową sztuczkę polegającą na tym, że pamięć podręczna jest wystarczająco mała i ma wystarczająco duże skojarzenie, aby zachowywała się jak pamięć podręczna PIPT (bez aliasingu) z prędkością VIPT (może indeksować w równolegle z wirtualnym> fizycznym wyszukiwaniem TLB).

Pamięci podręczne L1 Intela są 32kB, 8-kierunkowe asocjacyjne. Rozmiar strony to 4kiB. Oznacza to, że bity „indeksu” (które wybierają zestaw 8 sposobów buforowania dowolnej linii) znajdują się poniżej przesunięcia strony; tzn. te bity adresu są przesunięciem na stronę i zawsze są takie same w adresie wirtualnym i fizycznym.

Aby uzyskać więcej informacji na temat tego i innych szczegółów, dlaczego małe / szybkie pamięci podręczne są przydatne / możliwe (i działają dobrze, gdy są sparowane z większymi wolniejszymi pamięciami podręcznymi), zobacz moją odpowiedź, dlaczego L1D jest mniejszy / szybszy niż L2 .

Małe pamięci podręczne mogą robić rzeczy, które byłyby zbyt drogie w przypadku większych pamięci podręcznych, takie jak pobieranie tablic danych z zestawu w tym samym czasie, co pobieranie tagów. Kiedy więc komparator znajdzie odpowiedni pasujący tag, musi po prostu zmiksować jedną z ośmiu 64-bajtowych linii pamięci podręcznej, które zostały już pobrane z SRAM.

(To nie jest tak proste: Sandybridge / Ivybridge używają buforowanej pamięci podręcznej L1D z ośmioma bankami po 16 bajtów. Możesz uzyskać konflikty między pamięcią podręczną, jeśli dwa wejścia do tego samego banku w różnych liniach pamięci podręcznej spróbują wykonać w tym samym cyklu. (Istnieje 8 banków, więc może się tak zdarzyć w przypadku adresów o wielokrotności 128, tj. 2 linii pamięci podręcznej).

IvyBridge nie ma również kary za niezaangażowany dostęp, o ile nie przekroczy granicy linii pamięci podręcznej 64B. Wydaje mi się, że określa, które banki należy pobrać na podstawie niskich bitów adresu i konfiguruje wszelkie zmiany, jakie będą musiały się zdarzyć, aby uzyskać prawidłowe 1 do 16 bajtów danych.

W przypadku podziału linii pamięci podręcznej nadal jest to tylko jedna poprawka, ale umożliwia dostęp do wielu pamięci podręcznej. Kara jest wciąż niewielka, z wyjątkiem podziału na 4k. Skylake sprawia, że ​​nawet 4k podziały są dość tanie, z opóźnieniem około 11 cykli, tak samo jak normalny podział linii pamięci podręcznej ze złożonym trybem adresowania. Ale przepustowość przy podziale na 4k jest znacznie gorsza niż przy podziale na cl bez podziału.


Źródła :

Peter Cordes
źródło
1
To bardzo jasne, wyczerpujące i dobrze napisane! +1!
następny hack
8

W nowoczesnych procesorach pamięć podręczna znajduje się tuż obok procesora na tej samej matrycy (chipie) , jest wykonana za pomocą SRAM, który jest znacznie, znacznie szybszy niż DRAM, który jest używany dla modułów RAM w komputerze.

Na jednostkę pamięci (bitową lub bajtową) SRAM jest znacznie droższy niż DRAM. Właśnie dlatego DRAM jest również używany w komputerze.

Ale ponieważ SRAM jest wykonany w tej samej technologii co sam procesor, jest tak szybki jak procesor. Do rozwiązania są tylko magistrale wewnętrzne (na CPU), więc jeśli musi to być magistrala o szerokości 496 linii, prawdopodobnie tak jest.

Bimpelrekkie
źródło
Dzięki za zainteresowanie. Widziałem w kilku książkach stwierdzających, że prędkości dostępu do rejestru przekraczają 300 GB / s, w którym przypadku procesora 3 GHz przepustowość rejestru wynosi 100 B / cykl, co nie jest możliwe, ponieważ rejestry mają zwykle szerokość 64/128 bitów, nie mogli wyprodukować tyle. To mnie dotyczy. Czy GB / sa to właściwy sposób na wyrażenie przepustowości.
Knight
3
@Knight pamiętaj, że IvB (jak każdy procesor o wysokiej wydajności) wykonuje kilka instrukcji na cykl, takich jak 3 operacje ALU, 2 obciążenia i 1 sklep. Większość z nich może przyjąć 2 dane wejściowe (nawet obciążenia, adresowanie indeksowane), a obciążenie nawet zajmuje 3. To 13 rejestrów po 8 bajtów każdy, 104 bajty (mogło być tak, że taka epicka kombinacja jest niedozwolona, ​​ale tam nie oznacza, że ​​tak jest w przypadku IvB, choć nie można tego utrzymać). Jeśli weźmiesz również pod uwagę rejestry wektorowe, liczba ta wzrośnie jeszcze bardziej.
Harold
@harold: spokrewnione: Haswell i Skylake wydają się mieć ograniczenia odczytu rejestrów na zegar, chociaż może to być w interfejsie i nie wpływa na przyspieszenie wykonania po przygotowaniu niektórych danych wejściowych. Może to jakiś inny limit mikroarchitektoniczny, ale znalazłem wąskie gardła w kodzie, które powinny być w stanie utrzymać więcej operacji na zegar. agner.org/optimize/blog/read.php?i=415#852 . W Haswell mój najlepszy scenariusz to odczyt ~ 6 rejestrów liczb całkowitych na cykl zegara (podtrzymany). Udało mi się również uzyskać 7 Uopsów za wysłanie / wykonanie zegara na Skylake (sklepy to adres sklepu + dane sklepu).
Peter Cordes,
@PeterCordes, które muszą być front-endem, prawda? IIRC to był również problem historycznie (PPro do Core2) i nie jestem pewien, w jaki sposób liczby ułamkowe mają sens inaczej. Chociaż i tak moje liczby były trochę nie tak
Harold
@harold: tak, jestem prawie pewien, że jest to jakieś wąskie gardło front-endu, prawdopodobnie zmieniające nazwę. Wąskie gardło P6 w zakresie odczytu rejestrów dotyczyło „zimnych” rejestrów, które należało odczytać z pliku rejestru stałego do spornego ROB. Ostatnio zmodyfikowane rejestry nadal znajdowały się w ROB i nie było w tym wąskiego gardła. Nie badałem dużo z zimnymi kontra gorącymi regami na HSW / SKL, ponieważ z jakiegoś powodu nie pomyślałem o tym, aby moja pętla była większa niż 4 uops / idealnie 1c na iterację. ups. IDK, jaka jest różnica między odczytami przekazywania a odczytami PRF (które muszą się zdarzyć w czasie wykonywania, a nie wydania / zmiany nazwy).
Peter Cordes,
4

Pamięci podręczne L1 są dość szerokimi strukturami pamięci. Architekturę pamięci podręcznych L1 w procesorach Intel można znaleźć w tym podręczniku (dostarczonym przez hack next). Jednak interpretacja niektórych parametrów jest nieprawidłowa, „rozmiar linii pamięci podręcznej” nie jest „szerokością danych”, jest to rozmiar szeregowego bloku dostępu do danych atomowych.

Tabela 2-17 (sekcja 2.3.5.1) wskazuje, że przy obciążeniach (odczytach) szerokość pasma pamięci podręcznej wynosi 2x16 = 32 bajtów na rdzeń na CYCLE . To samo daje teoretyczną przepustowość 96 Gb / s na rdzeniu 3GHz. Nie jest jasne, co przytacza cytowany test porównawczy, wygląda na to, że mierzy dwa rdzenie pracujące równolegle, więc robi 192 Gb / s dla dwóch rdzeni.

Ale..chenski
źródło
2

Opóźnienia bramy są co? 10 pikosekund? Czasy cyklu dla całych operacji potokowych wynoszą 333 pikosekundy, z różnymi czynnościami dekodowania i magistrali oraz przechwytywania danych typu flip-flop przed rozpoczęciem następnego cyklu zegara.

Oczekuję, że najwolniejsza aktywność w czytaniu pamięci podręcznej czeka, aż dane odejdą wystarczająco daleko od siebie (prawdopodobnie są to różnice: jedno odniesienie i jedno rzeczywiste ładowanie z bitu odczytu), że komparator / zatrzask można taktować, aby zaimplementować dodatnią- sprzężenie zwrotne w celu przekształcenia niewielkiego napięcia w duże wahanie napięcia między szynami (około 1 wolta).

analogsystemsrf
źródło
1
Należy pamiętać, że 4-cyklowe opóźnienie L1D obejmuje generowanie adresu (w przypadku prostych trybów adresowania [reg + 0-2047]) oraz wyszukiwanie TLB i porównanie znaczników (8-kierunkowe asocjacyjne), a także umieszczanie wynikowych maksymalnie 16 niezrównanych bajtów na port wyjściowy jednostki ładującej, do przekazywania do innych jednostek wykonawczych. To opóźnienie 4c dla pętli ścigającej wskaźnik mov rax, [rax].
Peter Cordes,