Dlaczego nie mamy więcej rejestrów w mikroprocesorach?

18

Rejestry teoretycznie nie są wymagane; wszystkie mikroprocesory nadal działałyby bez rejestrów. Ale ten pozornie trywialny dodatek pomógł zwiększyć wydajność mikroprocesorów.

Dlaczego nie możemy mieć więcej rejestrów, aby dalej czerpać z nich korzyści? Są tylko pamięcią na chipie i można sobie wyobrazić, że nie jest to trudne do dodania? Jaki czynnik wpłynął na liczbę rejestrów, jaka jest teraz, a nie, powiedz 10 razy więcej?

Darszan Chaudhary
źródło
8
@ Alper91 Wiele architektur, hipotetycznych i rzeczywistych, nie ma rejestrów i wcale nie jest konieczne. To po prostu przydatna optymalizacja.
rura
4
Hmm Nikt nie wspominał o Sparku. Największa implementacja może mieć w niej 520 rejestrów (32 okna razy 16 rejestrów, + 8 globali.) Na pewno je pamiętam.
jonk
13
Myślę, że liczba bitów w instrukcji, którą musisz podać w rejestrze, jest dużym problemem. Jeśli masz 1024 rejestry, potrzebujesz co najmniej 30 bitów na każdą instrukcję arytmetyczną - chyba że dodasz inne ograniczenia, takie jak „wszystkie 3 rejestry muszą należeć do tej samej grupy 32 (w takim przypadku potrzebujesz 20 bitów).
user253751
8
@pipe - właściwie praktycznie każdy praktyczny projekt wymaga „rejestrów” w sensie schematycznym, ponieważ nawet jeśli budujesz maszynę stosową lub coś w tym rodzaju, musisz mieć miejsce na przechowywanie argumentów na ALU lub na wyjściu - większość pamięci nie ma trzech portów dostępu. A maszyna stosu potrzebuje wskaźnika stosu, który jest ... rejestrem! I nie wspominając o rejestrach potokowych. Możesz ukryć użycie takich „rejestrów” przed programistą, ale nadal potrzebujesz niektórych, a prawdopodobnie prawie tyle, ile ma prymitywna maszyna rejestrująca.
Chris Stratton,
4
@ChrisStratton Pewnie, ale dopóki nie zostaną ujawnione przez ISA, jest to po prostu szczegół implementacji. Nieco bezsensowny argument, ponieważ nie wiemy, co OP oznacza przez rejestr .
rura

Odpowiedzi:

33

Istnieje kilka czynników:

  • wysokowydajne mikrotechniczne wykorzystują zmianę nazw rejestrów. Oznacza to, że liczba rejestrów fizycznych jest większa niż liczba rejestrów widocznych architektonicznie i są one w stanie śledzić ich niezależne wykorzystanie.

  • podwojenie liczby rejestrów nie podwaja wydajności. ISTR (z architektury komputerowej, podejście ilościowe ), że przejście z 16 do 32 rejestrów przynosi coś w rodzaju 10% poprawy przy założeniu, że wzrost nie ma negatywnego wpływu (co jest bardzo optymistycznym założeniem).

  • architektonicznie widoczne rejestry mają koszty. Na przykład:

    • Zwiększenie ich liczby powoduje zwiększenie liczby bitów pobranych w formacie instrukcji, aby wskazać, na który rejestr działa. dłuższy rozmiar instrukcji).
    • Zwiększenie liczby rejestrów architektonicznych zwiększa koszt przełączania kontekstu (ponieważ należy je zapisać i przywrócić w przełączniku kontekstu).
AProgrammer
źródło
1
Założę się, że poprawa wydajności 16 do 32 rejestrów zależy całkowicie od potencjału optymalizacji danego kompilatora. W asemblerze, dostęp do podwojonej liczby rejestrów (w architekturze x64) może znacznie poprawić wydajność - ale tylko w przypadku niszowych ról i tylko wtedy, gdy są one faktycznie używane.
rdtsc
6
@rdtsc: przejście z 8 do 16 rejestrów architektonicznych daje dużą poprawę w zakresie ilości wycieków / przeładowań dla typowego kodu, zgodnie z danymi z symulacji w dokumencie powiązanym z tą odpowiedzią . Wpływa to na rozmiar kodu, liczbę instrukcji oraz na znaczenie przekazywania w sklepie z niskim opóźnieniem. 16-> 32 to znacznie mniejszy efekt. AFAICT, 16 rejestrów architektonicznych jest dobrym wyborem dla sprzętu z przemianowaniem rejestru w celu usunięcia zagrożeń WAR i WAW.
Peter Cordes,
2
Jednak AVX512 Intela dodaje 16 kolejnych wektorów, co daje w sumie 32. (Oprócz podwojenia ich szerokości do 64 bajtów, pełna linia pamięci podręcznej). Ukrywanie opóźnień w operacjach FP o wysokiej przepustowości i dużych opóźnieniach może zająć wiele rejestrów. np. Intel Haswell ma 5c lat, jeden na przepustowość 0,5c FMA, więc potrzebujesz 10 wektorowych akumulatorów do nasycenia jednostek wykonawczych FMA w celu zmniejszenia (np. iloczynu lub sumowania tablicy, gdzie FMA jest częścią zależności przenoszonej przez pętlę ). x86-64 ma tylko 16 wektorów. Ale pamiętajcie, całkowite operacje, szczególnie. na rejestrach GP rzadko mają opóźnienie większe niż 1c.
Peter Cordes,
1
Kompromis jest różny dla rejestrów liczb całkowitych, rejestrów FP i wektorów. Na przykład leniwe zapisywanie / przywracanie rejestrów liczb całkowitych nie ma sensu, robienie tego dla wektora jest znacznie lepszym rozwiązaniem. I wektor ISA ma często więcej rejestrów niż liczba całkowita (AltiVec ma co najmniej 128, ISTR przeczytał około 256 dla Sparca, ale nie może teraz znaleźć odniesienia).
AProgrammer
1
en.wikipedia.org/wiki/AltiVec ma trzydzieści dwa rejestry wektorowe 128b. Zainteresowałem się SPARC i sprawdziłem, jak działa okno rejestrów dla przełączników kontekstu. Ma 32 rejestry widoczne jednocześnie, ale używa przesuwanego okna na większy plik rejestru. Wydaje się, że z tej uproszczonej wersji system operacyjny musi znać rozmiar całego pliku rejestru przesuwnego okna, aby go zapisać / przywrócić, ponieważ nawet jeśli instrukcje przesuwania okna zapewniają pamięć do zapisywania / przywracania rejestrów w razie potrzeby, odbywa się to poprzez pułapkowanie do systemu operacyjnego.
Peter Cordes,
16

Rejestry i pamięć RAM są pamięcią, ale dostęp do nich można uzyskiwać na różne sposoby, aby odzwierciedlić koszt (w obszarze chipa lub ukrytych cykli zegara) dostępu do nich.

Rejestry są ściśle powiązane z ALU i mogą pełnić wiele ról w źródłach danych, ujściach, modyfikatorach itp. Potrzebują zatem wielu szerokich multipleksowanych połączeń. W niektórych architekturach możemy napisać R1 <= R2 + R3, i to właśnie dzieje się w jednym cyklu zegara. Każdy rejestr jest adresowany bezpośrednio w kodzie operacyjnym, adresowanie to jest bardzo ograniczonym zasobem.

Ponieważ rejestry są kosztowne w implementacji, w większości architektur liczba jest zwykle ograniczona do 10/20.

Pamięć RAM jest luźno związana z procesorem, zwykle jest kierowana przez jedno wspólne połączenie. To sprawia, że ​​znacznie tańsze jest wdrażanie dużej ilości pamięci RAM. Adresy RAM generalnie pochodzą z adresu zapisanego w rejestrze, więc nie zużywaj znacznej szerokości instrukcji.

SPARC jest interesującą architekturą z 72 do 640 64-bitowymi rejestrami, z kontekstem 32 rejestrów, który można przesuwać z nakładaniem się dla szybkich wywołań podprogramów z przekazywaniem parametrów. Zwykle nie można ich znaleźć na komputerach PC i serwerach, gdzie koszty są ważne, jak w 99,999% aplikacji.

Neil_UK
źródło
4
Innym aspektem jest zapisywanie / przywracanie rejestrów podczas przełączania kontekstu. Więcej rejestrów, więcej czasu.
Michel Billaud,
Chciałbym zauważyć, że stary TMS9900 zachowywał wszystkie działające rejestry w pamięci zewnętrznej en.wikipedia.org/wiki/Texas_Instruments_TMS9900
Peter Smith
1
Kwalifikowałem się „niezmiennie” za pomocą (z wyjątkiem kilku poprawek), ale wyjąłem go, aby go uprościć. Być może po prostu zmienię to na „ogólnie”. Zasadniczo, jeśli potrafisz znaleźć i zrozumieć wyjątki, nie potrzebujesz, żebym je wskazał. Jeśli jesteś wystarczająco młody, aby zostać wprowadzonym w błąd, nie ma to znaczenia, ponieważ nie wpędzi cię w kłopoty. TMS9900, to było dziwne, miałem 99/4 za moje grzechy we wcześniejszym życiu, dziwna bestia!
Neil_UK
Itanium ma również okna rejestrów.
Simon Richter,
1
@ChrisStratton: Chociaż istnieje pewien precedens dla „nie można używać rejestrów X i Y” uważanych za część „ABI” (np. Rejestry k0 i k1 na mipsach), jest to niezwykłe użycie. Z pewnością istnieją niechciane / niebezpieczne ukryte kanały przesyłania wiadomości między procesami, jeśli zapis / przywracanie tych „rejestrów zabronionych przez ABI” nie jest wykonywane przy przełączaniu kontekstu. Oznacza to, że procesy, które nie powinny być w stanie się komunikować, mogą to robić przez przechowywanie informacji w zabronionych rejestrach i czekanie na przełączniki kontekstu.
R ..
12

Rejestry muszą być adresowane w instrukcji. Jeśli jest dużo rejestrów, instrukcja jest dłuższa. Zapisywanie i przywracanie zawartości rejestru dla usługi przerwania wymaga więcej czasu, jeśli jest dużo rejestrów.

Uwe
źródło
5

Jak większość rzeczy, liczba rejestrów stanowi kompromis między kosztem, złożonością i użytecznością.

Rejestry są implementowane jako wieloportowa statyczna pamięć RAM, co czyni je bardziej kosztownymi (obszar chipa) niż inne opcje przechowywania.

Następnie są one sprzężone z zestawem instrukcji procesora, zwiększenie liczby rejestrów zwiększa złożoność zestawu instrukcji. Więc jeśli chcesz zachować zgodność z zestawem instrukcji, nie możesz po prostu zwiększyć liczby rejestrów dostępnych w następnej generacji procesorów w celu zwiększenia wydajności, programy ich nie wykorzystają.

Następnie, ile rejestrów naprawdę potrzebujesz? Ich użyteczność jest ograniczona. Rozważ, że piszesz algorytm, który wykonuje pewne operacje matematyczne na 1024 bajtach, powiedzmy, pomnóż przez 5. Przy bieżącej liczbie rejestrów powstaje coś takiego:

load operand1=5
load address
loop: load operand2=byte1@address
multiply Register1 with Register2
store result
increment address
if address = end goto endLoop
jump loop
endLoop:

Teraz, gdybyś miał 1024 rejestry i wszystkie dane tam przechowywane, twój program wyglądałby następująco:

multiply Register1 with Register2
multiply Register1 with Register3
multiply Register1 with Register4
multiply Register1 with Register5
multiply Register1 with Register6
...

Ponieważ każdy z nich jest inną instrukcją, każdy z nich musi zostać zapisany. Twoja potrzebna pamięć programu eksploduje. Po realizacji tego, warto przedstawić kilka wskazówek jak, multiply register1 with register(2 to 256). Ale kiedy przestaniesz, czy podajesz instrukcje dla wszystkich kombinacji?

Być może więc liczby, które obecnie mamy, są dobrym kompromisem między kosztem, złożonością i użytecznością.

Arsenał
źródło
1
Myślę, że program multiply Register1 with Register2 multiply Register1 with Register3jest bardzo nierealny, ponieważ dane musiały pochodzić bezpośrednio lub pośrednio spoza komputera, więc rejestry muszą zostać załadowane, a wyniki muszą być użyte gdzieś, bezpośrednio lub pośrednio, więc rejestry muszą być przechowywane. W rzeczywistości przyzwoity kompilator optymalizujący dla języka wysokiego poziomu „rozwinie” pętlę pierwszego programu, tworząc coś w rodzaju drugiego programu, optymalizując wykorzystanie rejestru, opóźnienie pamięci, być może zajętość pamięci podręcznej i szybkość wykonywania.
żaglowiec
1
Nie ma potrzeby korzystania z wielu multiply register1 with register(2 to 256)instrukcji specjalnego przeznaczenia . Rurociągi znacznie poprawiają przepustowość procesora, szczególnie w celu łatwiejszego dekodowania i wykonywania instrukcji. Tak więc efekt złożonych, masywnych instrukcji odmian można uzyskać, stosując kilka prostszych instrukcji o wyższym wskaźniku wykonania. Większa liczba rejestrów pomaga kompilatorowi w generowaniu wielu niezależnych instrukcji (takich, które nie współużytkują rejestru), które można wykonać niezależnie, poprawiając przepustowość. Twój przykład = więcej rejestrów jest lepszych.
żaglowiec
4

Rejestry są bardzo drogie. Bardzo drogi. To nie tyle same rejestry, co wszystkie połączenia zi do rejestrów. Powiedzmy, że masz instrukcję reg1 = reg2 + reg3. Aby szybko to zaimplementować , musisz odczytać dane z dwóch rejestrów w jednym cyklu i zapisać w innym rejestrze w drugim cyklu. Teraz, jeśli masz procesor, który może wykonać wiele instrukcji na cykl, powiedzmy trzy instrukcje, będziesz musiał móc odczytać dane z sześciu rejestrów w każdym cyklu i zapisać dane do 3 rejestrów. To okropnie dużo bardzo szybkich połączeń.

Oczywiście możesz po prostu użyć więcej tranzystorów. Problem polega na tym, że prędkość spada. Potrzebujesz więcej sprzętu, aby wybierać spośród większej liczby rejestrów. Miejsce na plik rejestru staje się większe. Wszystko to sprawia, że ​​wszystko działa wolniej. Tak więc z tą samą technologią możesz mieć 16 rejestrów i pracować z częstotliwością 2600 MHz lub 32 rejestry i pracować z częstotliwością 2400 MHz. Teraz dodatkowe rejestry muszą zrekompensować znaczny spadek prędkości zegara.

gnasher729
źródło
2

Jaki czynnik wpłynął na liczbę rejestrów

- Hierarchia pamięci

Rejestry, pamięć podręczna i pamięć RAM są wdrażane przy użyciu różnych technologii przechowywania.

Różne technologie różnią się między sobą

  1. Czasy dostępu
  2. Koszt
  3. Gęstość

Przykład: Wewnętrzne rejestry znalezione w CPU to statyczna pamięć o swobodnym dostępie , natomiast pamięć główna komputera to dynamiczna pamięć o swobodnym dostępie

Komórka binarna ze statyczną pamięcią RAM jest implementowana za pomocą obwodu 6-tranzystorowego, natomiast komórka binarna z dynamiczną pamięcią RAM jest implementowana za pomocą kondensatora i tranzystora. Porównanie SRAM i DRAM

  • Pamięć SRAM jest znacznie szybsza niż pamięć DRAM [Kilka cykli dostępu do SRAM w porównaniu do DRAM]
  • Obwód SRAM zużywa mniej energii niż DRAM
  • DRAM wymaga okresowego odświeżania co pewien czas w pamięci, w przeciwieństwie do SRAM
  • SRAM kosztuje więcej niż DRAM
  • SRAM ma niższą gęstość w porównaniu do DRAM

Dlatego zwiększanie liczby szybkiej, drogiej pamięci o mniejszej gęstości nie jest praktyczne. W rzeczywistości możemy użyć kilku z nich, a dobrze napisany program przechowa najczęściej używane dane w tych szybkich rejestrach, podczas gdy rzadziej używane dane są przechowywane w wolniejszej pamięci.

- długość instrukcji

Adres rejestrów jest zawarty w instrukcji, która ogranicza liczbę dostępnych rejestrów na podstawie liczby bitów, które mogą reprezentować adres. Na przykład w architekturze MIPS instrukcja o długości 32 bitów zawiera tylko 5 bitów do reprezentowania adresu dostępnych rejestrów, co ogranicza liczbę rejestrów do 2 5 = 32 rejestr. Zwiększenie liczby rejestrów wymagałoby zwiększenia długości instrukcji, aby uwzględnić wystarczającą liczbę bitów, które mogłyby uzyskać dostęp do wszystkich rejestrów.

Elbehery
źródło
2

Jeśli spojrzysz na zestaw instrukcji procesora, istnieje wiele sposobów ich grupowania. Na przykład wszystkie ADDinstrukcje mogą być zgrupowane razem i wszystkie XORinstrukcje.

W każdej grupie tej samej instrukcji mogą istnieć wersje działające na pamięci lub rejestrach. To ta podgrupa skutecznie określa liczbę rejestrów posiadanych przez procesor.

Jako 8-bitowy hipotetyczny przykład, powiedzmy, że $Axinstrukcje mogą być ADDinstrukcjami i $Cxmogą być XORinstrukcjami. Dzięki takiemu projektowi pozostały tylko cztery bity do zdefiniowania argumentów!

  • Jeden może mieć tylko cztery rejestry ogólnego przeznaczenia i użyć dwóch bitów do zdefiniowania jednego, a dwóch bitów do zdefiniowania drugiego.
  • Lub można użyć pierwszego bitu do rozróżnienia wariantów „specjalnych”, a pozostałych 3 bitów do zdefiniowania, który z ośmiu rejestrów ma współpracować z akumulatorem ( $x0może to być sam akumulator).
  • Lub można mieć więcej niż tę liczbę rejestrów - ale wtedy ogranicz, które rejestry są dostępne dla których instrukcji.

Oczywiście minęliśmy 8-bitowe zestawy instrukcji. Mimo to ta logika pomogła zdefiniować zestawy rejestrów w przeszłości - będzie to nadal robić w przyszłości.

EDYCJA (zgodnie z żądaniem)

Powiedzieć szczyt cztery bity są do dyspozycji: ADD, SUB, XOR, MOV, CMPitd. Istnieje 16 możliwości tutaj. Następnie, w przypadku instrukcji, w których rejestrowanie do rejestru ma sens (np. ADD Rx,Ry), Musisz określić Rxi Ry. Powiedzmy, że następne dwa bity są za x, a dwa ostatnie są za y. A zatem:

ADD R1, R2  =>  'ADD' + 'R1' + 'R2' => $A0 + $04 + $02

Mając tylko dwa bity do zdefiniowania takiego rejestru, masz miejsce tylko na cztery rejestry!

Nawiasem mówiąc, zauważysz, że niektóre kombinacje rejestrów nie mają sensu. Na przykład MOV Rx, Rx(nic nie robi) i SUB Rx, Rx(zawsze produkuje 0). Mogą to być instrukcje specjalne:

  1. SUB Rx, Rxmoże stać NOT Rxsię instrukcją pojedynczego operandu.
  2. MOV Rx, Rxmoże stać się MOVinstrukcją, która przyjmuje drugi bajt jako wartość natychmiastową, interpretowaną jako MOV Rx, #$yy.

W ten sposób możesz „bawić się” mapą instrukcji, wypełniając dziury dla instrukcji, które w innym przypadku byłyby bezużyteczne lub nienazwalne, aby zapewnić programistowi większy zestaw instrukcji. Ale ostatecznie zestaw instrukcji definiuje zestaw rejestrów.

John Burger
źródło
Nadal jestem zdezorientowany. Czy możesz wyjaśnić, jak na operandy pozostały tylko 4 bity?
Darshan Chaudhary
Sprawdź moją zaktualizowaną odpowiedź
John Burger,
1
IMHO odpowiedź ta zostałaby znacznie poprawiona poprzez przeniesienie „ hipotetycznego przykładu zakładającego 8-bitowy zestaw instrukcji ” na początek pytania. Zmarnowałem czas, próbując to zrozumieć, doszedłem do wniosku, że ma to sens tylko dla 8-bitowej instrukcji o stałej długości, a następnie czytam dalej, aby się przekonać. IMHO, tego rodzaju zestaw instrukcji nie jest bardzo nieistotny w kontekście pytania; cała jego przestrzeń adresowa może być ściśle sprzężona ze statyczną pamięcią RAM. Myślę też, że część zaczynająca się od „ Niektóre kombinacje rejestrów nie mają sensu ... ” nie ma związku z pytaniem i może zostać usunięta. Moje 0,02 $
żarówka
-2

Intel korzysta obecnie z tysięcy rejestrów - setek na rdzeń procesora. Ale największa ilość danych przechowywanych na procesorze znajduje się w pamięci podręcznej, co pośrednio odpowiada na pytanie. Pamięć podręczna jest zorganizowana w warstwach, z małą szybką pamięcią podręczną L1 i wolniejszymi pamięciami podręcznymi L2 i L3 dalej. Plik rejestru jest w pewnym sensie L0, nawet szybszy niż L1, ale także jeszcze mniejszy. Możesz więc zwiększyć liczbę rejestrów, ale to prawdopodobnie ich spowolni.

MSalters
źródło