Díky, zajímavý článek jako vždycky od Pavla. Jenom bych doplnil dvě věci. Jsou dvě velké rodiny RISCových procesorů: jedna používá posuvná registrová okna (AMD29000, SPARC apod.), ta druhá ne (MIPS, ARM...). Co PowerPC? Z článku tak nějak vyplývá, že registry jsou pevné, neboli že PPC patři do té druhé skupiny, ale možná se pletu. No a k té instrukční sadě: PowerPC je odvozené z POWER, což byla vždycky nesmírně rozsáhlá architektura. RISC tedy v tomto případě nesmíme chápat jako "malou" instručkní sadu, ale jako sadu, ve které je každá jednotlivá instrukce jednoduchá, tj. jednoduché binární formáty, omezené adresovací režimy atd.
Díky :)
V mnoha instrukcích se pro indexaci registrů používá pět bitů, takže jsou přístupné všechny GPR najednou, ne například jen osm v daný okamžik.
Je to tak, POWER má instrukční sadu hodně rozsáhlou, je to například dobře vidět na případu skoků, ale i na instrukcích, které vezmou dva vybrané bity z CR a provedou s nimi jednu z operací AND, OR, NAND, NOR, XOR nebo negaci XOR (fakt jsou tam zastoupeny všechny tyto operace). Jestli to skutečně používají překladače, těžko říct :)
myslel jsem to napriklad v porovnani s MIPSy nebo RISV-5. U POWER jsem mel pocit, ze tam proste nacpali vsechno, co slo "zadratovat" bez mikroradice, aniz by nejak premysleli, k cemu to bude. U MIPSu naopak vsechno nepotrebne odrezali az na uplny zaklad (bez flagu, jen skok pri nulovem/nenulovem registru, nasobicka schvalne udelana "navic" atd.)
Ale je fakt ze "člověk vlastně minimalismus architektury nechce" muze byt pravdivy, viz prave PPC, ARMy s Thumb-2, aarch64 apod. nebo z druhe strany x86-64, kterej se k riscu blizi nenapadne.
No právě. Minimální architektury jako MIPS byly atraktivní v době, kdy se za každý tranzistor platilo zlatem. Skutečně bylo v mnoha ohledech lepší mít co nejjednodušší procesor, u kterého zbylo na slušný cache a šlo zvyšovat hodiny bez obav, aby se to uchladilo. Dneska naopak skutečně válí složitější (ARM) nebo velmi složité (POWER, x86-64) architektury, protože tam kde to jde je hardware vždycky rychlejší, než software. Pokud jde o ten x86-64, na něm nevidím nic RISCového. To, že má víc registrů a "vyčištěnou" instrukční sadu z něj nedělá RISC.
No ono to je s x86-64 složitější. Architektura je to jasně CISCová, ale její implementace od AMD i Intelu jsou vnitřně RISCové a těmto RISCovým jádrům je předřazen dekodér instrukcí, který x86-64 kód převádí pro to RISCové CPU uvnitř. U AMD by to mělo být už od K5 procesor AMD 29000 pokud mě paměť neklame. U Intelu to je tuším od Pentium Pro, ale nevím co to je uvnitř zač a ani nevím, jestli se to dá někde dočíst.
Záleží na úhlu pohledu. Já bych si možná i troufl říct, že x86-64 je RISCová architektura s dekodérem složitější instrukční sady. Něco jako ARM Thumb-2 - uvnitř skoro čistý RISC, nad tím taková směska RISCových a CISCových instrukcí (LDM, STM) s proměnnou délkou a prefixovými instrukcemi (IT*).
A to já bych zase nepřikládal takovou váhu tomu, jestli jde o RISC nebo CISC, protože to se ve finále na designu projeví jenom velikostí programu a rychlostí, mimo ASM to člověk nevidí av C to většinou schová kompilátor.
Zásadnější dělení vidím mezi von Neumannem a Harvardem. A to proto, že:
1. Harvard má často jinou šířku datové a instrukční sběrnice a je potřeba v SW zohlednit alignment. Prosákne to celou aplikací i Cčkem (PIC, AVR,...).
2. Harvard většinou nedokáže běžet z RAMky, to je potřeba vědět třeba při návrhu bootloaderu, dynamicky natahovaných rutin z vnější paměti (nutnost interpreteru) apod.
3. U harvardu je třeba explicitně volit, jestli konstanty budou ve FLASH s programem, nebo někde v datové oblasti. V prvním případě se můžou objevit dvě verze jedné rutiny s jinou třídou pointeru v argumentu, ale nachlup stejný, v to druhým... Zkusili jste takto zobrazovat na displeji hlášky celkové velikosti 8kB jednočipu s 4kB RAM?
Takže tyhle rozdíly jsou z pohledu aplikace o hodně zásadnější a dotýkají se architektury celýho systému podstatně víc, než RISC/CISC.
Když je řeč o instrukční sadě neboli externí architektuře, tak mám za to, že amd64 je jednoznačně CISC, MIPS je čirý RISC, moderní ARM tak něco mezi a POWER je... prostě IBM :) Z hlediska aplikací (tj. hustota kódu, LOAD/STORE nebo operace rovnou z/do paměti atd...) se tyhle procesory prostě tak jeví, celkem bez ohledu na to, co je uvnitř.
Jinak je pravda, že K5 byl ve skutečnosti AMD29K schovaný za dekodérem instrukcí. U Intelu je to tak od PPro, ale cosi podobného, byť v mnohem primitivnější prodobě, bylo už u 486. Vzpomínám si, že v manuálu ho vychvalovali jako "RISC Processor" (RISC byl tehdy buzzword).
Ale zdaleka to není specifika Intel/AMD. Stejný princip už drahnou dobu používá POWER a dneska i Cortexy od ARM, takže na otázce RISC/CISC se tím nic nemění (tedy pokud na tom vůbec záleží). Absolutně netuším, jak ta jádra vypadají, je to ostatně dost zajímavé téma, ale u ARM bych čekal pravděpodobně nějaký hodně jednoduchý RISC a u procesorů z hyperthreadingem, tj. Intel, AMD a POWER, bych to viděl spíš na něco typu VLIW. Představuju si, že dekodér/překladač instrukcí čte instrukce paralelně ze dvou nebo osmi vláken a přeložené je pak láduje do odpovídajících instrukčních slotů VLIW kódu... ale možná se pletu a ve skutečnosti to třeba funguje úplně jinak.
Když se to tak vezme, nebylo by vlastně vůbec nelogické, aby Xeon a Itanic měli uvnitř stejné nebo velmi podobné jádro.
Tim Intelem myslis i960?
Mam dva na dvou procesorovych kartach do Compaq serveru s CPU 133MHz: http://images.esellerpro.com/2131/I/246/85/Picture%20230.jpg
o VLIW v pripade implementacie podkladovej architektury velmi silne zasadne pochybujem. prax ukazala, ze VLIW vyzaduje velmi silne optimalizujuci prekladac a vhodny kod na to, aby tato architektura bezala optimalnym vykonom. hyperthreadingu sa dosahuje "jednoducho" tym, ze u superskalarnych procesorov byva casto napr. viacero ALU na jednu instrukcnu frontu, aby bolo mozne v kratkom slede po sebe spustit viacero instrukcii vykonavajucich sa na ALU bez toho aby sa museli vkladat delay sloty do pipeline. Namatkovo PowerPC 970 malo takto 3 Vector unity na jadro, PPC 7450 malo dve / jadro. Ak sa takyto paralelizmus znacne nafukne stane sa to, ze pri bezne hustom kode bude velka cast procesora pomerne casto zahalat, pretoze proste instrukcie na duplikovane jednotky nejdu tak zhusta. Preto sa potom spravi to, ze sa da do jadra napr. 5 ALU a potiahnu sa 2 instrukcne pipeline, ktore sa budu o tieto ALU delit. Takze sa da povedat, ze pri dostatocne bohate dimenzovanom superskalarnom procesore sa hyperthreading dostane "zadarmo". Staci pridat dalsiu instrukcnu pipeline a vyriesit vzniknute problemy :)
Ak sa nahodou stane, ze su vsetky ALU zamestnane a dojde dalsia instrukcia, ktora by rada ALU pouzila, vlozi sa do pipeline delay krok tak, ako by sa vlozil, keby vsetky dostupne zdroje vycucala jedna instrukcna pipeline. Toto sa zjavne dost casto stavalo u prvych HTckovych Pentii 4, ktore mali volnych jednotiek pomerne dost malo (a instrukcie trvali strasne vela krokov, takze ak bolo nieco busy, bolo viac menej iste, ze ten delay krok nebude jediny), co malo za nasledok, ze vykon pri pouziti HT mohol byt v sucte nizsi ako pri single-thread behu, pretoze sa dost vkladali delay kroky a ak sa k tomu pripocitala rezia synchronizacie SMP systemu, hruby vypoctovy vykon bol nizsi ako keby sa bezalo na jednom vlakne.
Tomuto napr. stale veri planovac vo Windows, ktory sa snazi zamestnavat vzdy najprv jednu instrukcnu pipeline v ramci jadra a az ked mu dojdu volne timesloty na primarnych pipeline, zacne obsadzovat aj sekundarne pipeline. U novsich procesorov rodiny Core i* by s tym ale uz nemal byt taky problem, pretoze jednak rollbackli ku kratsej 15-17 krokovej pipeline z ery Pentium 3 a za druhe asi prehodnotili mieru nasobnosti funkcnych blokov procesora.
VLIW se ukázalo jako neprůchozí tam, kde je nutné generovat kód staticky (tj. překladačem), protože ani ten nejlepší kompiler nemůže provádět optimalizace, které by se v důsledku rovnaly problému zastavení Turingova stroje. Něco jiného je ale, pokud se má kód generovat dynamicky z několika nezávislých paralelních instrukčních toků a s průběžnými informacemi o stavu jednotlivých pipelinů. Tady nevidím důvod, proč by to v zásadě nešlo. Tím nechci říct, že to tak nutně je v případě existujícího hyperthreadingu, ale jako princip mi to připadá rozumné.
No a není už potom lepší se skutečně na VLIW (skládání x operací do jednoho slova) vykašlat a mít prostě řekněme pět paralelně běžících modulů, do kterých se instrukce vkládají tak, jak přijdou? Příkladem: 2x ALU, 1x FP, 1x skoky, 1xLOAD/STORE. VLIW začal kdysi dávno, aby se ty moduly "krmily" ze staticky generovaného kódu (jasně, CPU bylo mnohem jednodušší), ukázalo se to být ne zcela optimální, takže kromě nějakých DSP to snad (?) už nikdo nepoužívá...
Vícero elementárních jednotek má každý superskalární procesor. Mě by zajímalo, jestli je v případě hyperthreadingu dekodér dokáže současně krmit instrukcemi z různých paralelních vláken.
Jinak VLIW byl propadák u staticky generovaného kódu (až se divím, že to někomu připadalo jako dobrý nápad) ale u dynamického výstupu z dekodéru, což je v podstatě zadrátovaný JIT, se to tak zle nejeví. Aby bylo jasno: netvrdím, že to tak funguje, ani, že by to tak bylo nutně dobře. Jenom mi to přišlo jako jeden možný přístup.
Kromě DSP VLIW ještě používá pár mikrokontrolérů a GPU. Tuším, že některé radeony jsou nebo byly VLIW. No a samozřejmě tu pořád ještě máme Itanium. Dlouho jsem si myslel, že není nic horšího, než staré x86 v reálném režimu, až jsem jednou měl tu "čest" psát pár rutin v assembleru IA64...
Pravda, Itanium (melo se to puvodne jmenovat Itanic :) tady mame, ale uz treba enterprise linuxy od jeho podpory ustupuji a asi to je to cele v zombie fazi...
Jestli tomu dobre rozumim - idea je takova, ze na vstupu je RISC kod z vice threadu a dekoder z toho vytvori VLIW? Tak proc ne, ted tam asi maji nejaky crossswitch, ktery proste instrukce prohazuje do volnych modulu a navic si musi hrat s prejmenovanim registru.
Což o to, Itanic se potápí už hezkou dobu. Pokud si pamatuji, tahle přezdívka se objevila sotva pár dní poté, co HP a Intel slavnostně oznámili značku Itanium - což mimochodem mluví samo za sebe... Enterprise distra ho už opustili (RHEL od verze 6, Ubuntu server už před tím, jinak nevím), ale nejsou samy, MS zařízl podporu ve Windows Server 2012 a i Oracle před lety oznámil, že se s ním už nebude zdržovat, za čež pak musel Intelu zaplatit odškodné... Jinak na něm fungovalo ještě OpenVMS (to pro změnu zase nefungovalo na ničem jiném), ale i tomu už je odzvoněno.
Ta idea je přesně tak, RISC nebo CISC kód v několika threadech, konkrétně dvou (Intel) nebo osmi (POWER). Dekodér ho přeloží a odešle do front, odkud se pak jednotlivé instrukce nacpou do příslušných slotů VLIW kódu, např. 2xALU + 1xMEM, podle toho, v kterých pipelinech je volno a jaké instrukce jsou zrovna připravené k běhu. Přejmenování registrů se v každém případě děje tak jako tak pokud má CPU umět spekulativní exekuci nebo exekuci mimo pořadí. Např. Intel ho používá už od Pentium Pro (ten má konkrétně 128 fyzických registrů, různě namapovaných na osm logických registrů architektury x86, u každé instrukce jinak).
Nemam uplne zkusenost primo z oboru navrhovani procesoru, ale co jsem v podobnem oboru ziskal sve pidizkusenosti a co jsem konzultoval s lidmi co delaji obdobne veci a jsou autoritami (napr. "chief architect" JITu v Jave), tak je potreba udelat vzorky nejakeho kodu (typicky spustenim OS, aplikace, apod. & merenim), a na tech vzorcich stavet vypocty "co by se stalo kdyby". A za kdyby dosazovat WLIV, ruzne predikujici JITy, multithreading, apod. Je to celkem dost prace a myslim, ze to je pole hodne neorane, protoze jsem se vetsinou dostal k odpovedi "meli jsme to v planu udelat, ale nedodelali jsme to, protoze management ...." (=byl hotovy prodejny produkt a trh to nevyzadoval).
Myslim, ze i neco podobneho vypadlo z jednoho ze zakladatelu VMware, ale nechci mu to primo vkladat do ust.
Mozna to trosku zkresluju, ale z odpovedi jsem to vycitil.