Hlavní navigace

Architektury mikroprocesorů

2. 5. 2008
Doba čtení: 16 minut

Sdílet

V jubilejní desáté části seriálu o funkci počítačů si popíšeme některé typické architektury mikroprocesorů, zejména architektury označované téměř magickými zkratkami RISC, CISC či MISC. Řekneme si také, jaké přednosti a zápory jednotlivé architektury mají z hlediska jejich dalšího vývoje.

Obsah

1. Architektury mikroprocesorů
2. Platforma IBM System/360 a vznik architektury CISC
3. RISC – jednoduchost a rychlost
4. Zásobníkové architektury
5. Rozdělení instrukčních sad podle počtu explicitně adresovaných operandů
6. Obsah další části seriálu

1. Architektury mikroprocesorů

V padesátých a šedesátých letech minulého století byl každý typ tehdy vyrobeného počítače vlastně unikátem, který v naprosté většině případů nebyl kompatibilní ani s předchozími modely téže firmy, ani s modely jiných firem. To mimo jiné znamenalo, že program napsaný pro jeden typ počítače byl prakticky nepřenositelný na jiné počítače – lišily se jak použité procesory (procesorové jednotky), tak i interní a externí sběrnice, paměťové subsystémy i předchůdci dnešních operačních systémů (v té době se v podstatě jednalo o sady ovladačů, popř. nějaký jednoduchý správce dávkově spouštěných úloh). S přechodem na jiný typ počítače tedy firmy musely investovat do nového programového vybavení a – co bylo z pohledu dnešních výrobců softwaru a hardwaru ještě horší – prakticky nic nedrželo zákazníky u řešení jedné firmy, protože změna typu počítače stejně vedla k zahození prakticky všech aplikací a mnohdy i k nákladné konverzi dat na jiná paměťová média a do jiného formátu.

pc1001

Eniac byl samozřejmě naprostý unikát kompatibilní maximálně sám se sebou (minimálně do doby, než se program „předrátoval“)

Od konce šedesátých let do přibližně poloviny let sedmdesátých docházelo k postupné unifikaci v oblasti výpočetní techniky; jak formátů dat (EBCDIC či ASCII byly v té době pro mnoho výrobců i uživatelů žhavé novinky), tak i programů, protože s nástupem překladačů vyšších programovacích jazyků bylo možné psát skutečně přenositelné aplikace. Výkon počítačů i kapacity jejich pamětí dosáhl takové míry, že bylo možné část výkonu (samozřejmě do určité míry a v některých aplikacích) „obětovat“ pro programy napsané v interpretovaných jazycích. Nás však budou v této chvíli zajímat srdce všech počítačů, tj. procesory a pozdější mikroprocesory. I ty se do určité míry unifikovaly (zejména s nástupem integrovaných obvodů s velkou mírou integrace), ale současně byla patrná snaha o dosažení lepších výpočetních výkonů, menší ceny či rychlejší reakce na přerušení pomocí aplikace různých technologií. To postupně vedlo ke vzniku několika typických konfigurací mikroprocesorů, které nazýváme architekturou. V následujících kapitolách si některé typické architektury popíšeme.

pc1002

Ovšem procesory řady i8080 byly již tak standardizované, že jejich klony vyráběly i státy RVHP (ovšem okolní svět v té době již používal šestnáctibitové mikroprocesory)

pc1003

2. Platforma IBM System/360 a vznik architektury CISC

V roce 1962 se firma IBM rozhodla navrhnout do značné míry univerzální architekturu počítačů, která by pokrývala jak nároky jednodušších úloh (pro které stačily méně výkonné a tím pádem i levnější počítače), tak i nároky mnohem větší. Předností této architektury mělo být to, že systém „rostl“ současně s rostoucími požadavky zákazníka bez nutnosti měnit programové vybavení. Výsledkem těchto snah firmy IBM byla platforma nazvaná System/360, resp. zkráceně S/360. Pro tuto platformu byla vytvořena poměrně rozsáhlá a složitá instrukční sada (ISA), která mimo běžné binární aritmetiky obsahovala i instrukce pro práci s textem, různé numerické formáty dat známé například z kalkulaček, ale i podporu BCD aritmetiky, která se dodnes používá například při výpočtech s měnou. V té době totiž vládlo přesvědčení, že bohatší instrukční sada ulehčí práci překladačům z vyšších programovacích jazyků, vyplní takzvanou sémantickou mezeru mezi assemblerem a vyššími programovacími jazyky atd.

Vzhledem ke složitosti instrukční sady System/360 se v praxi používaly mikroprogramy, tj. jednodušší procesory s touto architekturou kompatibilní mnoho instrukcí přímo nevykonávaly, ale vlastně emulovaly na základě takzvaného mikrokódu (mikroinstrukcí uložených v řadiči) – jednalo se tedy o obdobu dnes populárních bytekódů, které také mohou být emulovány přímo v mikroprocesorech (mikroprogramem), nikoli uživatelským programem. Teprve mnohem později byly podobně koncipované instrukční sady a mikroprocesory nazvány CISC neboli Complex Instruction Set Code (v některých případech byly i mikroinstrukce pro přímé vykonání zbytečně složité, a proto byly rozkládány do takzvaných nanoinstrukcí, což vedlo ke snížení potřebné kapacity paměti v řadiči i zjednodušení návrhu samotného mikroprocesoru).

pc1004

Jeden z počítačů platformy System/360

Procesory s architekturou CISC se většinou vyznačují velmi obsáhlou instrukční sadou, mnohdy do značné míry ortogonální (tj. většina instrukcí může být použita se všemi adresními režimy). To ovšem vede k nutnosti použití složitého řadiče, instrukce trvají i několik desítek či stovek taktů a celková složitost mikroprocesoru obecně roste. Před několika lety se zdálo, že celá architektura CISC bude opuštěna a nahrazena architekturou RISC. Ve skutečnosti však vznikly jakési hybridní architektury – dnes nejpopulárnější mikroprocesory jsou sice interně vytvořeny jako RISCové, ale jejich instrukční sada je CISCová. V této kombinaci se ukazují výhody obou architektur: velká rychlost a interní jednoduchost RISCů a současně kratší kód instrukcí u CISC procesorů (snižují se nároky na vyrovnávací paměti). Pro příklad nemusíme chodit daleko, protože do tohoto stavu došla i platforma x86 (a před ní VAX či Motorola 68060). I populární RISCové procesory ARM obsahují instrukční sadu nazvanou Thumb, která umožňuje snížení velikosti programů o cca 30–40 % (kromě toho je pro tyto procesory dostupná i technologie Jazelle určená pro přímé provádění Javovského bytekódu).

pc1005

Mikroprocesor Motorola 68000 patří mezi zástupce architektury CISC s téměř ortogonální instrukční sadou

Skok do podprogramu, návrat z podprogramu i podmíněný skok jsou pro CISC procesor takovou malou tragédií, protože musí zapomenout všechny rozpracované instrukce a začít plnit instrukční pipeline pěkně od začátku (bližší informace si uvedeme v následující části seriálu). Z tohoto důvodu se u CISC procesorů začaly objevovat různé technologie, vytvořené původně pro RISC, umožňující takzvaně predikovat podmíněný skok (typické jsou jednobitové a dvoubitové prediktory skoků), překladače na požádání rozbalují smyčky (loop unrolling), využívají inline funkce apod. Žádnou z těchto technologií není zapotřebí používat například u zásobníkových či akumulátorových mikroprocesorů (viz další kapitoly), což samozřejmě přispívá k jejich konstrukční jednoduchosti.

Pro ilustraci „komplexnosti“ instrukční sady následuje příklad části programu napsaného v assembleru CISCové architektury x86. Všimněte si různých adresních režimů, implicitně zadaných operandů u instrukce imul, segmentového adresování pomocí segmentového registru es, i toho, že u aritmetických instrukcí je možné používat operandy přímo načítané z operační paměti (mov es, ax, add ax,[zy1]), což je pro CISCové architektury typické a naopak netypické pro architekturu RISC:

mov     ax,bp
sar     ax,cl
imul    ax          ; implicitní operandy: dx:ax=ax*ax
push    ax

mov     ax,bx
sar     ax,cl       ; při bitovém posunu se musí použít registr cl
imul    ax
mov     es:[di],ax  ; uložení obsahu registru do paměti

mov     ax,bp
sar     ax,cl
sar     bx,5
imul    bx          ; implicitní operandy: dx:ax=ax*bx
add     ax,[zy1]    ; jeden z operandů je načten z operační paměti
xchg    ax,bx

pop     ax
push    ax
sub     ax,es:[di]
add     ax,[zx1]
mov     bp, ax
pop     ax
add     ax,es:[di]
dec     ch
jz      short pokrac
cmp     ax,4*P
jc      short opak
stosb               ; další instrukce s implicitními operandy (porušení ortogonality) 
pc1006

I platforma x86 je architekturou CISC, i když do ortogonality své instrukční sady měla zejména v minulosti daleko

3. RISC – jednoduchost a rychlost

V předchozí kapitole jsme si řekli, že jednou z motivací zavedení komplexní instrukční sady byla pomoc programátorům i překladačům s tvorbou efektivních programů. Složité instrukce s mnoha adresními režimy apod. měly programátorům umožnit programovat v assembleru podobně, jako ve vyšším programovacím jazyku (ostatně například assembler Motoroly 68000 se dost přibližuje Céčku). I překladače měly mít ulehčenou práci, protože se mnoho konstrukcí z vyšších programovacích jazyků dalo zapsat malým množstvím strojových instrukcí.

Ovšem nakonec se ukázalo, že většina programátorů i překladačů zdaleka nepoužívá všechny dostupné instrukce, v některých případech se využívalo jen 30 % všech možných kombinací. To mj. znamená, že investice do složitého CISC mikroprocesoru byla vlastně v tom případě zbytečná, protože jeho velká část zůstala nevyužita. Když k tomuto faktu ještě připočteme, že samotné CISC procesory jsou velmi složité a v minulosti pro ně prakticky nebylo možné implementovat různé urychlovací technologie (prediktory skoků, out-of-order provádění instrukcí, spekulativní provádění instrukcí atd.), nelze se divit tomu, že se výrobci i vědci začali ohlížet po zcela odlišném řešení: místo filozofie „more is better“ se tedy začala upřednostňovat filozofie „less is better“ (ta je ostatně výhodnější i v dalších oblastech).

V roce 1980 firma IBM a lidé z University of Berkeley přišli s myšlenkou vytvořit procesor s jednoduchými instrukcemi s omezením ortogonality, menším množstvím adresních režimů atd. Vzhledem k tomu, že v té době začaly být mikroprocesory rychlejší než k nim připojované paměti (tento trend trvá dodnes, ovšem „nůžky“ v rychlosti se ještě více rozevřely), byla RISC procesorům dána do vínku další užitečná vlastnost: velké množství pracovních registrů, které bylo mnohdy ještě více zvětšené pomocí takzvaného registrového okna (více sad registrů, mezi kterými se dá přepínat). Pracovní registry slouží jako cache paměť nulté úrovně. Důležité je, že se všechny aritmetické i logické instrukce provádí právě s těmito registry, které jsou si rovnocenné (není zde tedy privilegovaný akumulátor), což velmi ulehčuje práci jak překladačům (alokace registrů), tak i programátorům píšícím programy v assembleru.

U RISC procesorů nastávají problémy při volání podprogramů a návratech z podprogramů, protože se přeruší plynulý tok instrukcí a tím pádem je zapotřebí vyprázdnit polozpracované instrukce z fronty instrukcí (pipeline). V praxi se tento problém řeší buď při překladu (rozbalování smyček – loop unrolling) nebo za běhu pomocí prediktorů skoků, out-of-order zpracováním instrukcí atd. Více si o těchto technologiích povíme příště.

pc1007

PA RISC firmy Hewlett-Packard (mikroprocesor spolu s podpůrnými obvody a vyrovnávacími paměťmi)

Mezi velmi úspěšné RISC procesory patří celá rodina mikroprocesorů označovaná MIPS. Mikroprocesory patřící do této rodiny byly použity jak u výkonných grafických stanic firmy SGI, tak i ve zcela opačném trhu: v embedded aplikacích, Nintendu 64, Sony PlayStation, PlayStation 2 atd. Čínští výrobci mají svoji verzi MIPS označovanou jako Godson popř. v anglicky mluvících zemích Dragon. Důvod velké oblíbenosti MIPS spočívá především v možnosti propojení jádra mikroprocesoru s dalšími obvody na jednom čipu, což je velmi často využíváno zejména v embedded aplikacích. V praxi to znamená možnost mít celé zařízení umístěné na jednom jediném čipu a programovat přitom na známé, výkonné a mnoha lety praxe odladěné architektuře.

pc1008

Mikroprocesor MIPS

O tom, že ne vždy je možné se přesně rozhodnout, zda je nějaký mikroprocesor typu RISC či CISC, svědčí následující graf, na kterém jsou mikroprocesory rozděleny jak podle bitové šířky, tj. šířky zpracovávaných operandů, tak i podle toho, zda se blíží spíše typické CISC architektuře nebo kanonické architektuře RISC.

    Complex/                                                         Simple/
      CISC____________________________________________________________RISC
      |                                                         14500B*
4-bit |                                                    *Am2901
      |                                   *4004
      |                                *4040
8-bit |                                     6800,650x         *1802
      |                       8051*  *  *8008   *    SC/MP
      |                              Z8    *         *    *F8
      |                F100-L*   8080/5  2650
      |                             *       *NOVA        *  *PIC16x
      |          MCP1600*   *Z-80         *6809    IMS6100
16-bit|          *Z-280           *PDP11             80C166*  *M17
      |                      *8086    *TMS9900
      |                 *Z8000          *65816
      |                *56002
      |            32016*   *68000 ACE HOBBIT  Clipper      R3000
32-bit|432           96002 *68020    *   *  *  *   *29000     *   *ARM
      | *         *VAX * 80486 68040 *PSC i960    *SPARC         *SH
      |          Z80000*    *  *    TRON48    PA-RISC
      |    PPro  Pent*    -- T9000 -*-------     *    *88100
      | *    *    -- 860 -*--*-----            *     *88110
64-bit|Rekurs         POWER PowerPC   *        CDC6600     *R4000
      |            x86-64*   *620 U-SPARC *     *R8000         *Alpha
      |     ------- IA-64 -------      R10000

4. Zásobníkové architektury

V předchozích dvou částech tohoto seriálu, konkrétně u popisu předávání parametrů do podprogramů a samotného volání podprogramů či přerušovacích rutin, jsme si ukázali význam zásobníku při zpracování strukturovaného programového kódu. Ovšem zásobníky se v některých případech využívají i při vyčíslování aritmetických a logických výrazů, kopírování dat a řízení programového kódu. Zásobníkové procesory jsou takové procesory, které manipulaci se zásobníkem podporují již ve svých instrukcích a mnohdy dokonce ve svém jádru jeden či více zásobníků obsahují (nebo alespoň několik nejvyšších položek zásobníku). Nejedná se však pouze o základní manipulaci se zásobníkem (tu zvládají prakticky všechny procesory), ale například o instrukce určené pro efektivní provádění výpočtů nad hodnotami uloženými v zásobníku, instrukce typu OVER, DUP apod. V praxi se můžeme setkat jak s čistě zásobníkovými procesory, tak i s různými modifikacemi, například kombinací zásobníkového procesoru a procesoru typu RISC.

pc1009

Zásobníkový mikroprocesor SEAforth-24

Zásobníkové procesory jsou určeny především ve vestavěných systémech (embedded devices), u kterých hrají velkou roli nepatrné systémové požadavky a cena. Vzhledem k tomu, že programový kód je u zásobníkových procesorů obecně kratší (nezávisle na složitosti programu) než u procesorů typu RISC a CISC (nemluvě o VLIW), mohou být také použity paměti s menší kapacitou a tím se může snížit i finální cena výrobku. Samotný zásobníkový procesor je také velmi jednoduchý, protože nemusí obsahovat sadu obecných registrů ani plánovač instrukcí. Další aplikační oblastí zásobníkových procesorů jsou systémy, u kterých je požadována vysoká rychlost zpracování a především rychlé odezvy systému na přerušení (není zapotřebí ukládat stav procesoru při příchodu přerušení, protože vše podstatné je stejně uloženo na zásobníku). V neposlední řadě jsou zásobníkové procesory použity i v některých družicích, kde provádí řídicí a měřící činnosti. Na druhou stranu jsou však zásobník či zásobníky úzkým místem, které do jisté míry zabraňuje využití instrukčního paralelismu.

Mezi zásobníkové procesory patří například všechny výrobky firem Minimum Instruction Set Computer, Inc., Novix, několik mikroprocesorů firmy Harris Semiconductor, minimalistické mikroprocesory F21 a X18 Chucka Moorea atd. Ovšem i procesory určené pro běh Javy (UltraJava, MicroJava a PicoJava) jsou ve skutečnosti zásobníkovými procesory.

Největším rozdílem mezi zásobníkovými procesory a procesory typu RISC je fakt, že zásobníkové procesory používají instrukce bez explicitního adresování operandů. U RISC procesorů se typicky používají instrukce se dvěma operandy, kterými bývají pracovní registry (viz pátá kapitola). Jedinou výjimku tvoří instrukce typu LOAD a STORE, které načítají obsah pracovního registru z operační paměti, nebo naopak ukládají obsah registru do operační paměti. Pro zajímavost: u mnoha zásobníkových mikroprocesorů se tyto instrukce jmenují FETCH a STORE, což vychází z pojmenování základních příkazů programovacího jazyka Forth (viz seriál o programovacím jazyce Forth).

Celková velikost programového kódu je u zásobníkových procesorů obecně menší, než u RISC procesorů. RISC procesory totiž mají velké množství registrů, pro jejichž specifikaci (adresaci) je nutné použít většího množství bitů v kódu instrukce. Dokonce se uvádí vtip, že velikost vyrovnávací paměti (cache) u RISC procesoru musí být větší než kapacita CELÉ operační paměti u zásobníkového procesoru, přičemž na obou procesorech běží programy stejnou rychlostí.

Jak může vypadat assemblerovský kód určený pro zásobníkové procesory? Všimněte si, že se u instrukcí nepoužívají operandy a celý kód vzdáleně připomíná Forth, což samozřejmě není náhoda:

; část kódu napsaná v assembleru pro zásobníkový procesor
; která vyčíslí výraz z=x*x+y*y
prom_x FETCH  ; načtení proměnné x a uložení na zásobník
DUP           ; duplikace nejvyšší hodnoty uložené na zásobníku (x)
MUL           ; na vrcholu zásobníku je nyní výsledek výrazu x*x
prom_y FETCH  ; načtení proměnné y a uložení na zásobník
DUP           ; duplikace nejvyšší hodnoty uložené na zásobníku (y)
MUL           ; na vrcholu zásobníku je nyní výsledek výrazu y*y
ADD           ; na vrcholu zásobníku je nyní výsledek výrazu x*x+y*y
prom_z        ; na zásobník se uloží adresa proměnné, kam se má výsledek uložit
STORE         ; uložení výsledku a jeho odstranění spolu s adresou 

5. Rozdělení instrukčních sad podle počtu explicitně adresovaných operandů

Instrukční sady mikroprocesorů je možné rozdělit podle různých kritérií. Jedním kritériem, které je patrné již na první pohled z libovolného (i docela krátkého) kódu napsaného pro daný mikroprocesor, je založeno na počtu operandů, které jsou explicitně adresovány v adresní části instrukce. Mohlo by se zdát, že u většiny aritmetických a logických instrukcí se vždy bude jednat o dva vstupní operandy a jeden operand výstupní (například ADD A,B,C, kde A je pracovní registr, do kterého se uloží výsledek operace), ovšem ve skutečnosti je situace poněkud složitější a tři operandy (2 vstupní a 1 výstupní) se používají pouze v malém množství případů, protože větší množství adres u instrukce celé instrukční slovo prodlužuje, což se projevuje zejména u procesorů typu RISC, které obecně mají velký počet pracovních registrů (například pro výběr jednoho z 32 registrů je zapotřebí 5 bitů). Pojďme si nyní říci, jaké možnosti při adresování operandů máme:

UX DAy - tip 2

  • Žádné explicitně zadané operandy se používají zejména u zásobníkových mikroprocesorů. Operandy není zapotřebí v adresní části instrukce v tomto případě zadávat, protože je dopředu známo, že se vybírají ze zásobníku, konkrétně z nejvyšší položky (TOS – Top Of Stack) a druhé, popř. u složi­tějších instrukcí i třetí položky. Výsledek operace se taktéž ukládá na zásobník, většinou pouze do nejvyšší položky (TOS). Výhodou těchto takzvaných bezadresových instrukcí je jejich velmi krátká délka, protože se v instrukčním kódu nemusí vytvářet prostor pro specifikaci zdrojů a cíle dat. Nevýhodou je úzké místo, které zásobník představuje při přípravě dat na výpočet. Zástupcem tohoto typu procesorů je například MISC M17, F21 (a další mikroprocesory vytvořené Chuckem Moorem), RTX 32P, b16 a ve své podstatě i mikroprocesory určené pro přímé provádění „strojového kódu“ zpracovávaného JVM (Java Virtual Machine).
  • Jeden explicitně zadaný operand je použit typicky u takzvaných akumulátorových mikroprocesorů (jedná se o nepřesný název, ovšem především v minulosti se poměrně často používal). Tyto mikroprocesory jsou charakteristické tím, že obsahují jeden specifický registr nazývaný akumulátor. Tento registr je použitý při prakticky všech výpočtech, proto ho není zapotřebí v instrukčním kódu uvádět (mikroprocesor ví, že jeden z operandů je vždy akumulátor a i výsledek se do něj ukládá – akumuluje). Typicky bývá akumulátor použit jako první operand a také jako místo, kam se uloží výsledek operace. Zástupcem tohoto typu procesorů, které byly vyráběné především v minulosti, je Intel 8080, Intel 8048 a také MOS 6502. Výhody a nevýhody akumulátorových procesorů jsou stejné (nevýhody jsou však větší), jako v případě procesorů zásobníkových: poměrně krátké instrukce a existence úzkého místa, kterým je nyní akumulátor. V praxi vypadají programy psané pro akumulátorové procesory tak, že cca 1/4 až 1/3 instrukcí tvoří přesuny mezi akumulátorem a ostatními pracovními registry popř. pamětí.
  • Dva explicitně zadané operandy jsou použity u takzvaných registrových mikroprocesorů, tj. u těch typů procesorů, které obsahují větší množství obecně použitelných (a v instrukcích adresovatelných) registrů. Jedná se o dnes nejpoužívanější procesory typu RISCCISC. V instrukčním kódu jsou specifikovány dva pracovní registry nebo paměťová místa – jeden registr je zdrojový a současně i cílový, druhý registr obsahuje druhý operand, který do instrukce vstupuje (samozřejmě se musí jednat o binární instrukce, unární instrukce používají pouze jeden registr). Výhodou těchto typu mikroprocesorů je snadná tvorba složitějších výpočtů a z toho plynoucí jednodušší práce pro překladače. Nevýhodou jsou dlouhé instrukční kódy a praktická nutnost použití pipeliningu. Známou architekturu Intel x86 lze zařadit do této kategorie, i když vykazuje i některé vlastnosti kategorie předchozí. Dále sem patří legendární Motorola 68000.
  • Tři explicitně zadané operandy jsou používané taktéž u registrových mikroprocesorů. Rozdíl oproti předchozí skupině je ten, že jsou explicitně specifikovány jak oba zdrojové operandy, tak i operand cílový. Ruční i automatická tvorba strojového kódu je jednoduchá (zde mají překladače snadnou práci, zejména ve chvíli, kdy mají k dispozici dostatek pracovních registrů), nevýhodou jsou dlouhé instrukce (samotný operační kód je stejný, ovšem prodlužuje se adresní část instrukce). Tříadresový kód je často použit jako abstraktní mezikód při překladu programu z vyšších programovacích jazyků, protože nad tříadresovým kódem je možné relativně snadno provádět různé optimalizace. Mezi zástupce mikroprocesorů využívajících tříadresové instrukce patří už zmíněná architektura MIPS, ve které jsou registry adresovány pomocí pěti bitů, tj. je k dispozici 32 pracovních registrů, z nichž některé mají speciální význam (například jeden z registrů vždy obsahuje nulu, čehož se u mnoha instrukcí dá využít).

6. Obsah další části seriálu

V následující části tohoto seriálu si podrobněji popíšeme některé způsoby urychlení vykonávání strojových instrukcí v mikroprocesoru. Možností urychlení existuje mnoho – použití rychlejších pamětí (cache), rozdělení instrukcí do menších částí a vykovávání těchto částí paralelně (pipelining), zmírnění negativního dopadu použití časově náročných skoků (speculative branches, branch predicting), paralelní zpracování instrukcí (VLIW, MMX, vektorové instrukce), paralelní zpracovávání více vláken (multithreading) či dokonce paralelní zpracování celých procesů v samostatných jádrech propojených přepínací sítí (multi-core) atd.

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.