RSS

RISC: ograniczony zestaw, a nie liczba rozkazów

Liczba odsłon: 52

Swego cza­su w pra­sie (na­wet fa­cho­wej), a w szcze­gól­noś­ci w umys­łach ludz­kich, za­gnieź­dzi­ło się prze­ko­na­nie, że archi­tek­tu­ra RISC ozna­cza ogra­ni­cze­nie licz­by roz­ka­zów roz­poz­na­wa­nych i rea­li­zo­wa­nych przez mikro­pro­ce­sor. Wytłuma­cze­niem ta­kiej inter­pre­tac­ji była moż­li­wość szyb­szej, w peł­ni sprzę­to­wej reali­zac­ji po­szcze­gól­nych roz­ka­zów, w prze­ci­wień­stwie do ukła­dów CISC, wy­ko­nu­ją­cych roz­ka­zy za po­mo­cą mikro­pro­gra­mu (mikro­ko­du).

Owszem, pierw­sze mikro­pro­ce­so­ry RISC miały zde­cy­do­wa­nie krót­szą lis­tę roz­ka­zów, niż po­cho­dzą­ce z te­go sa­me­go okre­su ukła­dy CISC. Różnica ta wy­ni­ka­ła jed­nak z cze­goś zu­peł­nie in­ne­go.

Architektura RISC rzeczy­wiś­cie za­kła­da ogra­ni­cze­nie lis­ty roz­ka­zów mikro­pro­ce­so­ra. I fak­tycz­nie, ukła­dy RISC są częs­to po­zba­wio­ne roz­ka­zów reali­zu­ją­cych naj­bar­dziej skom­pli­ko­wa­ne ope­rac­je, na przy­kład zna­nych z archi­tek­tu­ry IA-32 roz­ka­zów pęt­lo­wych i łań­cu­cho­wych. Największe ogra­ni­cze­nie do­ty­czy jed­nak nie ro­dza­ju wy­ko­ny­wa­nych ope­rac­ji, lecz try­bów adre­so­wa­nia.

Lista roz­ka­zów mikro­pro­ce­so­rów CISC na pierw­szy rzut oka nie po­ra­ża wca­le swo­ją dłu­goś­cią. Proste ukła­dy dys­po­nu­ją kil­ku­dzie­się­cio­ma roz­ka­za­mi; je­dy­nie bar­dziej skom­pli­ko­wa­ne roz­poz­na­ją od trzy­stu do czte­ry­stu. Trzeba so­bie jed­nak uświa­do­mić, że więk­szość z tych roz­ka­zów wy­stę­pu­je w kil­ku wer­sjach, róż­nią­cych się od sie­bie try­bem adre­so­wa­nia. Niektóre wer­sje po­bie­ra­ją ar­gu­ment w po­sta­ci war­toś­ci po­da­nej w sa­mym roz­ka­zie (na­tych­mias­to­wo), in­ne od­czy­tu­ją dane z pa­mię­ci adre­su­jąc ją bez­względ­nie, względ­nie lub in­dek­so­wo. W efek­cie peł­na lis­ta ko­dów roz­ka­zów (ang. opcodes) po­tra­fi za­wie­rać kil­ka ty­się­cy po­zyc­ji, z któ­rych spo­ra część roz­po­czy­na się li­ta­nią róż­ne­go ro­dza­ju ko­dów-przed­rost­ków.

Podstawo­wym za­ło­że­niem archi­tek­tu­ry RISC, ogra­ni­cza­ją­cym licz­bę kom­bi­nac­ji ko­dów roz­ka­zów, było nie usu­nię­cie częś­ci ope­rac­ji (a więc i grup ko­dów od­po­wia­da­ją­cych da­nej ope­rac­ji przy wszyst­kich do­pusz­czal­nych try­bach adre­so­wa­nia), lecz wy­eli­mi­no­wa­nie try­bów adre­so­wa­nia. Rozkaz mikro­pro­ce­so­ra RISC mo­że ope­ro­wać wy­łącz­nie na re­jest­rach we­wnętrz­nych ukła­du: za każ­dym ra­zem, gdy po­trzeb­ne jest sięg­nię­cie do da­nych za­pi­sa­nych w pa­mię­ci opera­cyj­nej lub za­pi­sa­nie tam wy­ni­ków obli­czeń, sko­rzys­tać na­le­ży z wy­dzie­lo­nych roz­ka­zów ty­pu LOADSTORE.

Aby wy­daj­ność ta­kie­go mikro­pro­ce­so­ra była akcep­to­wal­na, zbiór re­jest­rów jest za­zwy­czaj cał­kiem ob­szer­ny (kil­ka­dzie­siąt po­zyc­ji, w po­rów­na­niu do kil­ku lub kil­ku­nas­tu do­stęp­nych w więk­szoś­ci ukła­dów kla­sy CISC), a po­szcze­gól­ne roz­ka­zy są wy­ko­ny­wa­ne jak naj­szyb­ciej, po­to­ko­wosu­per­ska­lar­nie. W ten spo­sób efek­tyw­ny czas reali­zac­ji po­je­dyn­cze­go roz­ka­zu moż­na spro­wa­dzić do po­zio­mu jed­ne­go cyk­lu ze­ga­ro­we­go lub – w przy­pad­ku prze­twa­rza­nia su­per­ska­lar­ne­go – na­wet do mniej­szych war­toś­ci. Dzięki te­mu ukła­dy RISC, choć wy­ma­ga­ją więk­szej iloś­ci ko­du do reali­zac­ji nie­któ­rych ope­rac­ji, przez dłu­gi czas gó­ro­wa­ły wy­daj­noś­cią nad mikro­pro­ce­so­ra­mi kla­sy CISC.

Dzisiaj róż­ni­ca nie jest już tak wiel­ka. Czemuż się dzi­wić: ukła­dy CISC wy­ko­rzys­tu­ją w za­sa­dzie wszyst­kie po­mys­ły kie­dyś wy­róż­nia­ją­ce na ich tle ro­dzi­nę RISC. Złożone roz­ka­zy CISC są tłu­ma­czo­ne na wejś­ciu na pros­tszy ze­staw, przy­po­mi­na­ją­cy archi­tek­tu­rę RISC. Zbiór re­jest­rów jest po­sze­rzo­ny na po­trze­by me­cha­niz­mu prze­mia­no­wy­wa­nia. Superska­lar­ne po­to­ki są w sta­nie fi­na­li­zo­wać prze­twa­rza­nie kil­ku roz­ka­zów w cią­gu jed­ne­go cyk­lu ze­ga­ro­we­go. I choć moż­li­we, że ukła­dy RISC byłyby w sta­nie osiąg­nąć wyż­szą wy­daj­ność lub efek­tyw­ność, przy­szłość – pra­wem iner­cji – wciąż wy­da­je się na­le­żeć do mikro­pro­ce­so­rów o zło­żo­nej liś­cie roz­ka­zów.


Apple zrezygnowało z PowerPC, IBM też na rzecz PowerXCell 8i, po upadku SGI zniknął ich procesor MIPS, HP dawno zrezygnowało z PA-RISC, jeszcze Sun ze swoim UltraSPARC się trzyma, na studiach miałem przyjemność jeden semestr spędzić na maszynach z tymi układami. Za to ukłądy ARM jako rozwinięcie architektury RISC są wszędzie: routery, netbooki, przenośne odtwarzacze multimedialne, nawigacje, handheldy, palmtopy, telefony komórkowe, odwarzacze DivX, tunery satelitarne. Niewielkie taktowania 266-600MHz w zupełności wystarczają do spełnianych przez nie zadań. Intel XScale, Connexant, Frescale, Texas Instruments, STI, Atmel, a ostatnio nawet 1GHz Cortex-A8, Qualcomm Snapdragon MSM 8250 i nVidia Tegra. Może kiedyś zobacze porównanie takiej architekruty z x86 o podobnych zegarach, a przynajmniej do Intel Atom w netbookach, będzie to mozliwe przy pomocy tej samej dystrybucji Linuksa. Może sam kiedyś będe miał okazje porównania ostatniej rodziny PowerPC do PentiumM lub C2D o zblizonych zegarach. Chyba najlepszym testem będzie odtwarzanie wideo w rozdzielczości HD 1080p, bez żadnych dodatkowych sprzętowych wspomagań.
Ograniczenie dostępu do pamięci jest na dzisiejsze czasy zbawienne.
Niestety, nawet przy pracy z najszybszymi pamięciami taki mikroprocesor RISC musi oczekiwać kilka, kilkanaście cykli maszynowych na gotowość do zapisania bądź odczytania pamięci RAM.

Szczególnie widać to przy zapisie bądź odczycie pojedynczych bajtów. Aby to zrobić to napierw trzeba obudzić taką pamięć, a zazwyczaj bywa, że się trafi na moment odświeżania się takiej pamięci potem jej powiedzieć, co się od niej chce, ile się chce i skąd się chce. Co w praktyce okazuje się, że taki RISC bardzo się nudzi
przy współpracy z pamięcią. Więc podwyższanie częstotliwości pracy RISC nie jest dobrym rozwiązaniem. Może dlatego uP RISC nie wykraczają poza granicę 1GHz.

Lista rozkazów mikroprocesora RISC wcale nie jest uboga. Fakt, że nie występują w jawnej formie rozkazy
służące do realizacji pętli. Ale nic nie stoi na przeszkodzie, aby "poskładać" to z kilku rozkazów. Te kilka rozkazów wcale nie oznacza kilku straconych cykli, między innymi dzięki superskalarności
takiego uP. Aby programistom nie było smutno z tego powodu, ta architektura dostarcza również inne "kwiatki". :)
Na przykład można zrealizować w jednym cyklu maszynowym takie cudo" addeq r0,r4,r5, lsl r10 Co można przetłumaczyć jako r0=r4+r5<<r10 jeśli poprzedni rozkaz zwrócił true
Co bardzo przydaje się przy realizacji algorytmów numerycznych. Można w kilku linijkach zrobić to samo, co uP CISC będzie potrzebować kilkunastu. Dodatkowo CISC będzie musiał korzystać
z pamięci, co również się odbije na wydajności. Liczba 16, 32 bądż 64 rejestrów roboczych o długości 32 lub 64 bitów uP RISC skutecznie zapobiegnie odwoływaniu się do pamięci.
Pamięć jest potrzebna jedynie do odczytu danych wejściowych i zapisaniu wyników obliczeń. Taka sytuacja występuje również przy przetwarzaniu danych strumieniowych.
Zawsze można podzielić tak dane, aby "zmieściły się" w rejestrach procesora. Jeśli zabraknie, to można skorzystać z Data Cache, który w odróźnieniu od np. x86 jest widoczny dla programu, jako pamięć podręczna, bezzwłoczna. :)