Miért is kell(ene) az AGLU a Bulldozer-be?
"And two which handle address generation and simple ALU operations (AGLU)."
Nézzük ezt az egyszerű for-ciklust:
@decrease_free_row:
mov edx,[edi+ecx*04h+__COLROWMARK]
xor edx,eax
or edx,[esi+ecx]
mov edx,00000000h
cmovns edx,eax
sub [esi+ecx],edx
add ecx,04h
jnz @decrease_row_free
Tegyük fel, hogy rendesen igazított a kód, azaz teljesen belefér egy 32 byte-os aligned memóriaterületre, így a dekódolás nem szűk keresztmetszet.
A következő lefutási képe van 4 cikluslefutásnak K10-en (K10-en kénytelen azon az ALU/AGU-n futni az utasítás, amelyre a dekódolás során esik az adott órajelben dekódolt utasításhármasban):
decode:
00 (1)mov edx,[edi+ecx*04h+__COLROWMARK] (1)xor edx,eax (1)or edx,[esi+ecx]
01 (1)mov edx,00000000h (1)cmovns edx,eax (1)sub [esi+ecx],edx
02 (1)add ecx,04h (1)jnz @decrease_row_free (1)
03 (2)mov edx,[edi+ecx*04h+__COLROWMARK] (2)xor edx,eax (2)or edx,[esi+ecx]
04 (2)mov edx,00000000h (2)cmovns edx,eax (2)sub [esi+ecx],edx
05 (2)add ecx,04h (2)jnz @decrease_row_free (2)
06 (3)mov edx,[edi+ecx*04h+__COLROWMARK] (3)xor edx,eax (3)or edx,[esi+ecx]
07 (3)mov edx,00000000h (3)cmovns edx,eax (3)sub [esi+ecx],edx
08 (3)add ecx,04h (3)jnz @decrease_row_free (3)
09 (4)mov edx,[edi+ecx*04h+__COLROWMARK] (4)xor edx,eax (4)or edx,[esi+ecx]
10 (4)mov edx,00000000h (4)cmovns edx,eax (4)sub [esi+ecx],edx
11 (4)add ecx,04h (4)jnz @decrease_row_free (4)
exec:
clk 1. ALU 1.AGU | 2. ALU 2.AGU | 3. ALU 3.AGU
---------------------------------------- | ------------------------------------- | -----------------------------------
01 (1)mov edx,[esi+ecx*4] | | (1)ld x1,[esi+ecx]
02 (1)mov edx,0 | | (1)ld y1,[esi+ecx]
03 (1)add ecx,4 | |
04 (2)mov edx,[esi+ecx*4] | (1)xor edx,eax | (2)ld x2,[esi+ecx]
05 (2)mov edx,0 | (1)jnz @decrease_free_row | (1)or edx,x1 (2)ld y2,[esi+ecx]
06 (2)add ecx,4 | (1)cmovns edx,eax |
07 (3)mov edx,[esi+ecx*4] | (2)xor edx,eax | (1)sub y1,edx (3)ld x3,[esi+ecx]
08 (3)mov edx,0 | (2)jnz @decrease_free_row | (2)or edx,x2 (1)st [esi+ecx],y1
09 (3)add ecx,4 | (2)cmovns edx,eax | (3)ld y3,[esi+ecx]
10 (4)mov edx,[esi+ecx*4] | (3)xor edx,eax | (2)sub y2,edx (4)ld x4,[esi+ecx]
11 (4)mov edx,0 | (3)jnz @decrease_free_row | (3)or edx,x3 (2)st [esi+ecx],y1
12 (4)add ecx,4 | (3)cmovs edx,eax | (4)ld y4,[esi+ecx]
13 | (4)xor edx,eax | (3)sub y3,edx
14 | (4)jnz @decrease_free_row | (4)or edx,x4 (3)st [esi+ecx],y3
15 | (4)cmovns edx,eax |
16 | | (4)sub y4,edx
17 | | (4)st [esi+ecx],y4
A következő lefutási képe van 4 cikluslefutásnak Bulldozer-en (itt már egységes ütemező van a 4 végrehajtóra):
decode:
00 (1)mov edx,[edi+ecx*04h+__COLROWMARK] (1)xor edx,eax (1)or edx,[esi+ecx] (1)mov edx,00000000h
01 (1)cmovns edx,eax (1)sub [esi+ecx],edx (1)add ecx,04h (1)jnz @decrease_row_free
02 (2)mov edx,[edi+ecx*04h+__COLROWMARK] (2)xor edx,eax (2)or edx,[esi+ecx] (2)mov edx,00000000h
03 (2)cmovns edx,eax (2)sub [esi+ecx],edx (2)add ecx,04h (2)jnz @decrease_row_free
04 (3)mov edx,[edi+ecx*04h+__COLROWMARK] (3)xor edx,eax (3)or edx,[esi+ecx] (3)mov edx,00000000h
05 (3)cmovns edx,eax (3)sub [esi+ecx],edx (3)add ecx,04h (3)jnz @decrease_row_free
06 (4)mov edx,[edi+ecx*04h+__COLROWMARK] (4)xor edx,eax (4)or edx,[esi+ecx] (4)mov edx,00000000h
07 (4)cmovns edx,eax (4)sub [esi+ecx],edx (4)add ecx,04h (4)jnz @decrease_row_free
exec:
clk ALU0 | ALU1 | AG0 | AG1
| | |
01 (1)mov edx,0 | | (1)mov edx,[esi+ecx*4] | (1)ld x1,[esi+ecx]
02 (1)add ecx,4 | | (1)ld y1,[esi+ecx] |
03 (2)mov edx,0 | (1)jnz @decrease_free_row | (2)mov edx,[esi+ecx*4] | (2)ld x2,[esi+ecx]
04 (2)add ecx,4 | | (2)ld y2,[esi+ecx] |
05 (1)xor edx,eax | (2)jnz @decrease_free_row | (3)mov edx,[esi+ecx*4] | (3)ld x3,[esi+ecx]
06 (1)or edx,x1 | (3)mov edx,0 <<< +1 | (3)ld y3,[esi+ecx] |
07 (1)cmovns edx,eax | (2)xor edx,eax | |
08 (1)sub y1,edx | (2)or edx,x2 | |
09 (2)cmovns edx,eax | (3)xor edx,eax | (1)st [esi+ecx],y1 |
10 (2)sub y2,edx | (3)or edx,x3 | |
11 (3)cmovns edx,eax | (3)add ecx,4 <<< +5 | (2)st [esi+ecx],y2 |
12 (3)sub y3,edx | (3)jnz @decrease_free_row | (4)mov edx,[esi+ecx*4] | (4)ld x4,[esi+ecx]
13 | | (3)st [esi+ecx],y3 |
14 | | (4)ld y4,[esi+ecx] <<< +1 |
15 | | |
16 (4)xor edx,eax | | |
17 (4)or edx,x4 | | |
18 (4)cmovns edx,eax | | |
19 (4)sub y4,edx | | |
20 | | (4)st [esi+ecx],y3 |
AGLU-val (ADD + logic képesség az AGU-knak) felszerelt esetben ez lenne a lefutási kép (a decode azonos):
exec:
clk ALU0 | ALU1 | AG0 | AG1
| | |
01 (1)mov edx,0 | | (1)mov edx,[esi+ecx*4] | (1)ld x1,[esi+ecx]
02 (1)add ecx,4 | | (1)ld y1,[esi+ecx] |
03 (2)mov edx,0 | (1)jnz @decrease_free_row | (2)mov edx,[esi+ecx*4] | (2)ld x2,[esi+ecx]
04 (2)add ecx,4 | | (2)ld y2,[esi+ecx] |
05 (1)xor edx,eax | (2)jnz @decrease_free_row | (3)mov edx,[esi+ecx*4] | (3)ld x3,[esi+ecx]
06 (1)or edx,x1 | (3)mov edx,0 <<< +1 | (3)ld y3,[esi+ecx] | (3)add ecx,4
07 (1)cmovns edx,eax | (2)xor edx,eax | (4)mov edx,[esi+ecx*4] | (4)ld x4,[esi+ecx]
08 (1)sub y1,edx | (2)or edx,x2 | (4)ld y4,[esi+ecx] | (4)add ecx,4
09 (2)cmovns edx,eax | (3)xor edx,eax | (1)st [esi+ecx],y1 |
10 (2)sub y2,edx | (3)or edx,x3 | |
11 (3)cmovns edx,eax | (3)jnz @decrease_free_row | (2)st [esi+ecx],y2 |
12 (3)sub y3,edx | (4)jnz @decrease_free_row | (4)xor edx,eax |
13 (4)or edx,x4 | | (3)st [esi+ecx],y3 |
14 (4)cmovns edx,eax | | |
15 (4)sub y4,edx | | |
16 | | (4)st [esi+ecx],y4 |
K10-en a 17. órajelben indul az utolsó utasítás, Bulldozeren a 20. órajelben, AGLU esetén pedig a 16. órajelben.
A cikluslefutásoknak függetlenek egymástól, csakis az ADD ECX,00000004h utasítás lefutásán múlik, hogy mikor indulhatnak el a következő ciklusmag utasításai. Az ütemező erről mit sem tud, szabálya, hogy ha több utasításnak áll készen az összes bemeneti paramétere, akkor kötelező neki a programsorrendben korábbiakat indítani.
Viszont mivel a Bulldozerben csak két végrehajtó képes az ADD műveletet fogadni, ezért a 3. cikluslefutás ADD ECX,4 művelete 5 órajellel később indul, mint mire ismert a bemenő paramétere, annyi végrehajtható utasítás gyűlik össze a két ALU számára; emiatt viszont a 13-15. órajelben egy buborék keletkezik az ALU-kban, nincs mit csinálniuk, meg kell várniuk az L1-ból az adatokat.
Ha az AGU-k képesek lennének végrehajtani csak az összeadást, akkor 20 helyett 17 órajel alatt elindulhatna az összes utasítás; ha a logikai (XOR) műveletet is végre tudják hajtani, akkor 16 órajelre csökken ez az érték: ez egyenlő vagy gyorsabb, mint a K10 3 ALU + 3 AGU + 3 clock L1 load-to-use latency sebessége, 2 ALU + 2 AGLU + 4 clock L1 load-to-use latency felépítés mellett is.
[ Szerkesztve ]