3. Jak pracuje vektorový procesor


Vektorové počítače mívají obvykle různé funkční jednotky pro skalární a vektorové operace nebo alespoň různou metodu zpracování  vektorů  a  skalárů  ( skalárem  se - na rozdíl od vektoru - rozumí jedno reálné číslo). Jejich architektura je charakterizována několika specifickými vlastnostmi, z nichž vektorové operace realizované tzv.  pipeliningem  a organizace přenosu mezi procesorem a pamětí jsou nejdůležitější.

3.1 Pipelining

Pouze navenek se zdá, že se všech (řekněme) 64 složek obou vektorů sčítá najednou. Ve skutečnosti to probíhá trochu jinak. Mechanizmus, na němž je paralelita ve vektorovém procesoru založena, se nazývá  pipelining  (“protlačování potrubím, rourou”) a je založen na těchto zásadách:

Pipelining  si nyní vysvětlíme detailně na zpracování operace sčítání dvou vektorů ve vektorovém procesoru. Mějme dva vektory (dostatečné délky)

x = (x1,x2,...)
y
= (y1,y2,...)

jejichž součet má být umístěn v paměti jako vektor z.

Operace sčítání dvou čísel (skalárů - nikoli vektorů!) je v počítači obvykle tvořena těmito dílčími úkony:

  1. Přečti oba sčítance z registrů do funkční jednotky.
  2. Posuň mantisu s menším exponentem na úroveň druhé mantisy.
  3. Sečti mantisy.
  4. Normalizuj a vypočti exponent.
  5. Ulož součet do registru.

Schéma 1 znázorňuje postup zpracování, který nyní popíšeme. Předpokládejme pro názornost, že funkční jednotka našeho vektorového počítače má alespoň 5 segmentů, z nichž každý realizuje některý z úkonů 1 - 5, a že každý z těchto úkonů je realizován v jednom cyklu procesoru:

Ve schématu vidíme, že teprve po pěti cyklech (v 6. cyklu) je v registru k dispozici prvý součet

z1=x1+y1,

od této chvíle však je do registru dodána v každém cyklu jedna další složka vektoru z.

Schéma 1

Je tedy zřejmé, že je třeba  n+4  cyklů na sečtení dvou vektorů o   složkách. (To je pravda ovšem jen v tom případě, že všechny složky obou vektorů byly v registrech. Registry však mají určitou délku, která je specifická pro každý vektorový počítač; bývá 64 nebo 128. Jestliže mají sčítané vektory větší délku, je v registrech k dispozici nejprve prvých 64 složek obou vektorů a zbývající složky se zpracovávají až v “dalších etapách”. To může znamenat různý postup podle architektury počítače: další složky mohou být v jiném registru nebo se musí použité registry znovu naplnit atd.).

Vraťme se nyní k našemu časovému diagramu: Po zahájení operace sčítání neprodukuje funkční jednotka po dobu čtyř cyklů žádný výsledek. Tento čas se nazývá  startovací  (“startup time”) a je také pro architekturu vektorového počítače charakteristický. Je potřeba ho brát v úvahu při všech kalkulacích souvisejících s vektorizací programů. Kompilátory na vektorových počítačích dělají vektorizaci do značné míry automaticky a znají-li délku zpracovávaných vektorů, provádějí i tuto kalkulaci. V některých případech to může vést k tomu, že kompilátor “nepustí” krátké vektory do vektorových funkčních jednotek, ale nechá je postupně zpracovat ve skalární jednotce, jejíž rychlost nesouvisí obecně vůbec s rychlostí vektorových jednotek - i tuto skutečnost musí kompilátor “uvážit”.

V reálném vektorovém počítači je  pipelining  ještě rafinovanější, než jsme si na našem jednoduchém příkladě ukázali, takže zrychlení (“speedup”) vektorového počítače zvyšuje ještě více. Např. ve schématu 1 si všimněme, že v 7. cyklu už 1. segment “zahálí”. Architektura počítače umožňuje, aby tyto segmenty, kterých již není třeba pro dobíhající (vektorovou) operaci, mohly začít zpracovávat následující operaci. Kompilátor o tom ví a zařídí to, kdykoli to je možné (když za vektorovou operací následují skalární operace nebo skoky apod., musí nechat segmenty vektorové funkční jednotky zahálet; optimalizující kompilátory se však i v těchto případech snaží “pro ně najít práci” např. přeskupením programových instrukcí).

3.2 Paměti vektorových superpočítačů

Druhou významnou specifickou vlastností vektorových počítačů je organizace paměti, kterou popíšeme nyní.

Registry  jsou velmi rychlá paměťová zařízení, která mohou předat procesoru svůj obsah v jednom taktu. Bohužel jsou tak drahé, že jich v počítači musí být relativně málo - ne více než několik set. Vektorový počítač však musí mít v operační paměti miliony či miliardy čísel a kdyby měla být tato paměť konstruována jako registry, dosáhla by cena počítače astronomické výše. Háček je v tom, jak zorganizovat činnost počítače, aby spolupráce mezi procesorem a obecně “pomalejší” pamětí byla dostatečně rychlá. Nejběžnější způsob je založen na tom, že se paměť rozdělí do několika - např. 64 nebo 128 - bloků (anglicky “bank”) a procesor může současně komunikovat s každým z nich. Tak se kompenzuje to, že každé čtení z paměti nebo zápis do ní trvá několik taktů. Při dobré vyváženosti systému a správně napsaném programu může procesor i z “levnější” a “pomalejší” paměti dostat v každém taktu jednu položku: kompilátor zajistí, aby se složky všech vektorů ukládaly postupně do různých bloků. Teprve když byly všechny bloky využity a vektor není ještě celý umístěn, začne se zase od začátku. Za chvíli si to budeme ilustrovat na příkladě.

Doba, kterou paměť potřebuje k tomu, aby realizovala jednu komunikaci mezi blokem a procesorem, se nazývá  cyklus bloku . Je zřejmé, že systém je vyvážený (tj. umožní, aby se do procesoru v každém taktu dostala jedna položka), jestliže je paměť rozdělena alespoň do tolika bloků, kolik taktů trvá jeden cyklus bloku. 

Nejnáročnější na spolupráci mezi procesorem a pamětí bývají  DO-smyčky , pomocí nichž jsou mj. implementovány vektorové operace; jestliže jsou složky vektorů umístěny postupně v různých blocích, vybírají se operandy operací ve smyčce postupně stále z různých bloků paměti.

Cyklus bloku trvá ve vektorových počítačích obvykle 4 nebo 8 taktů, takže stačí rozdělit paměť do 4 nebo 8 bloků.

Uvažujme nyní pro jednoduchost operaci

y = x + u

v níž je na vstupu jen jeden proměnný vektor

x = (x1,x2,...,x18)

a kde

u = (1.0, 1.0,...,1.0)

Vektor x bude kompilátorem uložen v paměti rozdělené do 8 bloků tak, jak je znázorněno ve schématu 2, a operace přičítání konstanty bude kompilátorem přeložena do DO-smyčky 

DO 10 I = 1,18
Y(I) = X(I) + 1.0
10 CONTINUE

1

 

2

 

3

 

4

 

5

 

6

 

7

 

8

x1

 

x2

 

x3

 

x4

 

x5

 

x6

 

x7

 

x8

x9

 

x10

 

x11

 

x12

 

x13

 

x14

 

x15

 

x16

x17

 

x18

                       
                             
                             
                             
                             
                             

Schéma 2

Prvky vektoru x uložené postupně cyklicky v různých blocích podle schématu 2 se do procesoru zpracovávajícího tuto smyčku čtou podle schématu 3.

Schéma 3

Optimalizace překladu smyčky by měla zajistit, aby ukládání prvků vektoru y probíhalo bez kolize s čtením prvků vektoru x (aby se povel neukládal do bloku, z něhož se právě čte).

Jestliže cyklus bloku je 4 takty (tj. přečtení jedné položky trvá 4 takty), bude čtení prvých 9 prvků vektoru x z paměti do registru procesoru probíhat podle časového diagramu uvedeného v tabulce 1: počínaje 4. taktem má v každém taktu procesor k dispozici jeden prvek vektoru. Teprve v 9. taktu je požadováno čtení z bloku, z něhož se již četlo. V té době je však předchozí čtení z tohoto bloku již ukončeno.

Takt

Instrukce

V registru

1

čti x1

-

2

čti x2

-

3

čti x3

-

4

čti x4

x1

5

čti x5

x2

6

čti x6

x3

7

čti x7

x4

8

čti x8

x5

9

čti x9

x6

10

 

x7

11

 

x8

12

 

x9

Tabulka 1


© J. Nadrchal (28.4.2000)