Vektorový procesor - Vector processor

Ve výpočtu , je vektor procesor nebo procesor pole je centrální procesorová jednotka (CPU), který implementuje instrukční sada , kde její instrukce jsou navrženy tak, aby účinně a efektivně pracovat na velké jednorozměrná pole dat nazývají vektory . To je na rozdíl od skalárních procesorů , jejichž instrukce fungují pouze na jednotlivých datových položkách, a na rozdíl od některých stejných skalárních procesorů, které mají další aritmetické jednotky SIMD nebo SWAR . Vektorové procesory mohou výrazně zlepšit výkon při určitých úlohách, zejména při numerické simulaci a podobných úkolech. Techniky vektorového zpracování fungují také v hardwaru konzoly pro videohry a v grafických akcelerátorech .

Vektorové stroje se objevily na začátku 70. let a dominovaly designu superpočítačů v 70. až 90. letech, zejména na různých platformách Cray . Rychlý pokles poměru ceny a výkonu konvenčních návrhů mikroprocesorů vedl ke konci devadesátých let k zániku vektorového superpočítače.

Dějiny

Brzká práce

Vývoj zpracování vektorů začal na začátku 60. let minulého století ve Westinghouse v jejich projektu „Solomon“. Cílem Solomona bylo dramaticky zvýšit matematický výkon pomocí velkého počtu jednoduchých matematických koprocesorů pod kontrolou jediného hlavního CPU . CPU napájel jedinou společnou instrukci všem aritmetickým logickým jednotkám (ALU), jedné za cyklus, ale s jiným datovým bodem, na kterém každá pracovala. To umožnilo Solomonovu stroji použít jeden algoritmus na velkou datovou sadu , přiváděnou ve formě pole.

V roce 1962 Westinghouse projekt zrušil, ale úsilí bylo restartováno na University of Illinois jako ILLIAC IV . Jejich verze návrhu původně požadovala stroj 1 GFLOPS s 256 ALU, ale když byl v roce 1972 konečně dodán, měl pouze 64 ALU a mohl dosáhnout pouze 100 až 150 MFLOPS. Ukázalo se však, že základní koncept je zdravý, a když byl použit v aplikacích náročných na data, jako je výpočetní dynamika tekutin , byl ILLIAC nejrychlejším strojem na světě. Přístup ILLIAC pomocí použití samostatných ALU pro každý datový prvek není u pozdějších návrhů běžný a často se na něj odkazuje v samostatné kategorii, masivně paralelních výpočtů. V této době Flynn kategorizoval tento typ zpracování jako ranou formu SIMT .

Počítač pro práci s funkcemi byl prezentován a vyvinut Kartsev v roce 1967.

Superpočítače

K první úspěšné implementaci vektorového zpracování došlo v roce 1966, kdy byly představeny jak Control Data Corporation STAR-100, tak Texas Instruments Advanced Scientific Computer (ASC).

Základní ASC (tj. „Jedna trubka“) ALU používala architekturu potrubí, která podporovala skalární i vektorové výpočty, přičemž špičkový výkon dosahoval přibližně 20 MFLOPS, což bylo snadno dosaženo při zpracování dlouhých vektorů. Rozšířené konfigurace ALU podporovaly „dvě trubky“ nebo „čtyři trubky“ s odpovídajícím zvýšením výkonu 2X nebo 4X. Šířka pásma paměti byla dostatečná k podpoře těchto rozšířených režimů.

STAR-100 byl jinak pomalejší než vlastní superpočítače CDC , jako je CDC 7600 , ale při úkolech souvisejících s daty dokázali držet krok a přitom byly mnohem menší a levnější. Stroj však také potřeboval značný čas na dekódování vektorových instrukcí a na přípravu procesu, takže vyžadoval práci na velmi specifických sadách dat, než ve skutečnosti cokoli zrychlil.

Tato vektorová technika byla poprvé plně využita v roce 1976 slavným Cray-1 . Místo toho, aby data zůstala v paměti jako STAR-100 a ASC, měl design Cray osm vektorových registrů , z nichž každý obsahoval 64 64bitových slov. Vektorové instrukce byly použity mezi registry, což je mnohem rychlejší než rozhovor s hlavní pamětí. Zatímco STAR-100 by použil jedinou operaci na dlouhém vektoru v paměti a poté by se přesunul k další operaci, Cray design by načetl menší část vektoru do registrů a poté na tato data použil tolik operací, kolik by mohl , čímž se vyhnete mnoha mnohem pomalejším operacím přístupu k paměti.

Návrh Cray používal k implementaci vektorových instrukcí spíše paralelismus potrubí než více ALU. Kromě toho měl návrh zcela oddělené kanály pro různé instrukce, například sčítání/odčítání bylo implementováno v jiném hardwaru než násobení. To umožnilo zavést dávku vektorových instrukcí do každé z podjednotek ALU, což je technika, kterou nazývali vektorové řetězení . Cray-1 měl normálně výkon asi 80 MFLOPS, ale s až třemi běžícími řetězy mohl dosahovat maxima 240 MFLOPS a průměrně kolem 150-mnohem rychleji než jakýkoli stroj té doby.

Modul procesoru Cray J90 se čtyřmi skalárními/vektorovými procesory

Následovaly další příklady. Control Data Corporation se pokusila znovu vstoupit na špičkový trh se svým strojem ETA-10 , ale prodával se špatně a vzali to jako příležitost úplně opustit pole superpočítačů. V raných a střední 1980 japonských společností ( Fujitsu , Hitachi a Nippon Electric Corporation (NEC) zavedených založeného na registrech vektorové stroje podobně jako Cray-1, typicky je o něco rychlejší a mnohem menší. Oregon na bázi Floating Point Systems (FPS) postavené přídavné procesory pole pro minipočítače , později budování vlastních minisuperpočítačů .

Cray byl po celou dobu vedoucím představitelem výkonu a neustále porazil konkurenci sérií strojů, které vedly k Cray-2 , Cray X-MP a Cray Y-MP . Od té doby se trh se superpočítači mnohem více zaměřuje na masivně paralelní zpracování než na lepší implementace vektorových procesorů. Vzhledem k výhodám vektorového zpracování vyvinula společnost IBM Virtual Vector Architecture pro použití v superpočítačích spojujících několik skalárních procesorů, které fungují jako vektorový procesor.

Přestože jsou vektorové superpočítače připomínající Cray-1 v dnešní době méně populární, společnost NEC pokračovala ve výrobě tohoto typu počítačů až do současnosti díky své řadě počítačů SX . SX-Aurora TSUBASA v poslední době umísťuje procesor a buď 24 nebo 48 gigabajtů paměti na modul HBM 2 na kartu, která se fyzicky podobá grafickému koprocesoru, ale místo toho, aby sloužila jako koprocesor, je to hlavní počítač s počítač kompatibilní s PC, do kterého je zapojen, obsluhující podpůrné funkce.

Jedním extrémním a vzácným příkladem procesoru Array byl Aspex Microelectronics ASP, který se kategorizoval jako „Massive wide SIMD“, ale měl ALU na úrovni bitů a predikci bitové úrovně, a tak by mohl být definitivně považován za procesor Array (Vector). Linedancer, vydaný v roce 2010, obsahoval 4096 2bitových predikovaných SIMD ALU, každý s vlastní pamětí adresovatelnou obsahem , a byl schopen 800 miliard instrukcí za sekundu. Je zajímavé, že podle Flynnovy taxonomie byl ASP jak asociativním procesorem, tak i procesorem Array.

GPU

Moderní grafické procesorové jednotky ( GPU ) zahrnují řadu shaderových kanálů, které mohou být poháněny výpočetními jádry , a lze je považovat za vektorové procesory (používající podobnou strategii pro skrývání latence paměti). Jak ukazuje Flynnův papír z roku 1972, klíčovým rozlišovacím faktorem GPU založených na SIMT je to, že má jediný vysílač dekodéru instrukcí, ale že jádra přijímající a provádějící stejnou instrukci jsou jinak přiměřeně normální: jejich vlastní ALU, jejich vlastní soubory registrů, jejich vlastní jednotky Load/Store a jejich vlastní nezávislé datové mezipaměti L1. Ačkoli tedy všechna jádra současně provádějí přesně stejnou instrukci v blokovém kroku navzájem, dělají to se zcela odlišnými daty ze zcela odlišných paměťových míst. To je podstatně složitější a zapojenější než „Packed SIMD“ , který je striktně omezen pouze na provádění paralelních potrubních aritmetických operací. Ačkoli přesné interní detaily dnešních komerčních GPU jsou chráněným tajemstvím, tým MIAOW dokázal sestavit neoficiální informace dostatečné k implementaci podmnožiny architektury AMDGPU.

Srovnání s moderní architekturou

Od roku 2016 většina komoditních procesorů implementuje architektury, které obsahují instrukce SIMD s pevnou délkou . Při první inspekci je lze považovat za formu vektorového zpracování, protože fungují na více datových sadách (vektorových, explicitní) a vypůjčují si funkce od vektorových procesorů. Podle definice však přidání SIMD nemůže samo o sobě kvalifikovat procesor jako skutečný vektorový procesor, protože SIMD má pevnou délku a vektory jsou variabilní. Rozdíl je ilustrován níže na příkladech, které ukazují a porovnávají tři kategorie: Pure SIMD, Predicated SIMD a Pure Vector Processing.

Jiné konstrukce CPU obsahovat některé více instrukcí pro zpracování vektoru na více (vectorised) datových souborů, obvykle známé jako MIMD ( M ultiple I nstruction, M ultiple D ATA) a realizované s VLIW ( V ery L ong I nstruction W ord). Fujitsu FR-V / VDSI vektor procesor spojuje obě technologie.

Rozdíl mezi SIMD a vektorovým procesorem.

Ve srovnání s instrukčními sadami vektorového procesoru chybí instrukční sady SIMD. Nejdůležitější z nich je, že vektorové procesory, již ze své podstaty podle definice a designu, mají od svého vzniku vždy proměnnou délku.

Tam, kde se o SIMD čisté (pevné šířce, bez predikce) běžně mylně tvrdí, že je „vektory“ (protože SIMD se používá ke zpracování dat, která jsou vektory), prostřednictvím podrobné analýzy a srovnání historických a moderních ISA mohou skutečné vektorové procesory musí mít následující funkce, které žádný SIMD ISA nemá:

  • způsob, jak nastavit délku vektoru (jako je setvlinstrukce v RISCV RVV) nebo poskytnout funkci REP(opakování instrukcí) v nějaké formě, bez omezení opakování na sílu dvou
  • Iterace a redukce nad prvky ve Vektorech. Vektory RISC-V od verze 0.10 mají pouze redukci, zatímco systémy SX-Aurora a novější Cray mají iteraci i redukci.

Predicated SIMD (součást Flynnovy taxonomie ), což je komplexní individuální predikátová maska ​​na úrovni jednotlivých prvků pro každou instrukci Vector, která je nyní k dispozici v ARM SVE2. a AVX-512 , se téměř kvalifikuje jako vektorový procesor. Predicated SIMD používá pevnou šířku SIMD ALU, ale umožňuje lokálně řízenou (predikovanou) aktivaci jednotek, aby poskytoval vzhled vektorů s proměnnou délkou. Níže uvedené příklady pomáhají vysvětlit tyto kategorické rozdíly.

SIMD , protože se jedná o dávkové zpracování s pevnou šířkou, se podle návrhu nedokáže vyrovnat s iterací a redukcí. To je dále ilustrováno příklady níže.

Simd vs vector.png

Navíc, vektorové procesory mohou být účinněji využívat zdroje (pouze pomalejší hardware, spoření energie, ale stále dosáhnout propustnosti) a mají nižší latence než SIMD prostřednictvím vektoru řetězení .

Zvažte procesor SIMD i vektorový procesor pracující na 4 64bitových prvcích, které provádějí sekvenci LOAD, ADD, MULTIPLY a STORE. Pokud je šířka SIMD 4, pak musí procesor SIMD NAKLÁDAT 4 prvky úplně, než se bude moci přesunout na ADD, musí dokončit všechny ADD, než bude moci přejít na MULTIPLY, a podobně musí dokončit všechny MULTIPLY, než bude moci spustit OBCHODY. To je podle definice a podle návrhu .

Nutnost provádět 4 široké simultánní 64bitové LOADy a 64bitové OBCHODY je velmi nákladná na hardware (256bitové datové cesty do paměti). Mít také 4x 64bitové ALU, zejména VÍCENÁSOBNĚ. Aby se předešlo těmto vysokým nákladům, musel by procesor SIMD mít 1 široký 64bitový LOAD, 1 široký 64bitový STORE a pouze 2 široký 64bitový ALU. Jak je znázorněno na diagramu, který předpokládá model provedení s více problémy , důsledky jsou, že dokončení operací nyní trvá déle. Pokud není možné více problémů, operace trvají ještě déle, protože LD nemusí být vydán (spuštěn) současně s prvními ADD atd. Pokud existují pouze 4 široké 64bitové SIMD ALU, je doba dokončení ještě horší: pouze tehdy, když jsou dokončeny všechny čtyři LOADy, mohou začít operace SIMD a teprve po dokončení všech ALU operací mohou začít OBCHODY.

Naproti tomu vektorový procesor, i když je jediným problémem a nepoužívá žádné SIMD ALU, má pouze 1 široký 64bitový LOAD, 1 široký 64bitový STORE (a stejně jako v Cray-1 schopnost spustit MULTIPLY současně s ADD), může dokončit čtyři operace rychleji než procesor SIMD s 1-wide LOAD, 1-wide STORE a 2-wide SIMD. Toto efektivnější využití zdrojů díky řetězci vektorů je klíčovou výhodou a rozdílem oproti SIMD. SIMD podle návrhu a definice nemůže provádět řetězení kromě celé skupiny výsledků.

Popis

Obecně lze říci, že procesory jsou schopné manipulovat s jedním nebo dvěma daty najednou. Například většina procesorů má instrukci, která v podstatě říká „přidejte A do B a výsledek vložte do C“. Data pro A, B a C mohla být - alespoň teoreticky - zakódována přímo do instrukce. V efektivní implementaci jsou však věci jen zřídka tak jednoduché. Data se jen zřídka odesílají v nezpracované formě a místo toho se na ně „ukazuje“ předáním adresy na místo v paměti, kde jsou uložena data. Dekódování této adresy a získání dat z paměti nějakou dobu trvá, během nichž CPU tradičně nečinně čekal, až se objeví požadovaná data. Jak se rychlosti CPU zvýšily, tato latence paměti se historicky stala velkou překážkou výkonu; viz Paměťová zeď .

Aby se snížilo množství času spotřebovaného těmito kroky, většina moderních CPU používá techniku ​​známou jako instrukční pipeline, ve které instrukce procházejí postupně několika podjednotkami. První dílčí jednotka přečte adresu a dekóduje ji, další „načte“ hodnoty na těchto adresách a další provede samotnou matematiku. Při pipeliningu je „trikem“ začít dekódovat další instrukci ještě dříve, než první opustí CPU, a to způsobem montážní linky , takže dekodér adresy je neustále používán. Dokončení jakékoli konkrétní instrukce zabere stejnou dobu, čas známý jako latence , ale CPU může zpracovat celou dávku operací překrývajícím se způsobem mnohem rychleji a efektivněji, než kdyby to udělal jeden po druhém.

Vektorové procesory posouvají tento koncept ještě o krok dále. Místo pipeliningu pouze instrukcí také pipelineují samotná data. Procesor dostává instrukce, které říkají nejen přidat A do B, ale také přidat všechna čísla „odsud sem“ ke všem číslům „odtamtud tam“. Namísto neustálé dekódování instrukcí a následného načítání dat potřebných k jejich dokončení procesor načte jedinou instrukci z paměti a v definici samotné instrukce jednoduše vyplývá , že instrukce bude fungovat znovu na jiné položce dat, na adrese o jeden přírůstek větší než poslední. To umožňuje výrazné úspory času při dekódování.

Abychom ilustrovali, jaký to může být rozdíl, zvažte jednoduchý úkol sečtením dvou skupin po 10 číslech. V normálním programovacím jazyce by člověk napsal „smyčku“, která by postupně zachytila ​​každou dvojici čísel a poté je přidala. Pro CPU by to vypadalo nějak takto:

; Hypothetical RISC machine
; add 10 numbers in a to 10 numbers in b, storing results in c
; assume a, b, and c are memory locations in their respective registers
  move  $10, count   ; count := 10
loop:
  load  r1, a
  load  r2, b
  add   r3, r1, r2   ; r3 := r1 + r2
  store r3, c
  add   a, a, $4     ; move on
  add   b, b, $4
  add   c, c, $4
  dec   count        ; decrement
  jnez  count, loop  ; loop back if count is not yet 0
  ret

Ale pro vektorový procesor vypadá tento úkol značně odlišně:

; assume we have vector registers v1-v3 
; with size equal or larger than 10
  move   $10, count    ; count = 10
  vload  v1, a, count
  vload  v2, b, count
  vadd   v3, v1, v2
  vstore v3, c, count
  ret

Všimněte si úplného nedostatku opakování v instrukcích, protože je to hardware, který provedl 10 sekvenčních operací: počet smyček je ve skutečnosti založen na explicitním základě instrukcí .

Vector ISA ve stylu Cray to posouvají o krok dále a poskytují globální registr „count“ s názvem Vector Length (VL):

; again assume we have vector registers v1-v3
; with size larger than or equal to 10
  setvli  $10        # Set vector length VL=10
  vload   v1, a      # 10 loads from a
  vload   v2, b      # 10 loads from b
  vadd   v3, v1, v2  # 10 adds
  vstore v3, c       # 10 stores into c
  ret

Tento přístup má několik úspor.

  1. jsou zapotřebí pouze tři překlady adres. V závislosti na architektuře to může samo o sobě představovat značné úspory.
  2. Další úsporou je načítání a dekódování samotné instrukce, která musí být provedena pouze jednou místo deseti.
  3. Samotný kód je také menší, což může vést k efektivnějšímu využití paměti, zmenšení velikosti mezipaměti instrukcí L1, snížení spotřeby energie.
  4. Díky zmenšení velikosti programu má predikce větve snazší práci.
  5. Vzhledem k tomu, že délka (ekvivalentní šířce SIMD) není do instrukce pevně zakódována, je kódování nejen kompaktnější, ale je také „odolné vůči budoucnosti“ a umožňuje i návrhům integrovaných procesorů zvážit použití vektorů čistě pro získání všech ostatních výhod , spíše než jít na vysoký výkon.

Navíc v modernějších ISA vektorových procesorů bylo zavedeno „Fail on First“ nebo „Fault First“ (viz níže), což přináší ještě více výhod.

Ale více než to, vysoce výkonný vektorový procesor může mít více funkčních jednotek přidávajících tato čísla paralelně. Kontrola závislostí mezi těmito čísly není vyžadována, protože vektorová instrukce určuje více nezávislých operací. To zjednodušuje požadovanou logiku řízení a může dále zlepšit výkon tím, že se vyhne zablokování. Matematické operace se tak celkově dokončily mnohem rychleji, přičemž limitujícím faktorem je čas potřebný k načtení dat z paměti.

S tímto druhem řešení nelze útočit na všechny problémy. Zahrnutí těchto typů pokynů nutně zvyšuje složitost jádra CPU. Že složitost obvykle dělá další pokyny pomalejší-ie, kdykoliv je to sečtením mnoho čísel v řadě. Složitější instrukce také zvyšují složitost dekodérů, což může zpomalit dekódování běžnějších instrukcí, jako je běžné přidávání. ( To lze poněkud zmírnit tím, že se celý ISA bude řídit zásadami RISC : RVV přidá pouze 190 vektorových pokynů, a to i s pokročilými funkcemi. )

Vektorové procesory byly tradičně navrženy tak, aby fungovaly nejlépe pouze v případě, že je třeba zpracovat velké množství dat. Z tohoto důvodu byly tyto druhy CPU nalezeny především v superpočítačích , protože samotné superpočítače se obecně nacházely na místech, jako jsou centra pro předpověď počasí a fyzikální laboratoře, kde „drtí“ obrovské množství dat. Jak však ukazuje výše a ukazuje to RISC-V RVV, účinnost vektorových ISA přináší další výhody, které jsou přesvědčivé i pro případy použití Embedded.

Vektorové instrukce

Výše uvedený příklad vektorového pseudokódu přichází s velkým předpokladem, že vektorový počítač dokáže zpracovat více než deset čísel v jedné dávce. Pro větší množství čísel ve vektorovém registru je pro počítač nerealizovatelné mít registr tak velký. Výsledkem je, že vektorový procesor buď získá schopnost provádět smyčky sám, nebo vystaví programátorovi nějaký registr vektorového řízení (stavu), obvykle známý jako vektorová délka.

Samovolně se opakující instrukce se nacházejí v raných vektorových počítačích, jako je STAR-100, kde by výše uvedená akce byla popsána v jedné instrukci (poněkud podobné vadd c, a, b, $10). Nacházejí se také v architektuře x86 jako REPpředpona. V hardwaru lze tímto způsobem efektivně provádět pouze velmi jednoduché výpočty bez velmi velkého nárůstu nákladů. Protože pro architekturu STAR-100 musí být všechny operandy v paměti, latence způsobená přístupem byla také obrovská.

Je zajímavé, že Broadcom zahrnoval prostor ve všech vektorových operacích Videocore IV ISA pro REPpole, ale na rozdíl od STAR-100, který používá paměť pro své opakování, jsou opakování Videocore IV u všech operací, včetně aritmetických vektorových operací. Délka opakování může být malý rozsah síly dvou nebo získaný z jednoho ze skalárních registrů.

Cray-1 představil myšlenku použití registrů procesoru držet vektorová data v dávkách. Dávky šarže (Vector Length, VL) lze dynamicky nastavovat pomocí speciální instrukce, přičemž význam ve srovnání s Videocore IV (a, jak bude zásadně ukázáno níže, také SIMD) je ten, že délka opakování nemusí být součástí kódování instrukcí. Tímto způsobem lze v každé dávce odvést mnohem více práce a navíc je kódování instrukcí mnohem elegantnější a kompaktnější, jedinou nevýhodou je, že aby bylo možné plně využít této extra kapacity dávkového zpracování, odpovídajícím způsobem mělo zatížení paměti a rychlost ukládání také zvýšit. To je někdy prohlašováno za nevýhodu procesorů Vector ve stylu Cray: realita je taková, že jde jen o dosažení vysokého výkonu, jak je vidět na GPU , které čelí přesně stejnému problému. Řečeno hovorově: chcete číslo-křupání, potřebujete šířku pásma.

Moderní počítače SIMD tvrdí, že vylepšují ranou Cray přímo pomocí více ALU pro vyšší stupeň paralelismu ve srovnání s použitím pouze normálního skalárního potrubí. Moderní vektorové procesory (jako například SX-Aurora TSUBASA ) kombinují obojí, a to vydáváním více dat do více interních propojených SIMD ALU, přičemž vydané číslo je dynamicky zvoleno vektorovým programem za běhu. Masky lze použít k selektivnímu načítání a ukládání dat do paměťových míst a použít stejné masky k selektivnímu zakázání prvku zpracování SIMD ALU. Některé procesory se SIMD ( AVX-512 , ARM SVE2 ) jsou schopné tohoto druhu selektivního zpracování na prvek ( „predikované“ ) a právě tyto si poněkud zaslouží nomenklaturu „Vektorový procesor“ nebo si alespoň zaslouží nárok být schopen "vektorového zpracování". Procesory SIMD bez predikce na prvek ( MMX , SSE , AltiVec ) kategoricky ne.

Moderní GPU, které mají mnoho malých výpočetních jednotek, z nichž každá má své vlastní nezávislé SIMD ALU, používají něco, co se nazývá SIMT ( Single Instruction Multiple Threads ). Jednotky SIMT běží ze sdílené instrukční jednotky synchronizované s jediným vysíláním. "Vektorové registry" jsou velmi široké a potrubí bývá dlouhé. Část „navlékání“ SIMT zahrnuje způsob, jakým jsou data zpracovávána nezávisle na každé z výpočetních jednotek.

Kromě toho mohou GPU, jako je Broadcom Videocore IV, a další externí vektorové procesory, jako je NEC SX-Aurora TSUBASA, používat méně vektorových jednotek, než naznačuje šířka: namísto 64 jednotek pro registr o šířce 64 čísel může místo toho použít hardware proveďte propojenou smyčku přes 16 jednotek pro hybridní přístup. Broadcom Videocore IV je také schopen tohoto hybridního přístupu: nominálně uvádí, že jeho modul SIMD QPU Engine podporuje ve svých instrukcích 16-dlouhé operace pole FP, ve skutečnosti je provádí 4 najednou, jako (další) forma „vláken“.

Příklad vektorové instrukce

V tomto případě začneme s algoritmem („IAXPY“), nejprve jej ukážeme ve skalárních instrukcích, pak SIMD, pak Predicated SIMD a nakonec Vector instrukce. To postupně ukazuje rozdíl mezi tradičním vektorovým procesorem a moderním SIMD. Začínáme s 32bitovou celočíselnou variantou funkce "DAXPY", vc :

void iaxpy(size_t n, int a, const int x[], int y[]) {
    for (size_t i = 0; i < n; i++)
        y[i] = a * x[i] + y[i];
}

V každé iteraci má každý prvek y prvek x vynásobený a přidaný k němu. Program je pro čitelnost vyjádřen ve skalární lineární formě.

Skalární Assembler

Naše skalární verze toho načte jeden z každého z xay, zpracuje jeden výpočet, uloží jeden výsledek a smyčku:

loop:
  load32  r1, x      ; load one 32bit data
  load32  r2, y
  mul32   r1, a, r1  ; r1 := r1 * a
  add32   r3, r1, r2 ; r3 := r1 + r2
  store32 r3, y
  addl    x, x, $4   ; x := x + 4
  addl    y, y, $4
  subl    n, n, $1   ; n := n - 1
  jgz     n, loop    ; loop back if n > 0
out:
  ret

Kód podobný STAR zůstává stručný, ale protože vektorizace STAR-100 byla záměrně založená na přístupech do paměti, nyní ke zpracování informací potřebujeme další slot paměti. Kvůli dodatečnému požadavku na přístup k paměti je také zapotřebí dvojnásobná latence.

  ; Assume tmp is pre-allocated
  vmul tmp, a, x, n ; tmp[i] = a * x[i]
  vadd y, y, tmp, n ; y[i] = y[i] + tmp[i]
  ret

Čistá (bez predikce, zabalená) SIMD

Moderní architektura Packed SIMD, známá pod mnoha názvy (uvedena ve Flynnově taxonomii ), může většinu operací provádět v dávkách. Kód je většinou podobný skalární verzi. Předpokládáme, že x i y jsou zde správně zarovnány (začínají pouze na muliltiple 16) a že n je násobkem 4, protože jinak by k výpočtu masky nebo ke spuštění skalární verze byl zapotřebí nějaký instalační kód. Pro jednoduchost také předpokládáme, že instrukce SIMD mají možnost automaticky opakovat skalární operandy, stejně jako ARM NEON. Pokud tomu tak není, musí být použito „splat“ (vysílání), které zkopíruje skalární argument do registru SIMD:

  splatx4   v4, a        ; v4 = a,a,a,a

Trvaný čas by byl v zásadě stejný jako y = mx + cvýše popsaná vektorová implementace .

vloop:
  load32x4  v1, x
  load32x4  v2, y
  mul32x4   v1, a, v1  ; v1 := v1 * a
  add32x4   v3, v1, v2 ; v3 := v1 + v2
  store32x4 v3, y
  addl      x, x, $16  ; x := x + 16
  addl      y, y, $16
  subl      n, n, $4   ; n := n - 4
  jgz       n, vloop   ; go back if n > 0
out:
  ret

Všimněte si, že ukazatele x a y jsou zvýšeny o 16, protože to je doba (v bajtech) čtyři 32bitová celá čísla. Bylo rozhodnuto, že algoritmus bude jen vyrovnat se s 4-širokým SIMD, proto je konstanta pevně do programu.

Bohužel pro SIMD byl klíč ve výše uvedeném předpokladu, „že n je násobkem 4“ a také „zarovnaný přístup“, což je zjevně omezený případ speciálního použití.

Realisticky, pro smyčky obecného účelu, jako například v přenosných knihovnách, kde n nelze tímto způsobem omezit, může režie nastavení a vyčištění pro SIMD, aby se vyrovnala s násobky šířky SIMD, výrazně překročit počet instrukcí uvnitř samotná smyčka. Za předpokladu, že v nejhorším případě hardware nemůže provádět nevyrovnané přístupy do paměti SIMD, algoritmus reálného světa:

  • Nejprve musíte mít přípravnou sekci, která pracuje na počátečních nezarovnaných datech, až do prvního bodu, kde mohou převzít operace zarovnané s pamětí SIMD. to bude zahrnovat buď (pomalejší) skalární operace, nebo menší balené SIMD operace. každá kopie implementuje vnitřní smyčku celého algoritmu
  • proveďte zarovnanou smyčku SIMD s maximální šířkou SIMD až do několika posledních prvků (zbývajících, které neodpovídají pevné šířce SIMD)
  • mít fázi čištění, která je stejně jako přípravná část stejně velká a stejně složitá.

Osm širokých SIMD vyžaduje opakování algoritmu vnitřní smyčky nejprve se čtyřmi širokými prvky SIMD, pak dvěma širokými SIMD, pak jedním (skalárním), s testem a větví mezi každým, aby byla pokryta první a poslední zbývající SIMD prvků (0 <= n <= 7).

Tím se velikost kódu více než ztrojnásobí , ve skutečnosti to v extrémních případech vede k řádovému zvýšení počtu instrukcí! To lze snadno demonstrovat sestavování iaxpy příklad AVX-512 , s použitím volby "-O3 -march=knl"na gcc .

Postupem času, kdy se ISA vyvíjí, aby stále zvyšoval výkon, to má za následek, že ISA Architects přidává 2 široké SIMD, poté 4 široké SIMD, 8 širokých a více. Začínáme tedy chápat, proč AVX-512 existuje v x86.

Bez predikce platí, že čím je šířka SIMD širší, tím jsou problémy horší, což vede k masivnímu šíření operačního kódu, zhoršené výkonnosti, zvýšené spotřebě energie a zbytečné složitosti softwaru.

Na druhou stranu vektorové procesory jsou navrženy tak, aby vydávaly výpočty proměnné délky pro libovolný počet, n, a proto vyžadují velmi malé nastavení a žádné čištění. I ve srovnání s těmi SIMD ISA, které mají masky (ale bez setvlinstrukcí), produkují vektorové procesory mnohem kompaktnější kód, protože nepotřebují provádět explicitní výpočet masky, aby pokryly posledních několik prvků (znázorněno níže).

Predikovaná SIMD

Za předpokladu hypotetické predikované SIMD ISA s podporou masky (a s možností masky) a opět za předpokladu, že se instrukce SIMD dokážou vypořádat s nesprávně zarovnanými daty, bude instrukční smyčka vypadat takto:

vloop:
  # prepare mask. few ISAs have min though
  min       t0, n, $4     ; t0 = min(n, 4)
  shift     m, $1, t0     ; m = 1<<t0
  sub       m, m, $1      ; m = (1<<t0)-1
  # now do the operation, masked by m bits
  load32x4  v1, x, m
  load32x4  v2, y, m
  mul32x4   v1, a, v1, m  ; v1 := v1 * a
  add32x4   v3, v1, v2, m ; v3 := v1 + v2
  store32x4 v3, y, m
  # update x, y and n for next loop
  addl      x, t0*4      ; x := x + t0*4
  addl      y, t0*4
  subl      n, n, t0     ; n := n - t0
  # loop?
  jgz       n, vloop     ; go back if n > 0
out:
  ret

Zde vidíme, že kód je mnohem čistší, ale trochu složitý: alespoň však neexistuje žádné nastavení ani vyčištění: při poslední iteraci smyčky bude maska ​​predikátu nastavena buď na 0b0000, 0b0001, 0b0011, 0b0111 nebo 0b1111 , což má za následek provádění 0 až 4 operací s prvky SIMD. Jedna další potenciální komplikace: některé ISA RISC nemají instrukci „min“, místo toho potřebují použít oborové nebo skalární predikované srovnání.

Je jasné, jak si predikované SIMD přinejmenším zaslouží termín „Vector schopný“, protože si dokáže poradit s vektory s proměnnou délkou pomocí predikátových masek. Konečný vyvíjí krok k „pravému“ Vector ISA však je, že nebude mít žádný důkaz v ISA vůbec o šířce SIMD, opouštět, že záleží jen na hardware.

Čistý (pravdivý) vektor ISA

U vektorových ISA typu Cray, jako je RVV, se používá instrukce s názvem „setvl“ (nastavená délka vektoru). Hardware nejprve definuje, kolik datových hodnot může zpracovat v jednom "vektoru": může to být buď skutečné registry, nebo to může být vnitřní smyčka (hybridní přístup, uvedený výše). Tato maximální částka (počet hardwarových „drah“) se označuje jako „MVL“ (maximální délka vektoru). Všimněte si toho, jak jsme viděli v SX-Aurora a Videocore IV, MVL může být skutečné množství hardwarového pruhu nebo virtuální . (Poznámka: Jak je uvedeno v ARM SVE2 Tutorial, programátoři nesmí udělat tu chybu, že předpokládají pevnou šířku vektoru: MVL tedy není veličina, kterou programátor potřebuje vědět. To může být po letech SIMD myšlení trochu znepokojující).

Při volání setvl s počtem zbývajících datových prvků, které mají být zpracovány, je „setvl“ povoleno (více podobné, povinné) omezit to na maximální délku vektoru (MVL) a tím vrátí skutečné číslo, které může být zpracováno hardwarem v následné vektorové instrukce a nastaví interní speciální registr „VL“ na stejnou částku. ARM ve svých návodech na SVE2 označuje tuto techniku ​​jako program „Vector Length Agnostic“.

Níže je Cray-style Vector Assembler pro stejnou smyčku stylu SIMD, výše. Podívejte se pozorně, jak se místo pevně zakódovaných konstant používá t0 (který, obsahující pohodlnou kopii VL, může být různý):

vloop:
  setvl   t0, n      # VL=t0=min(MVL, n)
  vld32   v0, x      # load vector x
  vld32   v1, y      # load vector y
  vmadd32 v1, v0, a  # v1 += v0 * a
  vst32   v1, y      # store Y
  add     y, t0*4    # advance y by VL*4
  add     x, t0*4    # advance x by VL*4
  sub     n, t0      # n -= VL (t0)
  bnez    n, vloop   # repeat if n != 0

To se opravdu neliší od verze SIMD (zpracovává 4 datové prvky na smyčku) nebo od původní skalární verze (zpracovává pouze jednu). Vidíme, že n stále obsahuje počet zbývajících datových prvků, které mají být zpracovány, ale že t0 obsahuje kopii VL - číslo, které bude zpracováno v každé iteraci. t0 se odečte od n po každé iteraci, a pokud n je nula, pak byly zpracovány všechny prvky.

Při porovnávání s variantou montáže Predicated SIMD je třeba poznamenat řadu fascinujících věcí:

  1. setvlinstrukce má vestavěný v ní minnávodu
  2. Kde varianta SIMD pevně zakódovala jak šířku (4) do vytvoření masky, tak v šířce SIMD (zatížení32x4 atd.), Ekvivalenty Vector ISA nemají žádný takový limit. Díky tomu jsou programy Vector přenosné, nezávislé na dodavateli a připravené na budoucnost.
  3. nastavení VL efektivně vytvoří skrytou masku predikátu, která se automaticky použije na Vektory
  4. Tam, kde je u Predicated SIMD bitová délka masky omezena na tu, která může být držena ve skalárním (nebo speciální maskovém) registru, registry masky Vector ISA takové omezení nemají. Vektory Cray-I mohly mít něco přes 1 000 prvků (v roce 1977).

Můžeme tedy velmi jasně vidět, jak Vector ISA snižují počet instrukcí.

Všimněte si také, že stejně jako varianta Predicated SIMD jsou ukazatele na xay posunuty o t0 krát čtyři, protože oba ukazují na 32 bitová data, ale že n je sníženo o rovné t0. Ve srovnání s asimulátorem SIMD s pevnou velikostí je velmi malý zjevný rozdíl: xay jsou posunuty napevno kódovanou konstantou 16, n je sníženo o pevně zakódovanou 4, takže zpočátku je těžké ocenit význam. Rozdíl spočívá v poznání, že hardware Vector by mohl být schopen provádět 4 simultánní operace, nebo 64 nebo 10 000, pro všechny by to byl úplně stejný Vector Assembler a stále by neexistoval žádný kód pro čištění SIMD . I ve srovnání se SIMD podporujícím predikáty je stále kompaktnější, přehlednější, elegantnější a využívá méně prostředků.

Nejen, že máme mnohem kompaktnější program (úspora velikosti mezipaměti L1), ale jak již bylo zmíněno, verze Vector může vydávat mnohem více zpracování dat ALU, což opět šetří energii, protože instrukce Decode a Issue mohou sedět nečinně.

Ještě jeden fascinující aspekt: ​​počet prvků vstupujících do funkce může začínat na nule . Tím se nastaví délka vektoru na nulu, čímž se za běhu efektivně deaktivují všechny instrukce Vector a změní se na no-ops . Na rozdíl od nepředpovídané SIMD tedy stále neexistuje žádný zbytečně vyčištěný kód, i když nejsou k dispozici žádné prvky ke zpracování.

Příklad vektorové redukce

V tomto případě začneme s algoritmem, který zahrnuje redukci. Stejně jako v předchozím příkladu to nejprve ukážeme ve skalárních instrukcích, pak v SIMD a nakonec ve vektorových instrukcích. Začínáme v c :

void (size_t n, int a, const int x[]) {
    int y = 0;
    for (size_t i = 0; i < n; i++)
        y += x[i];
    return y;
}

Zde se k shrnutí všech hodnot v poli použije akumulátor (y), x.

Skalární Assembler

Naše skalární verze toho načte každé z x, přidá to do y a smyčka:

  set     y, 0     ; y initialised to zero
loop:
  load32  r1, x    ; load one 32bit data
  add32   y, y, r1 ; y := y + r1
  addl    x, x, $4 ; x := x + 4
  subl    n, n, $1 ; n := n - 1
  jgz     n, loop  ; loop back if n > 0
out:
  ret y            ; returns result, y

To je velmi jednoduché. "y" začíná na nule, 32 bitová celá čísla se načítají po jednom do r1, přidají se k y a adresa pole "x" se přesune na další prvek v poli.

Redukce SIMD

Zde začínají problémy. SIMD podle návrhu není schopen provádět aritmetické operace „mezi prvky“. Prvek 0 jednoho registru SIMD lze přidat k prvku 0 jiného registru, ale prvek 0 nelze přidat k ničemu jinému než k jinému prvku 0. Tím se potenciální implementace výrazně omezují. Pro jednoduchost předpokládejme, že n je přesně 8:

  addl      r3, x, $16 ; for 2nd 4 of x
  load32x4  v1, x      ; first 4 of x
  load32x4  v2, r3     ; 2nd 4 of x
  add32x4   v1, v2, v1 ; add 2 groups

V tomto okamžiku jsme provedli čtyři dodatky:

  • x[0]+x[4] - První SIMD ADD: prvek 0 první skupiny přidán k prvku 0 druhé skupiny
  • x[1]+x[5] - Second SIMD ADD: prvek 1 první skupiny přidán k prvku 1 druhé skupiny
  • x[2]+x[6] - Třetí SIMD ADD: prvek 2 první skupiny přidán k prvku 2 druhé skupiny
  • x[3]+x[7] - Čtvrtá SIMD ADD: prvek 3 první skupiny přidán k prvku 2 druhé skupiny

ale vzhledem k tomu, že SIMD o šířce 4 není konstrukčně schopen přidávat, x[0]+x[1]například věci jdou rychle z kopce, stejně jako u obecného případu použití SIMD pro univerzální smyčky IAXPY. Abych to shrnul své čtyři dílčí výsledky, dva celé SIMD může být použita, po němž následuje jedinou skalární doplňku, aby konečně vyrábět odpověď, ale často, musí být data přenášena z dedikovaných SIMD registrů před posledním skalární výpočet může být proveden .

I při obecné smyčce (n není pevná) je jediným způsobem, jak použít SIMD o šířce 4, předpokládat čtyři oddělené „proudy“, každý posunutý o čtyři prvky. Nakonec je třeba sečíst čtyři dílčí výsledky. Další techniky zahrnují náhodné přehrávání: online příklady najdete pro AVX-512, jak provést „horizontální součet“

Kromě velikosti programu a složitosti vyvstává další potenciální problém, pokud je zahrnut výpočet s plovoucí desetinnou čárkou: skutečnost, že hodnoty nejsou sčítány v přísném pořadí (čtyři dílčí výsledky), může mít za následek chyby zaokrouhlování.

Vektorové snížení ISA

Sady vektorových instrukcí mají v ISA integrovány aritmetické redukční operace . Pokud můžeme předpokládat, že n je menší nebo rovno maximální délce vektoru, jsou vyžadovány pouze tři pokyny:

  setvl      t0, n  # VL=t0=min(MVL, n)
  vld32      v0, x  # load vector x
  vredadd32  y, v0  # reduce-add into y

Kód, když n je větší než maximální délka vektoru, není o tolik složitější a je podobným vzorem jako v našem prvním příkladu („IAXPY“).

  set     y, 0
vloop:
  setvl   t0, n      # VL=t0=min(MVL, n)
  vld32   v0, x      # load vector x
  vredadd32 y, y, v0 # add all x into y
  add     x, t0*4    # advance x by VL*4
  sub     n, t0      # n -= VL (t0)
  bnez    n, vloop   # repeat if n != 0
  ret y

Ve srovnání se SIMD je jednoduchost algoritmu značná. Opět, stejně jako u příkladu IAXPY, je algoritmus agnostický podle délky (dokonce i u implementací Embedded, kde by maximální vektorová délka mohla být pouze jedna).

Implementace v hardwaru mohou, pokud jsou si jisti, že bude vytvořena správná odpověď, provádět redukci paralelně. Některé vektorové ISA nabízejí jako explicitní možnost režim paralelní redukce, když programátor ví, že na potenciálních chybách zaokrouhlení nezáleží a nízká latence je kritická.

Tento příklad opět zdůrazňuje klíčový zásadní zásadní rozdíl mezi „skutečnými“ vektorovými procesory a těmi procesory SIMD, včetně většiny komerčních GPU, které jsou „inspirovány“ funkcemi vektorových procesorů.

Postřehy z příkladů

Ve srovnání s jakýmkoli procesorem SIMD, který tvrdí, že je vektorovým procesorem, je řádové zmenšení velikosti programu téměř šokující. Tato úroveň elegance na úrovni ISA má však na hardwarové úrovni poměrně vysokou cenu:

  1. Z příkladu IAXPY vidíme, že na rozdíl od procesorů SIMD, které mohou zjednodušit svůj interní hardware tím, že se vyhnou řešení nesouladného přístupu k paměti, se vektorový procesor takovému zjednodušení nevyhne: jsou psány algoritmy, které ze své podstaty spoléhají na to, že Vector Load and Store bude úspěšný, bez ohledu na zarovnání začátku vektoru.
  2. Zatímco na příkladu redukce vidíme, že kromě permutačních instrukcí se SIMD podle definice zcela vyhýbá meziprostorovým operacím (prvek 0 lze přidat pouze k jinému prvku 0), vektorové procesory řeší tento problém čelně. Co jsou programátoři nuceni dělat v softwaru (pomocí shuffle a dalších triků, pro výměnu dat do správného „pruhu“), musí vektorové procesory dělat v hardwaru, automaticky.

Celkově pak existuje možnost buď mít

  1. komplexní software a zjednodušený hardware (SIMD)
  2. zjednodušený software a složitý hardware (vektorové procesory)

Tyto výrazné rozdíly jsou tím, co odlišuje vektorový procesor od toho, který má SIMD.

Funkce vektorového procesoru

Tam, kde si mnoho SIMD ISA „vypůjčuje“ nebo „inspiruje“ níže uvedený seznam, typické vlastnosti, které dobrý vektorový procesor bude mít, jsou:

  • Vector Load and Store - tyto neodmyslitelně ukládají vyhledávání virtuální paměti a jsou navrženy tak, aby vkládaly data do registrů s minimem starostí. Pokročilá vylepšení Vector Load/Store zahrnují podporu pro strukturování , Fail-First, Gather-scatter , Indexed, Unit a Element strides.
  • Maskované operace - jak se nyní běžně vyskytuje v GPU , masky predikátů umožňují paralelní konstrukce if/then/else bez větví (které jsou ze své podstaty skalární)
  • Komprimovat a rozbalit -obvykle pomocí bitové masky jsou data lineárně komprimována nebo rozšiřována (redistribuována) podle toho, zda jsou bity v masce nastaveny nebo čisté, přičemž vždy zachovává sekvenční pořadí a nikdy neduplikuje hodnoty (na rozdíl od Gather-Scatter aka permute) . Tyto pokyny jsou obsaženy v AVX-512
  • Register Gather, Scatter (aka permute) - méně omezující obecnější variace motivu Komprimovat/Rozbalit, která místo toho potřebuje jeden Vektor k určení indexů, které se použijí k „změně pořadí“ jiného Vektoru. Gather/Scatter je implementovatelnější než Compress/Expand, a protože je ze své podstaty nesekvenční, může interferovat s vektorovým řetězcem . Nesmí být zaměňováno s režimy Gather-scatter Memory Load/Store, Gather/Scatter Vector působí na vektorové registry a často se místo toho nazývají permutační instrukce .
  • Splat a Extract - užitečné pro interakci mezi Scalar a Vector, které vysílají jednu hodnotu napříč Vectorem, nebo extrahují jednu položku z Vectoru.
  • Iota -velmi jednoduchá a strategicky užitečná instrukce, která převádí postupně se zvyšující immediály do po sobě jdoucích prvků. Obvykle začíná od nuly.
  • Redukce a iterace - operace, které provádějí mapreduce na Vectoru (například najděte jednu maximální hodnotu celého Vectoru nebo sečtěte všechny prvky). Iterace je formy, x[i] = y[i] + x[i-1]kde Redukce je formyx = y[0] + y[1]… + y[n-1]
  • Podpora Matrix Multiply -buď pomocí algoritmického načítání dat z paměti, nebo přeskupením (přemapováním) normálně lineárního přístupu k prvkům Vector, nebo poskytnutím „Akumulátorů“, lze efektivně zpracovávat matice libovolné velikosti. IBM POWER10 poskytuje pokyny MMA, i když pro libovolné šířky matice, které neodpovídají přesné technice opakování dat velikosti SIMD, jsou zapotřebí, což je plýtvání prostředky registračních souborů. Aspex ASP Linedancer měl modul DMA pro změnu pořadí 2D/3D paměti, což vyžadovalo značné úsilí k optimálnímu využití. NVidia poskytuje API Matrix CUDA na vysoké úrovni, i když interní podrobnosti nejsou k dispozici. Nejúčinnější technikou z hlediska zdrojů je přeuspořádání přístupu k jinak lineárním vektorovým datům na místě.
  • Pokročilé matematické formáty -často zahrnují aritmetiku pole Galois , ale mohou zahrnovat binární kódování desítkové nebo desetinné pevné body a podporu pro mnohem větší (libovolnou přesností) aritmetické operace podporou paralelního přenosu a provádění
  • Bitová manipulace -včetně vektorových verzí operací bitové permutace, vkládání a vyjímání bitového pole, operace centrifugy, počet obyvatel a mnoho dalších .

Funkce vektorového zpracování GPU

U mnoha aplikací 3D Shader, které vyžadují trigonometrické operace i krátké vektory pro běžné operace (RGB, ARGB, XYZ, XYZW), je v moderních GPU kromě těch, které se nacházejí ve vektorových procesorech, obvykle k dispozici podpora následujících:

  • Subvektory- prvky mohou typicky obsahovat dva, tři nebo čtyři subelementy (vec2, vec3, vec4), kde se jakýkoli daný bit predikátové masky vztahuje na celý vec2/3/4, nikoli na prvky v subvektoru . Sub-vektory jsou také zavedeny v RISC-V RVV (nazývané "LMUL"). Subvektory jsou zásadní integrální součástí specifikace Vulkan SPIR-V .
  • Sub-vektor Swizzle -aka „Lane Shuffling“, který umožňuje sub-vektorové mezičlánkové výpočty bez nutnosti dalších (nákladných, nehospodárných) instrukcí pro přesun dílčích prvků do správných „pruhů“ SIMD. Také ukládá bity masky predikátu. Účinně se jedná o letovou minipermut sub-vektoru, která je výraznou součástí binárních souborů 3D Shader, a je dostatečně důležitá, aby mohla být součástí specifikace Vulkan SPIR-V . Broadcom Videocore IV používá terminologii „Lane rotate“, kde zbytek odvětví používá termín „swizzle“ .
  • Transcendentály - trigonometrické operace, jako je sinus , kosinus a logaritmus, se zjevně zobrazují mnohem více převážně ve 3D než v mnoha náročných úlohách HPC . Zajímavé však je, že rychlost je mnohem důležitější než přesnost ve 3D pro GPU, kde výpočet souřadnic pixelu jednoduše nevyžaduje vysokou přesnost. Specifikace Vulkan to uznává a stanoví překvapivě nízké požadavky na přesnost, takže hardware GPU může snížit spotřebu energie. Koncept snížení přesnosti tam, kde to jednoduše není potřeba, je prozkoumán v rozšíření MIPS-3D .

Mezi další funkce patří mapovací jednotka textury, která je někdy samostatnou jednotkou od hlavního procesoru GPU. Často jsou také zahrnuty pokyny pro interpolaci textury a několik dalších speciálních pokynů, jako je vektorová normalizace a bodový produkt .

O moderních sadách instrukcí GPU není veřejně k dispozici mnoho. Další informace a rady k funkcím GPU Vector ISA lze nalézt ve specifikaci SPIR-V , Vulkan a OpenCL . Tato API byla vytvořena skupinou Khronos členy, jako jsou Intel, Google, AMD a NVIDIA, a poskytují tak pohled na funkce poskytované nejrychlejšími GPU na světě. Pomáhá také zpětně navržená instrukční sada MALI Midgard GPU.

Chyba (nebo selhání) Nejprve

Představený v ARM SVE2 a RISC-V RVV je koncept spekulativních sekvenčních vektorových zatížení. ARM SVE2 má speciální registr s názvem „First Fault Register“, kde RVV upravuje (zkracuje) délku vektoru (VL).

Základním principem je nejprve pokus o velké sekvenční načtení vektoru, ale umožnění hardwaru libovolně zkrátit skutečné načtené množství buď na částku, která by uspěla bez vyvolání poruchy paměti, nebo jednoduše na částku (větší než nula), která je nejpohodlnější. Důležitým faktorem je, že následné pokyny jsou oznámeny nebo mohou přesně určit, kolik zatížení skutečně uspělo, s použitím tohoto množství pouze k provedení práce na datech, která byla skutečně načtena.

Kontrastujte tuto situaci se SIMD, což je pevná (nepružná) šířka zátěže a pevná šířka zpracování dat, která se nedokáže vyrovnat se zátěžími, které překračují hranice stránky, a i kdyby byly, nedokážou se přizpůsobit tomu, co se skutečně podařilo, ale paradoxně pokud by se program SIMD dokonce pokusil předem zjistit (v každé vnitřní smyčce, pokaždé), co by mohlo optimálně uspět, tyto instrukce slouží pouze k omezení výkonu, protože by podle potřeby byly součástí kritické vnitřní smyčky.

Začíná to naznačovat důvod, proč je ffirst tak inovativní, a nejlépe jej ilustruje memcpy nebo strcpy, když je implementován se standardní 128bitovou nepředpovídanou nefirstní SIMD. Pro IBM POWER9 je počet ručně optimalizovaných instrukcí k implementaci strncpy vyšší než 240. Naproti tomu stejná rutina strncpy v ručně optimalizovaném RVV assembleru je pouhých 22 instrukcí.

Výše uvedený příklad SIMD by mohl potenciálně způsobit poruchu a selhání na konci paměti kvůli pokusům přečíst příliš mnoho hodnot: mohlo by to také způsobit značný počet chyb na stránce nebo nesprávné zarovnání podobným překračováním hranic. Naproti tomu tím, že umožňuje vektorové architektuře svobodu rozhodovat o tom, kolik prvků se má načíst, první část strncpy, pokud začíná zpočátku na suboptimální hranici paměti, může vrátit jen tolik zatížení, že při následných iteracích smyčky dávky čtení vektorizované paměti jsou optimálně zarovnány se základními mezipaměti a uspořádáním virtuální paměti. Kromě toho se hardware může rozhodnout využít příležitost ukončit čtení jakékoli paměti iterace dané smyčky přesně na hranici stránky (vyhnout se nákladnému druhému vyhledávání TLB), přičemž spekulativní spuštění připraví další stránku virtuální paměti, zatímco data se stále zpracovávají v aktuálním smyčka. To vše je určeno hardwarem , nikoli samotným programem.

Výkon a zrychlení

Nechť r je poměr vektorové rychlosti a f je poměr vektorizace. Je -li čas potřebný na přidání jednotky 64 čísel do pole 64 čísel 10krát rychlejší než ekvivalent jejího skalárního protějšku, r = 10. Také pokud je celkový počet operací v programu 100, z nichž pouze 10 je skalárních (po vektorizaci), pak f = 0,9, tj. 90% práce je provedeno vektorovou jednotkou. Z toho vyplývá dosažitelné zrychlení:

Takže i když je výkon vektorové jednotky velmi vysoký ( ), dosáhneme zrychlení menší než , což naznačuje, že poměr f je pro výkon rozhodující. Tento poměr závisí na účinnosti kompilace, jako je sousednost prvků v paměti.

Programování heterogenních počítačových architektur

Byly navrženy různé stroje tak, aby zahrnovaly jak tradiční procesory, tak vektorové procesory, například Fujitsu AP1000 a AP3000. Programování takových heterogenních strojů může být obtížné, protože vývoj programů, které nejlépe využívají vlastnosti různých procesorů, zvyšuje zátěž programátora. Zvyšuje složitost kódu a snižuje přenositelnost kódu tím, že vyžaduje, aby byl kód specifický pro hardware vložen do kódu aplikace. Vyrovnávání pracovní zátěže aplikací mezi procesory může být problematické, zejména vzhledem k tomu, že obvykle mají různé výkonnostní charakteristiky. K řešení problému existují různé koncepční modely, například pomocí koordinačního jazyka a programových stavebních bloků (programovací knihovny nebo funkce vyššího řádu). Každý blok může mít pro každý typ procesoru jinou nativní implementaci. Uživatelé jednoduše programují pomocí těchto abstrakcí a inteligentní překladač vybere nejlepší implementaci na základě kontextu.

Viz také

externí odkazy

Reference