Diferencia entre revisiones de «Software pipelining (Organización del Computador II)»
Línea 253: | Línea 253: | ||
br.ret.sptk.many b0 | br.ret.sptk.many b0 | ||
.endp sumaVec | .endp sumaVec | ||
Para probar esto pueden usar el código C posteado para el ejercicio anterior y modificar los nombres de las funciones llamadas y descomentar la línea que ya crea un vector con los resultados correctos. Recuerden que este ejercicio hace todo para i=1 en adelante (por que usa V[i-1] y W[i-1]. |
Revisión del 13:40 14 nov 2006
Clase de 2/11/06
Enunciado
v[n]-> 16bits w[n]-> 16bits x[n]-> 16bits
x[i] = (v[i]+w[i])^2
Pseudo Codigo
for (i=0; i < n; i++) x[i]= (v[i]+w[i])(v[i]+w[i])
R32 = v, R33 = w, R34 = x, R35 = n, R36 = i
Codigo
alloc r20 = ar.pfs, 4,3,0,0 add r36 = r0,r0 ciclo: cmp.lt p2,p3=r36,r35 (p3) br.cond fin ld2 r37=[r32],2 // CARGA ld2 r38= [r33],2 // add r37= r37,r38 //SUMA pmpy2.r r37=r37,r37 //PRODUCTO st2 [r34]=r37,2 // GUARDADO br.cond ciclo fin:
Optimizacion con rotacion
v[i] ->2reg w[i] ->2reg Suma ->2reg Producto ->2reg
Empiezo de R32 que son los rotativos
r32 r33 r34 r35 r36 r37 r38 r39 |_vi|___|wi_|___|___|___|___|___|___| r33 r34 r35 r36 r37 r38 r39 r32 |v0_|w1_|w0_|___|___|___|___|v1_| ld2 r32=[--],2 // 1ªetapa ld2 r34= [--],2 // add r36= r33,r35 // 2ª etapa pmpy2.r r38=r37,r37 // 3ª etapa st2 [--]=r39,2 // 4ª etapa
ctop y cexit, pone en 1 pr63 y lo rota (pr16 a pr63 se va poniendo en 1s)(uso para controlar q se ejecuta y q no) wtop y wexit, pone en 0 pr63 y lo rota (pr16 a pr63 va poniendo ceros)
alloc r20= ar.pfs,4,9,0,8 // los de rotacion siempre multiplo de 8 mov ar.ec= 4 mov pr.rot= 0x----- ciclo: cmp.lt p16,p3=--,-- (p16) br.wexit fin (p17)ld2 r32 = [--],2 // 1ªetapa (p17)ld2 r34= [--],2 // (p18)add r36 = r33,r35 // 2ª etapa (p19)pmpy2.r r38 = r37,r37 // 3ª etapa (p20)st2 [--] = r39,2 // 4ª etapa add -- = 1, -- br.cond ciclo fin:
Versión completa del ejercicio en IA64
.global sumaCuadrado .proc sumaCuadrado sumaCuadrado: alloc r46=ar.pfs, 4, 14, 0, 8;; mov r41=in0 mov r42=in1 mov r43=in2 mov r44=in3 mov r45=0 mov pr.rot=0 mov ar.ec=4 LOOP: cmp.lt p16, p0=r45,r44 (p16) br.wexit.sptk.many END (p17) ld4 r32=[r41], 4 (p17) ld4 r34=[r42], 4 (p18) add r35=r33, r35 (p19) pmpy2.r r36=r36,r36 (p20) st4 [r43]=r37, 4 add r45=r0,r45,1 br.cond.sptk.many LOOP END: br.ret.sptk.many b0 .endp sumaCuadrado
Código en C para probarlo:
#include "stdio.h" #define size 9 extern void sumaCuadrado(int*, int*, int*,int); void printArrayInt(int* array,int length) { int i=0; printf("["); while(i<length) { printf("%i, ",array[i]); i++; } printf("]\n"); } int main(){ testSumaVec(); } int testSumaVec(){ int v[size]={8,-10,-5,3,4,6,5,7,8}; int w[size]={5,2,-1,0,9,2,1,0,2}; int x[size+1]={0,0,0,0,0,0,0,0,0,0}; int check[size]; for(int i=0;i<size;i++) { check[i]=(v[i]+w[i])*(v[i]+w[i]); //check[i]=(v[i]*w[i-1])+v[i-1]-w[i]; } printArrayInt(v,size); printArrayInt(w,size); sumaCuadrado(v,w,x,size); printArrayInt(x,size+1); printf("Check:\n"); printArrayInt(check,size); return 0; }
Clase 9/11/2006 - Otro ejemplo de software pipelining
Lo que hay que hacer: X[i] = V[i] * W[i-1] + V[i-1] - W[i]
for(i=j,i<n, i++) X[i] = V[i] * W[i-1] + V[i-j] - W[i]
El cuerpo del ciclo sería (sin rotación de registros):
a) ld2 R35 = V[i], 2 b) ld2 R36 = W[i], 2 c) pmpy2.r R37 = R35, R39 d) add R37 = R37, R38 e) sub R37 = R37 , R36 f) st2 [x] = R37, 2 mov R38 = R35 mov R39 = R36
Para aplicar software pipelining dividimos en etapas. Los criterios son disponibilidad de recursos y dependencias de datos. Elegimos que registros asignamos a cada etapa:
1) a y b 2) c 3) d 4) e 5) f
Notar que los MOV ya no van en la versión con las rotaciones, ya que este tipo de movimientos son justamente los que hacen las rotaciones.
¿Cuántos registros para cada cosa? "Criterio": en cuántas etapas después lo voy a necesitar.
V[i] -> 2 "slots/registros" R32-R33 W[i] -> 4 "slots" R34- R37 pmpy -> 2 R38 - R39 add -> 2 R40 - R41 sub -> 2 R42 - R43
Código con esta "propuesta":
br.wexit (p17) ld2 R32 = V[i], 2 (p17) ld2 R34 = W[i], 2 (p18) pmpy2.r R38 = R33, R36 // R36 porque W[i] se inicializa afuera del ciclo, por lo tanto debemos ver dónde queda luego de las tres primeras etapas (p19) add R40 = R39, ??? (p20) sub R42 = R37 , R36 (p21) st2 [x] = R43, 2
Problema: Nos equivocamos al decir que V[i] necesita 2 registros, haciendo el seguimiento salta que pisamos algo que necesitábamos, el V[i-1]. El error: Pensamos que el V[i] solo se utilizaba en pmpy, pero más adelante, en la suma, se usaba V[i-1], y lo deberíamos haber tenido en cuenta...
Reformulamos asignación de registros:
V[i] -> 4 "slots/registros" R32-R35 W[i] -> 4 "slots" R36- R39 pmpy -> 2 R40 - R41 add -> 2 R42 - R43 sub -> 2 R44 - R45
Código con esta "propuesta":
br.wexit (p17) ld2 R32 = V[i], 2 (p17) ld2 R36 = W[i], 2 (p18) pmpy2.r R40 = R33, R38 (p19) add R42 = R41,R35 (p20) sub R44 = R43 , R39 (p21) st2 [x] = R45, 2
Respecto a los wexit, cuando la condición es verdadera NO SALTAN. El epílogo es normalmente #etapas -1 . Pero como en este caso corta en 1, acá seria #etapas.
Versión terminada de este ejercicioo en IA64
Puede ser que el alloc sea exagerado...
.global sumaVec .global printReg .proc sumaVec sumaVec: alloc loc0=ar.pfs,4,15,1,16 mov r48=in0 mov r49=in1 mov r50=in2 add in3=-1, in3 mov ar.lc=in3 mov pr.rot=0 ld4 r32=[r48],4 ld4 r36=[r49],4 mov ar.ec = 5 BUCLE: br.cexit.sptk.many FIN (p16) ld4 r32=[r48],4 (p16) ld4 r36=[r49],4 (p17) pmpy2.r r40=r33, r38 (p18) add r42=R41, R35 (p19) sub r44=r43, r39 (p20) st4 [r50]=r45, 4 br.cond.sptk.many BUCLE FIN: br.ret.sptk.many b0 .endp sumaVec
Para probar esto pueden usar el código C posteado para el ejercicio anterior y modificar los nombres de las funciones llamadas y descomentar la línea que ya crea un vector con los resultados correctos. Recuerden que este ejercicio hace todo para i=1 en adelante (por que usa V[i-1] y W[i-1].