Dlaczego Intel ukrywa wewnętrzny rdzeń RISC w swoich procesorach?

89

Począwszy od Pentium Pro (mikroarchitektura P6), Intel przeprojektował swoje mikroprocesory i użył wewnętrznego rdzenia RISC zgodnie ze starymi instrukcjami CISC. Od Pentium Pro wszystkie instrukcje CISC są dzielone na mniejsze części (ups), a następnie wykonywane przez rdzeń RISC.

Na początku było dla mnie jasne, że Intel postanowił ukryć nową architekturę wewnętrzną i zmusić programistów do używania „powłoki CISC”. Dzięki tej decyzji Intel mógł w pełni przeprojektować architekturę mikroprocesorów bez naruszania kompatybilności, to rozsądne.

Jednak nie rozumiem jednej rzeczy, dlaczego Intel nadal ukrywa wewnętrzny zestaw instrukcji RISC przez tyle lat? Dlaczego nie pozwoliliby programistom używać instrukcji RISC, takich jak stary zestaw instrukcji CISC x86?

Jeśli Intel zachowuje wsteczną kompatybilność przez tak długi czas (nadal mamy wirtualny tryb 8086 obok trybu 64-bitowego), dlaczego nie pozwalają nam kompilować programów, aby omijały instrukcje CISC i bezpośrednio używały rdzenia RISC? Otworzy to naturalny sposób na powolne porzucanie zestawu instrukcji x86, który jest obecnie przestarzały (jest to główny powód, dla którego Intel zdecydował się użyć rdzenia RISC w środku, prawda?).

Patrząc na nową serię Intel 'Core i' widzę, że rozszerzają one jedynie zestaw instrukcji CISC o AVX, SSE4 i inne.

Głupkowaty
źródło
1
zwróć uwagę, że istnieją pewne procesory x86, w których ujawniony jest wewnętrzny zestaw instrukcji RISC
phuclv

Odpowiedzi:

90

Nie, zestaw instrukcji x86 z pewnością nie jest przestarzały. Jest tak popularny jak zawsze. Powodem, dla którego Intel używa wewnętrznie zestawu mikroinstrukcji podobnych do RISC, jest to, że mogą być one przetwarzane wydajniej.

Tak więc procesor x86 działa poprzez posiadanie dość wytrzymałego dekodera w interfejsie, który akceptuje instrukcje x86 i konwertuje je na zoptymalizowany format wewnętrzny, który backend może przetworzyć.

Jeśli chodzi o udostępnianie tego formatu programom „zewnętrznym”, są dwie kwestie:

  • nie jest to stabilny format. Firma Intel może zmieniać to między modelami procesorów, aby najlepiej pasowały do ​​określonej architektury. Pozwala im to zmaksymalizować wydajność, a ta przewaga zostałaby utracona, gdyby musieli zdecydować się na ustalony, stabilny format instrukcji do użytku wewnętrznego, jak i zewnętrznego.
  • po prostu nic nie można zyskać, robiąc to. Przy dzisiejszych ogromnych, złożonych procesorach dekoder jest stosunkowo niewielką częścią procesora. Konieczność dekodowania instrukcji x86 sprawia, że ​​jest to bardziej złożone, ale reszta procesora pozostaje nienaruszona, więc ogólnie niewiele można zyskać, zwłaszcza że interfejs x86 nadal musiałby tam być, aby wykonać „starszy” kod . Więc nie zapisałbyś nawet tranzystorów aktualnie używanych na frontendu x86.

To nie jest do końca idealne rozwiązanie, ale koszt jest dość mały i jest to znacznie lepszy wybór niż zaprojektowanie procesora do obsługi dwóch zupełnie różnych zestawów instrukcji. (W takim przypadku prawdopodobnie wymyśliliby trzeci zestaw mikrooperacji do użytku wewnętrznego, tylko dlatego, że można je dowolnie modyfikować, aby najlepiej pasowały do ​​wewnętrznej architektury procesora)

jalf
źródło
1
Słuszne uwagi. RISC to dobra architektura rdzenia, w której DOBRE oznacza szybkie działanie i możliwość poprawnej implementacji, a ISA x86, który ma historię architektury CISC, jest dopiero teraz układem zestawu instrukcji z ogromną historią i wspaniałym bogactwem dostępnego dla niego oprogramowania binarnego , a także wydajne przechowywanie i przetwarzanie. To nie jest powłoka CISC, to branżowy standard ISA.
Warren P
2
@Warren: jeśli chodzi o ostatnią część, tak naprawdę nie sądzę. Dobrze zaprojektowany zestaw instrukcji CISC jest bardziej efektywne pod względem przechowywania, tak, ale od kilku testach widziałem, „średni” instrukcja x86 jest coś takiego jak 4,3 bajty szerokości, który jest więcej niż się to zazwyczaj w architektura RISC. x86 traci dużo wydajności pamięci masowej, ponieważ został tak przypadkowo zaprojektowany i rozbudowany przez lata. Ale jak mówisz, jego główną siłą jest historia i ogromna ilość istniejącego kodu binarnego.
jalf
1
Nie powiedziałem, że to „dobrze zaprojektowany CISC”, tylko „wielka historia”. Części DOBRE to części konstrukcyjne układu RISC.
Warren P
2
@jalf - Po sprawdzeniu rzeczywistych plików binarnych rozmiar instrukcji w architekturze x86 wynosi średnio około 3 bajty każda. Istnieją oczywiście znacznie dłuższe instrukcje, ale w praktyce przeważają te mniejsze.
srking
1
Średnia długość instrukcji nie jest dobrą miarą gęstości kodu: najczęstszym typem instrukcji x86 w typowym kodzie jest ładowanie i przechowywanie (po prostu przenoszenie danych do miejsca, w którym mogą być przetwarzane iz powrotem do pamięci, procesory RISC i około ½ CISC mają wiele rejestrów, więc nie trzeba to zrobić dużo także ile można wskazówki na temat (instrukcje ramię może zrobić około 3 rzeczy)..
ctrl-alt-Delor
20

Prawdziwa odpowiedź jest prosta.

Głównym czynnikiem stojącym za wdrożeniem procesorów RISC było zmniejszenie złożoności i zwiększenie szybkości. Wadą RISC jest zmniejszona gęstość instrukcji, co oznacza, że ​​ten sam kod wyrażony w formacie podobnym do RISC wymaga więcej instrukcji niż równoważny kod CISC.

Ten efekt uboczny nie ma większego znaczenia, jeśli twój procesor działa z tą samą prędkością co pamięć, a przynajmniej jeśli oba działają z dość podobnymi prędkościami.

Obecnie szybkość pamięci w porównaniu do szybkości procesora pokazuje dużą różnicę w taktach. Obecne procesory są czasami pięciokrotnie lub więcej szybsze niż pamięć główna.

Ten stan technologii faworyzuje bardziej zagęszczony kod, coś, co zapewnia CISC.

Można argumentować, że pamięci podręczne mogą przyspieszyć procesory RISC. Ale to samo można powiedzieć o procesorach CISC.

Uzyskujesz większą poprawę szybkości, używając CISC i pamięci podręcznych niż RISC i pamięci podręczne, ponieważ ten sam rozmiar pamięci podręcznej ma większy wpływ na kod o wysokiej gęstości, który zapewnia CISC.

Innym efektem ubocznym jest to, że RISC jest trudniejszy do implementacji kompilatora. Łatwiej jest zoptymalizować kompilatory dla procesorów CISC. itp.

Intel wie, co robią.

Jest to tak prawdziwe, że ARM ma tryb wyższej gęstości kodu zwany Thumb.

Jorge Aldo
źródło
1
Również wewnętrzny rdzeń RISC zmniejsza liczbę tranzystorów w CPU CISC. Zamiast sztywnego okablowania każdej instrukcji CISC, możesz użyć mikrokodu do ich wykonania. Prowadzi to do ponownego wykorzystania instrukcji mikrokodu RISC dla różnych instrukcji CISC, a tym samym użycia mniejszej powierzchni matrycy.
Sil
16

Jeśli Intel zachowuje wsteczną kompatybilność przez tak długi czas (nadal mamy wirtualny tryb 8086 obok trybu 64-bitowego), dlaczego nie pozwalają nam kompilować programów, aby omijały instrukcje CISC i bezpośrednio używały rdzenia RISC? Otworzy to naturalny sposób na powolne porzucanie zestawu instrukcji x86, który jest obecnie przestarzały (jest to główny powód, dla którego Intel zdecydował się użyć rdzenia RISC w środku, prawda?).

Musisz spojrzeć na biznesowy aspekt tego. Intel faktycznie próbował odejść od x86, ale to ta gęś znosi dla firmy złote jajka. XScale i Itanium nigdy nie zbliżyły się nawet do poziomu sukcesu, jaki osiągają ich podstawowa działalność x86.

Zasadniczo prosisz, aby Intel podciął sobie nadgarstki w zamian za ciepłe meszki od programistów. Podważanie x86 nie leży w ich interesie. Wszystko, co sprawia, że ​​więcej programistów nie musi wybierać celu x86, podważa x86. To z kolei je osłabia.

Mike Thomsen
źródło
6
Tak, kiedy Intel próbował to zrobić (Itanium), rynek odpowiedział tylko wzruszeniem ramion.
Warren P
Należy zauważyć, że podczas upadku Itanium było wiele czynników, i to nie tylko dlatego, że była to nowa architektura. Na przykład przeładowanie planowania procesora na kompilator, który w rzeczywistości nigdy nie osiągnął swojego celu. Gdyby Itanium był 10x lub 100x szybszy niż procesory x86, sprzedawałby się jak świeże bułeczki. Ale to nie było szybsze.
Katastic Voyage,
5

Odpowiedź jest prosta. Intel nie rozwija procesorów dla programistów ! Tworzą je dla ludzi, którzy podejmują decyzje zakupowe , a tak przy okazji robi to każda firma na świecie!

Intel już dawno temu zobowiązał się (oczywiście w granicach rozsądku), że ich procesory pozostaną wstecznie kompatybilne. Ludzie chcą wiedzieć, że kupując nowy komputer z procesorem Intel, całe ich obecne oprogramowanie będzie działało dokładnie tak samo, jak na ich starym komputerze. (Chociaż, miejmy nadzieję, szybciej!)

Co więcej, Intel dokładnie wie , jak ważne jest to zaangażowanie, ponieważ kiedyś próbowali pójść inną drogą. Dokładnie, ile osób ma pan wiedzieć z procesorem Itanium?!?

Może ci się to nie podobać, ale ta jedna decyzja, aby pozostać przy x86, sprawiła, że ​​Intel stała się jedną z najbardziej rozpoznawalnych marek na świecie!

geo
źródło
2
Nie zgadzam się z insynuacją, że procesory Intela nie są przyjazne dla programistów. Po programowaniu PowerPC i x86 przez wiele lat doszedłem do wniosku, że CISC jest znacznie bardziej przyjazny programistom. (Pracuję teraz dla Intela, ale zdecydowałem się na ten problem, zanim zostałem zatrudniony.)
Jeff
1
@Jeff To wcale nie było moim zamiarem! Pytanie brzmiało, dlaczego Intel nie otworzył zestawu instrukcji RISC, aby programiści mogli z niego korzystać. Nie powiedziałem nic o tym, że x86 nie jest przyjazny dla programistów. To, co powiedziałem, że decyzje takie jak ta nie zdecydowała z deweloperami w umyśle , ale raczej były ściśle decyzje biznesowe.
geo
5

Odpowiedź @jalfa obejmuje większość powodów, ale jest jeden interesujący szczegół, o którym nie wspomina: wewnętrzny rdzeń podobny do RISC nie jest zaprojektowany do uruchamiania zestawu instrukcji czegoś takiego jak ARM / PPC / MIPS. Podatek od x86 jest płacony nie tylko w energochłonnych dekoderach, ale w pewnym stopniu w całym rdzeniu. tj. nie chodzi tylko o kodowanie instrukcji x86; to każda instrukcja z dziwną semantyką.

Załóżmy, że Intel stworzył tryb operacyjny, w którym strumień instrukcji był czymś innym niż x86, z instrukcjami, które były bardziej odwzorowane na Uops. Udawajmy również, że każdy model procesora ma własny ISA dla tego trybu, więc nadal mogą zmieniać elementy wewnętrzne, kiedy chcą, i wystawiać je z minimalną ilością tranzystorów do dekodowania instrukcji tego alternatywnego formatu.

Przypuszczalnie nadal miałbyś tylko taką samą liczbę rejestrów odwzorowanych na stan architektury x86, więc systemy operacyjne x86 mogą zapisywać / przywracać je na przełącznikach kontekstowych bez użycia zestawu instrukcji specyficznych dla procesora. Ale jeśli odrzucimy to praktyczne ograniczenie, tak, moglibyśmy mieć kilka więcej rejestrów, ponieważ możemy użyć ukrytych rejestrów tymczasowych zwykle zarezerwowanych dla mikrokodu 1 .


Gdybyśmy mieli tylko alternatywne dekodery bez zmian w późniejszych etapach potoku (jednostkach wykonawczych), ten ISA nadal miałby wiele ekscentryczności x86. Nie byłaby to zbyt ładna architektura RISC. Żadna pojedyncza instrukcja nie byłaby bardzo złożona, ale niektóre z innych szaleństw x86 wciąż by tam były.

Na przykład: przesunięcia w lewo / w prawo pozostawiają niezdefiniowaną flagę przepełnienia, chyba że liczba przesunięć wynosi jeden, w którym to przypadku OF = zwykłe wykrywanie przepełnienia ze znakiem. Podobne szaleństwo dla rotacji. Jednak ujawnione instrukcje RISC mogą zapewniać przesunięcia bez flag i tak dalej (pozwalając na użycie tylko jednego lub dwóch z wielu uopsów, które zwykle wchodzą w skład niektórych złożonych instrukcji x86). Więc to tak naprawdę nie jest głównym kontrargumentem.

Jeśli zamierzasz stworzyć zupełnie nowy dekoder dla RISC ISA, możesz wybrać i wybrać części instrukcji x86, które mają być ujawnione jako instrukcje RISC. To nieco łagodzi specjalizację x86 rdzenia.


Kodowanie instrukcji prawdopodobnie nie będzie miało stałego rozmiaru, ponieważ pojedyncze Uops mogą pomieścić dużo danych. O wiele więcej danych, niż ma to sens, jeśli wszystkie insny mają ten sam rozmiar. Pojedynczy uop z mikro-fuzją może dodać natychmiastowy 32-bitowy i operand pamięci, który używa trybu adresowania z 2 rejestrami i 32-bitowym przesunięciem. (W SnB i nowszych, tylko jednorejestrowe tryby adresowania mogą łączyć się z operacjami ALU).

uops są bardzo duże i niezbyt podobne do instrukcji ARM o stałej szerokości. Zestaw instrukcji 32-bitowych o stałej szerokości może załadować tylko 16-bitowe natychmiastowo, więc ładowanie adresu 32-bitowego wymaga pary natychmiastowego ładowania - niska połowa / ładowanie - wysoka. x86 nie musi tego robić, co pomaga nie być strasznym, ponieważ tylko 15 rejestrów GP ogranicza możliwość utrzymywania stałych w rejestrach. (15 to duża pomoc przy 7 rejestrach, ale ponowne podwojenie do 31 pomaga o wiele mniej, myślę, że znaleziono jakąś symulację. RSP zwykle nie jest ogólnym celem, więc bardziej przypomina 15 rejestrów GP i stos.)


Podsumowanie TL; DR:

W każdym razie ta odpowiedź sprowadza się do „zestawu instrukcji x86 jest prawdopodobnie najlepszym sposobem zaprogramowania procesora, który musi być w stanie szybko wykonywać instrukcje x86”, ale miejmy nadzieję, że rzuca trochę światła na przyczyny.


Wewnętrzne formaty UOP w interfejsie użytkownika i zapleczu

Zobacz także Mikro fuzja i tryby adresowania dla jednego przypadku różnic w tym, co mogą reprezentować formaty uop front-end i back-end na procesorach Intela.

Przypis 1 : Istnieje kilka „ukrytych” rejestrów używanych jako tymczasowe przez mikrokod. Nazwy tych rejestrów są zmieniane tak samo, jak rejestry architektury x86, więc instrukcje multi-uop mogą być wykonywane poza kolejnością.

np. xchg eax, ecxna procesorach Intela dekoduje jako 3 uopsy ( dlaczego? ), a naszym najlepszym przypuszczeniem jest to, że są to pliki Uops podobne do MOV tmp = eax; ecx=eax ; eax=tmp;. W tej kolejności, ponieważ mierzę opóźnienie kierunku dst-> src przy ~ 1 cyklu, w porównaniu z 2 w drugą stronę. A te ruchy nie są zwykłymi movinstrukcjami; nie wydają się być kandydatami do eliminacji ruchu z zerowym opóźnieniem.

Zobacz także http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/, gdzie można znaleźć wzmiankę o próbie eksperymentalnego pomiaru wielkości PRF i konieczności uwzględnienia fizycznych rejestrów używanych do przechowywania stanu architektonicznego, w tym rejestrów ukrytych.

W interfejsie użytkownika za dekoderami, ale przed etapem wydawania / zmiany nazwy, który zmienia nazwy rejestrów na plik rejestru fizycznego, wewnętrzny format uop wykorzystuje numery rejestrów podobne do numerów rejestrów x86, ale z miejscem na adresowanie tych ukrytych rejestrów.

Format uop jest nieco inny w rdzeniu niesprawnym (ROB i RS), czyli zapleczu (po etapie wydania / zmiany nazwy). Każdy zbiór rejestrów fizycznych int / FP ma 168 wpisów w Haswell , więc każde pole rejestru w uop musi być wystarczająco szerokie, aby zaadresować taką liczbę.

Ponieważ program do zmiany nazwy znajduje się w HW, prawdopodobnie lepiej byłoby go używać, zamiast przesyłać statycznie zaplanowane instrukcje bezpośrednio do zaplecza. Więc moglibyśmy pracować z zestawem rejestrów tak dużym jak rejestry architektoniczne x86 + tymczasowe elementy mikrokodu, nie więcej.

Back-end jest zaprojektowany do pracy z front-endowym renamerem, który unika zagrożeń WAW / WAR, więc nie mogliśmy go używać jako procesora w zamówieniu, nawet gdybyśmy chcieli. Nie ma blokad do wykrywania tych zależności; to jest obsługiwane przez wydanie / zmianę nazwy.

Byłoby fajnie, gdybyśmy mogli wprowadzić uopsy do zaplecza bez wąskiego gardła na etapie wydania / zmiany nazwy (najwęższy punkt w nowoczesnych potokach Intela, np. 4-szerokie w Skylake w porównaniu z 4 ALU + 2 obciążenia + 1 port magazynu w zaplecze). Ale jeśli to zrobiłeś, nie sądzę, abyś mógł statycznie zaplanować kod, aby uniknąć ponownego wykorzystania rejestru i nadepnięcia na wynik, który jest nadal potrzebny, jeśli brak pamięci podręcznej zatrzymał ładowanie na długi czas.

Tak więc prawie musimy podać Uops do etapu wydania / zmiany nazwy, prawdopodobnie omijając tylko dekodowanie, a nie pamięć podręczną uop lub IDQ. Następnie otrzymujemy normalne wykonanie OoO z rozsądnym wykrywaniem zagrożeń. Tablica alokacji rejestrów jest zaprojektowana tylko do zmiany nazwy 16 + kilku rejestrów całkowitych na 168-wejściową liczbę całkowitą PRF. Nie mogliśmy oczekiwać, że HW zmieni nazwę większego zestawu rejestrów logicznych na taką samą liczbę rejestrów fizycznych; to wymagałoby większego RAT.

Peter Cordes
źródło
-3

Dlaczego nie pozwolą nam kompilować programów, aby ominąć instrukcje CISC i bezpośrednio używać rdzenia RISC?

Oprócz poprzednich odpowiedzi kolejnym powodem jest segmentacja rynku. Uważa się, że niektóre instrukcje są implementowane w mikrokodzie, a nie w sprzęcie, więc zezwolenie każdemu na wykonywanie dowolnych mikrooperacji może podważyć sprzedaż nowych procesorów cpus z „nowymi” bardziej wydajnymi instrukcjami CISC.

KOLANICH
źródło
1
Nie sądzę, żeby to miało sens. RISC może używać mikrokodu, zwłaszcza jeśli mówimy o dodaniu dekoderów RISC do frontendu x86.
Peter Cordes,
2
To nadal jest złe. Nowe instrukcje AES (i nadchodzące instrukcje SHA) i inne rzeczy, takie jak PCLMULQDQ, mają dedykowany sprzęt. W Haswell AESENC dekoduje do pojedynczego UOP ( agner.org/optimize ), więc na pewno nie jest w ogóle mikrokodowany. (Dekodery muszą tylko aktywować sekwencer mikrokodu ROM, aby uzyskać instrukcje dekodowania do więcej niż 4 uops .)
Peter Cordes,
1
Masz rację, że niektóre nowe instrukcje po prostu wykorzystują istniejącą funkcjonalność w sposób, który nie jest dostępny w instrukcjach x86. Dobrym przykładem może być BMI2 SHLX , który pozwala zrobić zmiany zmiennej count pominięciem licznika w CL, i bez ponoszenia dodatkowych UOPs wymagane do obsługi brzydko x86 semantykę flagę (flagi są niezmodyfikowanej jeśli liczba przesunięcie wynosi zero, więc SHL r/m32, clma zależność danych wejściowych od FLAGS i dekoduje do 3 ups na Skylake. Jednak było to tylko 1 uop na Core2 / Nehalem, zgodnie z testami Agner Fog.)
Peter Cordes
Dziękuję za twoje komentarze.
KOLANICH