Documente Academic
Documente Profesional
Documente Cultură
1 2
Arhitecturi
tectu DSP
S “prietenoase”
p ete oase pentru
pe t u Exemplu - StarCore SC140
compilatorul C Arhitectura Variable Length Execution Set (VLES)
număr mare de registre un set de execuţie poate efectua până la:
patru instrucţiuni DALU
set de registre
g ortogonale
g
două
ă instrucţiuni AGU
moduri de adresare flexibile
arhitectură scalabilă cu set bogat de instrucţiuni
puţine restricţii de execuţie a instrucţiunilor set de registre ortogonal (independente)
suport pentru for diversele tipuri de date 16 registre de date DALU (d0 – d15)
16 + 4 + 4 registre AGU (r0-r15, n0-n3, m0-m3)
etape puţine pipeline => nu apar conflicte
suport hardware pentru întregi şi fracţionare
3 4
Exemplu - StarCore SC140 Este C potrivit pentru DSPuri?
[
move.4f (r0)+,d0:d1:d2:d3
( ) ,
Limbajul C nu poate produce un cod în
move.4f (r1)+,d4:d5:d6:d7 asamblare optim, care să utilizeze la maximum
]
LOOPSTART3 resursele procesorului.
[
mac d0,d4,d8 De exemplu în limbajul C nu sunt prezente:
mac d1,d5,d9
mac d2
d2,d6,d10
d6 d10
lucrul în virgulă
g fixă;;
mac d3,d7,d11 nu este prezent suportul pentru arhitecturi duale de
move.4f (r0)+,d0:d1:d2:d3
move.4f (r1)+,d4:d5:d6:d7
( ) , memorie;
]
nu sunt prezente porturi speciale de intrare/ieşire, şi
LOOPEND3
[ nici instrucţiuni specializate;
mac d0,d4,d8
nu este prezent suportul pentru instrucţiuni de tipul
mac d1,d5,d9
mac d2,d6,d10 SIMD (Single Instruction Multiple Data).
mac d3
d3,d7,d11
d7 d11
]
5 6
7 8
Realizarea unui proiect pentru DSP SC140
Trecerea de la virgulă mobilă (float) la
reprezentarea în virgulă fixă
scalarea datelor şi a funcţiilor pentru reprezentarea pe
domeniu de valori subunitare
Adaptarea codului C la formatul specific DSP
SC140
Trecerea de la virgulă mobilă
definirea tipurilor specifice DSP
introducerea operaţiilor de virgulă fixă reprezentate (float) la reprezentarea în
prin funcţii intrinseci g
virgulă fixă
Optimizarea codului C pentru reducerea
timpului de execuţie şi a dimensiunii codului
9 10
Trecerea virgulă mobilă - virgulă fixă Trecerea virgulă mobilă - virgulă fixă
Se consideră codul de referinţă în C cu formatul Scalarea este operaţia prin care variabilele (de
datelor de tip float, double etc. intrare, rezultatele etc.) pentru toate funcţiile
din program sunt aduse la valori subunitare
Definire variabile:
(păstrând formatul float).
float x[]={6.4, -5.5, 14.3, 0.5}, e, a=2.0;
Definire funcţii
var1 var2 var3
float energie(float a,float* x) {float s; F1 F2
f
for (i
(int
t i
i=0;
0 i<N
i<N; i++) M1 M2 M3
s+=pow(x[i],a);
return s;}
Apel funcţii
e=energie(a, x); M1,M2,M3 > 1
11 12
Trecerea virgulă mobilă - virgulă fixă Trecerea virgulă mobilă - virgulă fixă
Scalarea este operaţia prin care variabilele (de Scalarea variabilelor de intrare
intrare, rezultatele etc.) pentru toate funcţiile Apare o modificare a rezultatului final prin propagarea
din program sunt aduse la valori subunitare scalarii iniţiale în rezultatul fiecărei funcţii
(păstrând formatul float). Propagarea poate să nu fie liniară dacă funcţiile
efectuează operaţii neliniare (pow, exp etc.)
13 14
Trecerea virgulă mobilă - virgulă fixă Trecerea virgulă mobilă - virgulă fixă
Compensarea scalării la ieşirea fiecărei funcţii Scalarea funcţiei pentru ieşire subunitară
Se evaluează variaţia ieşirii funcţiei dacă se face Se scalează operaţiile efectuate în funcţie astfel ca
scalare la intrare rezultatul să fie subunitar
Se înmulţeşte ieşirea funcţiei cu inversul acestuia Factorul de scalare S intern al funcţiei este
Astfel rezultatul final nu este influenţat verificare compensat la ieşire pentru a păstra rezultatul final
1 1/S
var1 var1_s var2 var1 var1_s F1_s var2_s var2
_1_ F1 _1_ 1
M1 1 M1 F1
M1 1 F1 M2 M1 1 S 1
M1 M2
M1
15 16
Trecerea virgulă mobilă - virgulă fixă Trecerea virgulă mobilă - virgulă fixă
Exemplu: programul de calcul al energiei Exemplu: programul de calcul al energiei
Prin împărţirea cu 16 a intrării la ieşire se va regăsi
float x[]={6.4, -5.5, 14.3, 0.5}; un factor de atenuare de 1/162.
M1=14.3. Se înmulţeşte rezultatul cu 162, astfel rezultatul final
Se poate alege o scalare cu 16 echivalentă cu rămâne nemodificat.
shiftarea la dreapta cu 4 biţi.
energie energie
x[] e x[] x_s[] e
N 1 _1_ N 1
M1 e x i
2
M2 16 16 1 e x i 2 162
M2
i 0 i 0
17 18
Trecerea virgulă mobilă - virgulă fixă Trecerea virgulă mobilă - virgulă fixă
Exemplu: programul de calcul al energiei Exemplu: programul de calcul al energiei
Se scalează operaţiile efectuate în funcţie astfel ca Dacă rezultatul funcţiei energie este folosit într-o
rezultatul să fie subunitar. funcţie următoare atunci se reia operaţia de scalare a
Suma de N termeni pozitivi subunitari poate avea o i t ă ii ffuncţiei
intrării ţi i F2
F2, compensarea lla iieşire,
i scalarea
l
valoare maximă egală cu N factorul de scalare funcţiei F2 etc.
intern al funcţiei este 1/N.
1/N Compensarea ieşirii primei funcţii şi scalarea intrării
funcţiei următoare se anulează reciproc.
energie s
energie_s
x[] x_s[] e_s[] e e_s[] e e_s[] var3
_1_ 1 N 1
energie_s _1__ F2
N.162 N.162
16 16 1 e_s
N
x i
i 0
i
2
1 M2 1 M2 N.162 1 M3
19 20
Adaptarea codului la formatul SC140
Formate de date pentru DSP
identice cu tipurile de bază C
întregi
de aceeaşi lungime dar cu semnificaţie diferită
fracţionare pe 16 şi 32 biţi
specifice DSP (de ex. incluzând partea de extensie)
Adaptarea codului C la fracţionare pe 40 biţi
21 22
23 24
Adaptarea codului la formatul SC140 Adaptarea codului la formatul SC140
Exemplu: interpretarea datelor pe 16 biţi Funcţiile intrinseci
Reprezentare Reprezentare Reprezentare Sunt funcţii speciale prin care compilatorul realizează
Reprezentare în binar
hexazecimală ca întregi ca fracţionar o mapare în C a instrucţiunilor din asamblare
specifice
ifi operaţiilor
ţiil pe precizie
i i fi
finită.
ită
0100 0000 0000 0000 0x4000 16384 0.5
Această categorie de funcţii presupune definirea unor
0001 0000 0000 0000 0x1000 4096 0 125
0.125 mulţimi de noi tipuri de date
precizie simplă, dublă şi extinsă pentru numere
0000 0000 0000 0000 0x0000 0 0.0
fracţionale.
ţ
1100 0000 0000 0000 0xC000 -16384 -0.5 Utilizarea acestor funcţii intrinseci asigură emularea
programelor şi pe alte platforme.
1111 0000 0000 0000 0xF000 -4096 -0.125
W d16
Word16 add(Word16,
dd(W d16 W Word16);
d16)
Word32 L_add(Word32, Word32);
Word40 X_add(Word40, Word40);
Word64 D_add(Word64, Word64);
27 28
Adaptarea codului la formatul SC140 Adaptarea codului la formatul SC140
Exemplu: calculul energiei Înlocuirea tipurilor datelor şi a funcţiilor
float x[]={6.4, -5.5, 14.3, 0.5}; intrinseci
double e=0; 0.4 x 215 = 13107.2 (int) = 13107 = 0x3333
for (int i=0; i<N; i++) Se poate folosi macroul WORD16() care transformă
e+=x[i]*x[i]; valoarea fracţionară în reprezentarea hexa pe 16 biţi
16 registre de date ]
LOOPEND3
DALU (d0 – d15) [
16 + 4 + 4 registre AGU mac d0,d4,d8
mac d1,d5,d9
r0-r15, n0-n3, m0-m3
mac d2,d6,d10
mac d3
d3,d7,d11
d7 d11
]
33 34
35 36
Ce înseamnă optimizarea? Pragme
reducerea timpului de execuţie Prin p
pragme
g se înţelege
ţ g un mod standard de
reducerea dimensiunii codului comunicare cu un compilator.
reducerea dimensiunii datelor Acestea descriu nu numai caracteristicile
reducerea memoriei alocate stivei codului scris în limbaj C dar şi a datelor
reducerea
d consumului
l idde memorie
i utilizate.
utilizate
Utilizarea pragmelor nu afectează cu nimic
valoarea rezultatelor,
rezultatelor dar influenţează într-o
într o
măsură deosebit de importantă performanţele
#pragma align signal 8
#pragma loop_unroll 4
#pragma inline
#pragma loop_count (20, 40, 4)
37 38
41 42
43 44
Obţinerea de aplicaţii optimizate pe DSP Tehnici de optimizare pentru SC140
arhitectură DSP performantă tehnici generale aplicabile DSP
compilator cu grad mare de optimizare loop merging
loop unrolling
stilul de scriere a codului sursă C
loop splitting
singurul factor dependent de programator
tehnici specifice StarCore
scrierea
i codului
d l i C ttrebuie
b i să
ă respecte
t unele
l
split computation
tehnici de programare precizate în manualul
p
multisample
compilatorului
il t l i pentru
t
eliminarea dependenţelor datelor
completarea operaţiilor făcute de compilator pentru
structurarea codului
45 46
47 48
Loop Unrolling int i;
;
Word16 signal[SIGNAL_SIZE];
Word16 scaled_signal[SIGNAL_SIZE];
Loop Unrolling
L U lli
repetarea conţinutului unei bucle - Exemplu
permite gruparea mai multor instrucţiuni
/* ... */
for(i=0; i<SIGNAL_SIZE; i++)
pentru ca acestea sa se execute în paralel, în {
scaled_signal[i]
g [ ] = shr(signal[i],
( g [ ], 2);
)
cadrul
d l unuii aceluiaşi
l i i ciclu
i l iinstrucţiune.
t ţi }
49 /* ... */ 50
Compiler
p g
generated code Loop Unrolling
; Without loop unrolling : 6 cycles
; With
t loop
oop uunrolling
o g : 2 cyc
cycles
es inside
s de
permite specificarea explicită a folosirii de către
compilator a operaţilor în paralel
; inside the loop ; the loop.
loopstart3 ; The complier uses software pipelining
L5 [
[ move.4f (r0)+,d0:d1:d2:d3 p
factroul de desfacere a buclei depinde de
add
dd #
#<2,d3
2 d3 ;[20,1]
[20 1]
move.ll #
#_scaled_signal,r1
l d i l 1
move.l
move.l
d3,r2;[20,1] ]
<_signal,r1 ;[20,1]
[
alinierea datelor
]
move.l <
<_scaled_signal,r4
asrr
scaled signal,r4 asrr
#<2,d0
#<2
#<2,d1
d1
asrr
asrr
#<2,d3
#<2,d2
#<2 d2 numărul de transferuri cu memoria
adda r2,r1 ]
[ loopstart3 numărul de operaţii aritmetice
move.w (r1),d4 [
]
adda r2,r4 moves.4f d0:d1:d2:d3,(r1)+
,( ) ţ
numărul de iteraţii
asrr #<2,d4 move.4f (r0)+,d0:d1:d2:d3
move.w d4,(r4) ]
[
se face unroll până nu mai rezultă nici o
loopend3
asrr
asrr
#<2,d0
# 2 d2
#<2,d2
asrr
asrr
#<2,d1
#
#<2,d3
2 d3 îmbunătăţire
]
loopend3 în general se face unroll cu un factor 2 sau 4
moves.4f d0:d1:d2:d3,(r1)+
51 52
Loop Unrolling – Exemplu 1 Loop Unrolling – Exemplu 1
#include <prototype.h> _Prod #include <prototype.h> ... mpyr ...
#define VectorSize 40 doensh3 #39 #define VectorSize 40
Word16 Prod(Word16 a[], Word16 b[]) move.f (r0)+,d4 Word16 Prod(Word16 a[], Word16 b[]) LOOPSTART3
{ move.f (r1)+,d5 { [
Word16 c[VectorSize]; mpyr d4,d5,d3 #pragma align *a 8 move.4f (r0)+,d8:d9:d10:d11
i
int i
i; #
#pragma align
li *b 8 move.4f
4f (
(r1)+,d4:d5:d6:d7
1) d4 d5 d6 d7
Word32 sum=0L; LOOPSTART3 Word16 c[VectorSize]; ]
[ #pragma align c 8 [
for(i 0;i<VectorSize;i++)
for(i=0;i<VectorSize;i++) move.f (r0)+,d0 int i; mpyr d8,d4,d0
{ move.f (r1)+,d4 Word32 sum=0L; mpyr d9,d5,d1
c[i]=mult_r(a[i],b[i]); ] mpyr d10,d6,d2
} [ for(i=0;i<VectorSize;i+=4) mpyr d11,d7,d3
for(i=0;i<DataBlockSize;i++) mpyr d0,d4,d3 { moves.4f d0:d1:d2:d3,(r3)+
{ moves.f d3,(r3)+ c[i+0]=mult_r(a[i+0],b[i+0]); ]
sum=mult_r(c[i+0],c[i+0]); ] c[i+1]=mult_r(a[i+1],b[i+1]); LOOPEND3
} LOOPEND3 c[i+2]=mult_r(a[i+2],b[i+2]);
[i+2] lt ( [i+2] b[i+2])
return(round(sum)) c[i+3]=mult_r(a[i+3],b[i+3]); moves.4f d0:d1:d2:d3,(r3)
} moves.f d3,(r3) }
...
53 54
}
59 60
int i; Word32 e;
Split Computation Câte separări?
Word16 signal[SIGNAL_LEN];
depinde de alinierea în memorie
/* ... */
e = 0; numărul de iteraţii trebuie să fie multiplu de
for(i = 0; i < SIGNAL_LEN; i++) {
e = L_mac(e, signal[i], signal[i]); p
numărul de separări a sumei
} int i; Word32 e0, e1, e2, e3;
Word16 signal[SIGNAL_LEN]; sumele calculate separat trebuie recombinate
pentru a obţine rezultatul final
#pragma align signal 8
/* ... */
e0 = e1 = e2 = e3 = 0;
for(i = 0; i < SIGNAL
SIGNAL_LEN;
LEN; i+=4)
i+ 4) {
e0 = L_mac(e0, signal[i+0], signal[i+0]);
e1 = L_mac(e1, signal[i+1], signal[i+1]);
e2 = L_mac(e2, signal[i+2], signal[i+2]);
e3
3 = L_mac(e3,
L ( 3 signal[i+3],
i l[i 3] signal[i+3]);
i l[i 3])
}
e0 = L_add(e0, e1);
e1 = L_add(e2,
( , e3);
);
e0 = L_add(e0, e1);
/* the energy is now in e0 */ 61 62
nu necesită alinierea datelor în memorie Outer loop unrolling for (i = 0; i < T; i++)
acc33 = L_mac(acc3,
L ( 3 x[i],
[i] c[j+3+i]);
[j+3+i])
res[j+3] = acc3;
reduce numărul de operaţii de transfer al }
datelor
63 64
Multisample Example - Step 2 Multisample Example - Step 3
for (j = 0; j < N; j += 4) { for (j = 0; j < N; j += 4) {
3
acc0 = 0; 2 for (j = 0; j < N; j += 4) {
acc0 = 0;
Inner loop merging
for (i = 0; i < T; i++)
acc0 = 0; 3 acc1 = 0;
acc2 = 0;
acc0 = L_mac(acc0, x[i], c[j+0+i]); for (j = 0; j < N; j += 4) {
acc1 = 0; acc3 = 0;
res[j+0] = acc0; acc0 = 0;
acc2 = 0;
acc1 = 0;
acc3 = 0;
f
for (i = 00; i < TT; i++)
acc0 = L_mac(acc0, x[i],
acc1 = 0;
c[j+0+i]);
4
for (i = 0; i < T; i++) acc2 = 0;
for (i = 0; i < T; i++) for (i = 0; i < T; i++)
acc1 = L_mac(acc1, x[i], c[j+1+i]); acc3 = 0;
acc0 = L_mac(acc0, x[i], c[j+0+i]); acc1 = L_mac(acc1,
( , x[i],
[ ], c[j+1+i]);
[j ]) (i = 0; i < T; i++) {
res[j+1] = acc1; for
for (i = 0; i < T; i++) for (i = 0; i < T; i++)
acc2 = 0; acc0 = L_mac(acc0, x[i], c[j+0+i]);
acc1 = L_mac(acc1, x[i], c[j+1+i]); acc2 = L_mac(acc2, x[i], c[j+2+i]);
for (i = 0; i < T; i++) acc1 = L_mac(acc1, x[i], c[j+1+i]);
for (i = 0; i < T; i++) for (i = 0; i < T; i++)
acc2 = L_mac(acc2, x[i], c[j+2+i]); acc2 = L_mac(acc2, x[i], c[j+2+i]);
acc2 = L_mac(acc2,
L mac(acc2, x[i], c[j+2+i]); acc3 = LL_mac(acc3,
mac(acc3 x[i]
x[i], c[j+3+i]);
res[j+2]
[j 2] = acc2;
2 acc3 = L_mac(acc3, x[i], c[j+3+i]);
for (i = 0; i < T; i++) res[j+0] = acc0;
acc3 = 0; }
acc3 = L_mac(acc3, x[i], c[j+3+i]); res[j+1] = acc1;
for (i = 0; i < T; i++) res[j+0] = acc0;
res[j+0] = acc0; j
res[j+2] = acc2;
acc3 = L_mac(acc3,
ac(acc3, x[i],
[ ], c[j
c[j+3+i]);
3 ]); res[j+1] = acc1;
res[j+1] = acc1; res[j+3] = acc3;
res[j+3] = acc3; res[j+2] = acc2;
res[j+2] = acc2; }
} res[j+3] = acc3;
res[j+3] = acc3;
Rearrangement
}
}
65 66
67 68
Multisample Example - Final Result Exemplu – Funcţia de autocorelaţie
for (j = 0; j < N; j += 4) { Word16 Autocorr ( Loop unroll
acc0=acc1=acc2=acc3=0; xx = x[i+0]; Word16 x[], Word16 m,
c0 = c[j+0]; c1 = c[j+1];
Word32 r[], Word16 wind[] )
c2 = c[j+2]; c3 = c[j+3];
for (i = 0; i < T; i += 4) { { for (i = 0; i < L_WINDOW; i += 4)
acc0 = L
L_mac(acc0,
mac(acc0 xx
xx, c0); Word16 i, j, norm; {
acc1 = L_mac(acc1, xx, c1);
acc2 = L_mac(acc2, xx, c2);
one cycle (4 macs + 2 moves) Word16 y[L_WINDOW]; y[i+0] = mult_r(x[i+0], wind[i+0]);
Word32 sum;
acc3 = L_mac(acc3, xx, c3); y[i+1] = mult_r(x[i+1], wind[i+1]);
Word16 overfl,
overfl overfl
overfl_shft;
shft;
xx = x[i+1]; c0 = c[j+4+i]; y[i+2] = mult_r(x[i+2], wind[i+2]);
acc0 = L_mac(acc0, xx, c1);
acc1 = L_mac(acc1, xx, c2); /* Windowing of signal */ y[i+3] = mult_r(x[i+3], wind[i+3]);
acc2 = L
L_mac(acc2,
mac(acc2 xx
xx, c3); one cycle (4 macs + 2 moves) }
acc3 = L_mac(acc3, xx, c0); for (i = 0; i < L_WINDOW; i++)
xx = x[i+2]; c1 = c[j+5+i];
{
/* similar third and fourth loop */
} y[i] = mult
mult_r(x[i],wind[i]);
r(x[i] wind[i]);
res[j+0] = acc0; res[j+1] = acc1; }
res[j+2] = acc2; res[j+3] = acc3;
}
69 70
73 74
Word16 max_search(Word16
max search(Word16 vector[],
vector[] unsigned short int length ) {
better solution for 16-bit ((asm only)
y)
#pragma align *vector 8 based on max2 instruction (SIMD style)
signed short int i = 0; Word16 max0, max1, max2, max3;
fetches two 16-bit values as a 32-bit one
max0 = vector[i+0]; max1 = vector[i+1];
max2 = vector[i+2]; max3 = vector[i+3]; eight maxima per cycle
75 76
Maximum Search – ASM with max2 Maximum position
based on comparisons
move.2l (r0)+n0,d4:d5 move.2l (r1)+n0,d6:d7
around N cycles
move.2l (r0)+n0,d0:d1 move.2l (r1)+n0,d2:d3
FALIGN in C, two maxima required
LOOPSTART3
[ based on maximum search
max2 d0,d4 max2 d1,d5
max2 d2,d6 max2 d3,d7 around N/2 cycles
y
move.2l (r0)+n0,d0:d1 move.2l (r1)+n0,d2:d3
] based on max2-based maximum search
LOOPEND3
[ around N/4 cycles
max2 d0,d4 max2 d1,d5
max2 d2,d6 max2 d3,d7 care must be taken to preserve the original
semantics
]
77 78
79 80
DSP Coding Recommendations DSP Coding Recommendations (2)
use loops with a fixed number of iterations replace tests with computations
enables the detection of hardware loops small tests are ok due to predicative execution
p
provide extensive static information use synonym
y y operations
p if more flexible in the
pragmas, constants target architecture
use only supported data types use modulo addressing
do not mix integer and fractional operations on alignment in data structures should be
the same value provided using field arrangement
use custom calling conventions
81 82
83 84
Diet Speed Optimization C Optimization Limits
compile for speed only time-consuming loops
compile for
fo size
si e the rest
est
effort concentrated on loops
try speed and size optimizations combined no packed moves outside loops
loops and ifs delimit optimization blocks
reduce the unroll factors in the multisample
transformation
avoid register pressure that creates spill code
85 86
Conclusions
complexity of future DSP applications require
development using C
C can be transformed in efficient DSP C
compiler extensions are a must
the coding style is programmer
programmer’s
s key
optimized C code is suitable for high
performance applications
assembly remains for critical sections
87