Optymalizacja skalarna - czerwiec 2000 1 Optymalizacja skalarna Piotr Bała bala@mat.uni.torun.pl Wykład wygłoszony w ICM w czercu 2000
Optymalizacja skalarna - czerwiec 2000 2 Optymalizacja skalarna Czas obliczeń N instr zależy od algorytmu, kompilatora N cycles instr zależy od procesora, zrównoleglenia kodu obsługi błędów obsługi zaokrągleń T = N instr Ncycles instr Nsec cycle Procesory superskalarne wykonują do 6 instrukcji/cykl zegara
Optymalizacja skalarna - czerwiec 2000 3 Prawo Moore a Obserwujemy wykładniczy wzrost szybkości komputerów. More a) (Prawo CPU 58% / rok MEM 7% / rok Problemem zaczyna być szybkość dostępu do pamięci. Należy korzystać z pamięci podręcznej cache.
Optymalizacja skalarna - czerwiec 2000 4 Architektura procesora Zaczerpnięto z: Arkadiusz Wójtowicz Prace studentów Politecniki Wrocławskiej http://mm-edu.ict.pwr.wroc.pl/dydaktyka/sm/mips.htm
Optymalizacja skalarna - czerwiec 2000 5 Skalowalność problemu Szybkość wykonania spada gdy dane przestają mieścić się w pamięci podręcznej.
Optymalizacja skalarna - czerwiec 2000 6 Optymalizacja 1. Profile 2. Tune 3. Paralelize Możliwości kompilatora/procesora microparallelism cache software pipelininng Optymalizacja kodu na poziomie kompilatora jest najczęściej bardzo efektywna. Należy jednak kod źródłowy przygotować tak by kompilator w pełni wykorzystał możliwości procesora.
Optymalizacja skalarna - czerwiec 2000 7 Szybkość operacji (SUN UltraSpark) Operacja Szybkość Czas martwy Troughput Latency Dodawanie (SP) 1 3 Dodawanie (DP) 1 3 Mnożenie (SP) 1 3 Mnożenie (DP) 1 3 Dzielenie (SP) 12 12 Dzielenie (DP) 22 22 Pierwiastkowanie (SP) 12 12 Pierwiastkowanie (DP) 22 22 SP - pojedyncza precyzja DP - podwójna precyzja
Optymalizacja skalarna - czerwiec 2000 8 Zamiana dzielenia na mnożenie przez odwrotność. DO 10 I=1,N A(I) = A(I)/ANOR Lepiej: ANOR1 = 1./ANOR DO 10 I=1,N A(I) = A(I)*ANOR1
Optymalizacja skalarna - czerwiec 2000 9 Operacja redukcji DO 10 I=1,NMAX ATEMP = ATEMP - B(I)*X1 - D(I)*X2 Zastępujemy przez dwie instrukcje: DO 10 I=1,NMAX ATEMP = ATEMP - B(I)*X1 BTEMP = BTEMP - D(I)*X2 ATEMP = ATEMP + BTEMP lub stosujemy nawiasy: DO 10 I=1,NMAX ATEMP = ATEMP - ( B(I)*X1 - D(I)*X2 ) Optymalizujemy dostęp do cache a.
Optymalizacja skalarna - czerwiec 2000 10 Dostęp do pamięci Tradycyjnie: DO 10 I=2,IDIM-1 DO 10 J=2,IDIM-1 A(I,J) = A(I-1,J+1) + DX Lepiej - wewnętrzna pętla po I DO 10 J=2,IDIM-1 DO 10 I=2,IDIM-1 A(I,J) = A(I-1,J+1) + DX Pozwala na przyspieszenie około 5x W przypadku C macierze uporządkowane są odwrotnie w pamięci (ostatni indeks zmienia się najszybciej).
Optymalizacja skalarna - czerwiec 2000 11 Grupowanie wyrażeń Pomóż kompilatorowi znaleźć identyczne wyrażenia. Lepiej: DO 10 I=1,MXLOOP A(I) = (A(I)-B(I))*X - D(I)*F(I)*X*X + 1 D(I)*F(I)*X*X + A(I)-B(I) DO 10 I=1,MXLOOP A(I) = (A(I)-B(I))*X - D(I)*F(I)*X*X + 1 D(I)*F(I)*X*X + (A(I)-B(I))
Optymalizacja skalarna - czerwiec 2000 12 Loop reversal DO 10 I=1,M DO 20 J=1,N DO 30 K=1,P C(I,J) = C(I,J) + A(I,K) * B(K,J) 30 CONTINUE 20 CONTINUE skok C = 0 skok B = 1 skok A = M DO 10 J=1,N DO 20 K=1,P T = B(K,J) DO 30 I=1,M C(I,J) = C(I,J) + A(I,K) * T 30 CONTINUE 20 CONTINUE skok C = 1 skok B = 0 skok A = 1
Optymalizacja skalarna - czerwiec 2000 13 Loop unrolling DO 10 J=1,N DO 20 K=1,P DO 30 I=1,M C(I,J) = C(I,J) + A(I,K) * B(K,J) 30 CONTINUE 20 CONTINUE loop overhead = 4 ops (44%) loop body = 5 ops
Optymalizacja skalarna - czerwiec 2000 14 Loop unrolling DO 10 J=1,N DO 20 K=1,P T = B(K,J) DO 30 I=1,(M-4)+1,4 C(I+0,J) = C(I+0,J) + A(I+0,K) * T C(I+1,J) = C(I+1,J) + A(I+1,K) * T C(I+2,J) = C(I+2,J) + A(I+2,K) * T C(I+3,J) = C(I+3,J) + A(I+3,K) * T 30 CONTINUE DO 35 I=I,M C(I,J) = C(I,J) + A(I,K) * T 35 CONTINUE 20 CONTINUE loop overhead = 4 ops (16%) loop body = 20 ops
Optymalizacja skalarna - czerwiec 2000 15 Array padding PARAMETER (IDIM=256,JDIM=257) DIMENSION A(IDIM,IDIM)... DO 10 I=1,IDIM DO 20 J=1,IDIM DO 30 K=1,IDIM A(I,J) = A(I,J) + A(I,K) * A(K,J) 30 CONTINUE 20 CONTINUE PARAMETER (IDIM=256,JDIM=257) DIMENSION A(IDIM,JDIM)... DO 10 I=1,IDIM DO 20 J=1,IDIM DO 30 K=1,IDIM A(I,J) = A(I,J) + A(I,K) * A(K,J) 30 CONTINUE 20 CONTINUE Pozwala na asynchroniczny dostęp do pamięci i lepsze wykorzystanie cache a.
Optymalizacja skalarna - czerwiec 2000 16 Blokowe mnożenie macierzy Mnożenie macierzy (IDIM,IDIM) wykonujemy blokami JBLK x IBLK a nie dla całej macierzy od razu: DO 20 I=1,IDIM DO 30 J=1,IDIM DO 40 K=1,IDIM A(I,J) = A(I,J) + B(I,K)*C(K,J) 40 CONTINUE 30 CONTINUE 20 CONTINUE Lepiej: DO 20 II=1,IDIM,IBLK DO 30 JJ=1,IDIM,JBLK DO 40 KK=1,IDIM,KBLK DO 50 J=JJ,JJ+JBLK-1 DO 60 I=II,II+IBLK-1 DO 70 K=KK,KK+KBLK-1 A(I,J) = A(I,J) + B(I,K)*C(K,J) 70 CONTINUE 60 CONTINUE 50 CONTINUE 40 CONTINUE 30 CONTINUE 20 CONTINUE