Az előadás letöltése folymat van. Kérjük, várjon

Az előadás letöltése folymat van. Kérjük, várjon

Alkalmazások és operációs rendszerek optimizálása „Babeş-Bolyai” Tudományegyetem, Matematika-Informatika Kar Forráskód szintű optimizálások C-ben Assembly.

Hasonló előadás


Az előadások a következő témára: "Alkalmazások és operációs rendszerek optimizálása „Babeş-Bolyai” Tudományegyetem, Matematika-Informatika Kar Forráskód szintű optimizálások C-ben Assembly."— Előadás másolata:

1 Alkalmazások és operációs rendszerek optimizálása „Babeş-Bolyai” Tudományegyetem, Matematika-Informatika Kar Forráskód szintű optimizálások C-ben Assembly szintű optimizálások előadás dr. Robu Judit szeminárium drd. Lukács Sándor 11,12 2006

2 BBTE, Alkalmazások és operációs rendszerek optimizálása 2 Optimizálási alapszabályok 1 mielőtt optimizálnánk egy programot, előbb készítsünk el egy helyes, nem-optimizált kódot győződjünk meg a program helyességéről ha egy hiba estén egy programot / programrészt helyettesítünk egy nem-optimizált változattal és a hiba eltűnik  a hiba az optimizációban van mindig első lépésként algoritmus szintű optimizációt használjunk sokkal fontosabb mint az implementáció szintű vagy platform specifikus optimizálások pl. lineáris keresés  bináris keresés optimizálás ≠ átírjuk a programot C-ről asszemblyre előbb minden esetben a forráskód szintű optimizálásokat végezzük el

3 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 3 Optimizálási alapszabályok 2 mielőtt átírnánk egy programot asszemblyre, előbb ellenőrizzük a C fordító által generált kódot lehet, hogy nem a fordítás a lassú sebesség oka lehet, hogy a processzor vagy a memória túl lassú próbáljuk meg egy debuggerben végig követni a C fordító által generált ASM kód végrehajtását lehet, hogy allignment, ugrás stb. problémák vannak nem kizárt, hogy valóban elég lassú és nem optimális a fordítás  jó ilyen esetben ASM-ben optimizálni de vannak már előre optimizált függvénykönyvtárak amikor ASM-et implementálunk készítsünk standard, elegáns kódot külön modulok, jó, ha nem inline assemblyvel dolgozunk lehetőleg ne alkalmazzunk „nyakatekert” trükköket

4 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 4 Tipikus téveszmék a kompiler mindent optimizál kiváló sebesség csak asszembly kód segítségével érhető el a programozók, egy jó optimizáló kompilerrel ellentétben nem képesek egy processzor minden egyes tulajdonságát kihasználni az x86-os processzorok nem érik meg a fáradozást, igazán csak PowerPC és más RISC processzorokon lehet optimizálni

5 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 5 Processzor mikroarchitektúra dekódoló egységek végrehajtó egységek visszaíró egységek

6 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 6 Utasítás végrehajtás az utasításokat egyenként olvassa ki a dekódoló egység több dekódoló egység dolgozhat párhuzamosan a dekódolása után a processzor betölti az esetleges szükséges adatokat a processzor lefoglalja a szükséges erőforrásokat megtörénik az effektív végrehajtás (ALU stb. egységeken) szükség esetén az eredmény kiíródik vissza a memóriába

7 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 7 Pipeline véhrehajtás egy utasítás végrehajtása több lépésben történik a pipeline végreahjtás alapötlete: ameddig egy egység (pl. dekódoló) egy utasítás esetén az egységnek megfelelő műveletet végezi el, a processzor további egységei más műveleteket végezhetnek inst 1inst 2inst 3inst 4 inst 1 inst 2 inst 3 inst 4 inst 5 végrehajtási idő

8 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 8 Végrehajtási sebesség throughput (átmenet) ≠ latency (késleltetés) pl. egy gyár óránként 1000 chipet készít, mennyi időbe tellik egyetlen chip készítése? NEM 3.6 másodperc!!! nem lehet egy korszerű pipeline-os processzor esetén igazából egyetlen utasításhoz szükséges óraciklusok számáról beszélni pl. 1 szorzás ~ 10 ciklus, 10 szorzás ~ 24 óraciklus

9 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 9 Branch prediction (Pentium Pro)

10 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 10 Cache memória architektúrák 1 a jelenlegi számítógépek esetén a processzor és a memória sebessége nagymértékben különbözik tipikusak az 1:10, 1:20 vagy még ennél is roszabb arányok amikor a processzor vár egy következő utasítás betöltésére, ha a memória túl lassú, értékes óraciklusok vesznek el (annélkül, hogy a processzor effektíve dolgozna) a probléma kiküszöbölésére cache memóriákat alkalmaznak a fizikai memóriánál sokkal kissebb méretű, nagyon gyors memóriák (tipikusan 1:1, 1:2, legfennebb 1:4) egy klasszikus processzorban több szintű cache memória van L0 cache memória (tipikusan 4 – 32 KB), a leggyorsabb L1 cache memória (tipikusan 128 – 512 KB) L2 cache memória (tipikusan 512 – 8192 KB) a korszerű processzorok több további cache-t is alkalmaznak mint például TLB cache a lapozás számára

11 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 11 processzor Cache memória architektúrák 2 cache hit – a processzor által kért adatok a cache-ben találhatók nagyon kevés óraciklus alatt elérhetők az adatok cache miss – a processzor által kért adatok NEM találhatók a cache-ben lényegesn több óraciklus alatt érhetők el az adatok RAM cache kontroller végrehajtó egységek cache memória

12 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 12 Cache memória architektúrák 3 adatok betöltése RAM-ból cache-be load-on-demand – amikor először kérjük az adatot speculative load – megpróbáljuk előre „kitalálni” milyen adatokra lesz szüksége a processzornak az eddigi végrehajtási mintát elemezve a következő utasításokat elemezve késleltetett adatkiírás (delay write) több írási művelet eredményét a cache-ben tároljuk egyetlen írási műveletként utolagosan kiírjuk a RAM-ba a cache memória blokkokra van felosztva egy blokk (cache line) a cache alapegysége mivel a fizikai memória méretek sokkal nagyobb mint a cache, egyetlen cache vonalnak több fizikai memória blokk felel meg tárolni kell egy cache blokkban lévő adattal együtt az adatok címét is

13 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 13 Cache memória architektúrák 4 mivel a cache memória tárolja a fizikai és/vagy lineáris címeket, felépítéséből adódóan asszociatív memória a cache memória címzése érték alapú (és nem index alapú, mint például a fizikai memória estén) pl. a 456-os cache vonalat használja a processzor (ahol 456 a cache tag/címke értéke) és nem a 16-dik cache vonalat tipikus probléma: a processzor az XYZ című adatot szeretné elérni a cache ki kell keresse, hogy található-e a cache memóriában az XYZ címnek megfelelő adat a keresés a cache címkéken történik – ez lehet nagyon időigényes szekvenciális keresés, párhuzamos keresés több klasszikus cache architektúra direct mapped N-way associative (tipikusan 2, 4 vagy 8)

14 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 14 Cache memória architektúrák 5 1 2 3 4 1 2 3 4 5 6 7 8 9 10 11 12 fizikai memória cache memória direct mapped 1 2 3 4 1 2 3 4 5 6 7 8 9 10 11 12 fizikai memória cache memória 2-way associative 1 2 3 4

15 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 15 Cache memória architektúrák 6 cache koherencia – főképp multi-processzoros rendszerekben write-through a cache read-only, minden írás a fizikai memóriába történik write-combining az írások egy átmeneti bufferben tárolódnak csoportosan vannak kiírva a fizikai memóriába write-back miden cache vonalhoz státusz attributúm van rendelve írás esetén DIRTY lesz minden DIRTY vonal flush-al kiíródik ha más eszköz kéri a cache vonalnak megfelelő fizikai memóriában lévő adatot MESI / MOESI protocol SMP rendszerek számára Modified, Owned, Exclusive, Shared, Invalid

16 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 16 Optimizálási szintek 1 algoritmus szintű optimizálások a legfontosabb, tipikusan komplexitás szintjén gyorsítja a programot forráskód szintű optimizálások adatok elrendezése, modulok felépítése operációs rendszer szintű optimizálások pl. 4 MB-os lapok alkalmazása memória kiosztás library szintű optimizálások standard C library speciális optimizált könyvtárak használata (pl. matematika, 3D, DSP etc.) pipeline szintű optimizálás minél jobban ki legyenek használva a pipelineok – több utasítás egyszerre végrehajtó egység szintű optimizálás minél nagyobb mértékben legyenek kihasználva a végrehajtó egységek

17 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 17 Optimizálási szintek 2 branch optimizálások minél kevesebb ugró utasítás prefetch kódók cache optimizálás adatok elrendezése architektúra specifikus optimizálások – pl. spinlock-ok cache vonalakon SMP rendszerben processzor specifikus optimizálások pl. PAUSE utasítás használata spinlockban Intel Pentium 4-en SIMD optimizálások (vektorizálás) MMX, SSE lehet forráskód szintjén is végezni, Intel intrinsic makrókkal multi-threading szintű optimizálás megfelelő szinkronizációk OpenMP – akár több processzes felbontás, masszívan párhuzamos gépek esetén vagy tudományos kutatási projektekben használt a leginkább

18 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 18 C forráskód szintű optimizálások 1 a single konstansokat f suffixel deklaráljuk a C/C++ alapértelmezés szerint double-nek tekinti a lebegőpontos értékeket a C szintjén keverni lehet a tömb és pointer elemeket, ahol lehet, használjunk tömböket a C/C++ fordítók jobban tudnak optimizálni a kis iteráció számú ciklusokat rendszerint bontsuk ki (loop unrolling) a logikai kifejezések esetén az && és || kiértékelései esetén sokszor elég egy részkifejezést kiértékelni ha különböző valószínűséggel fordulnak elő a részkifejezések igazság értékei, rendezzük sorba őket if utasítások esetén próbáljuk meg elkerűlni a túl sűrű feltételes részkifejezéseket (túl sűrű ugró utasításokat generálnak) pl. annak függvényében, hogy a és b rendszerint min és max között van-e? if (a = min && b = min) if (a > max || a max || b < min)

19 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 19 C forráskód szintű optimizálások 2 a malloc függvény által visszatérített memória mutatókat szükség esetén ígazítsuk nagyságrend szerint double *p; double *np; p = (double *)malloc(sizeof(double) * number_of_doubles + 7L); np = (double *)((((long)(p)) + 7L) & (-8L)); mindig használjunk függvény prototípusokat jobban optimizál a C/C++ kompiler használjuk gyakran (ahol lehet) a const kulcsszót minden kivűlről nem használt függvényt deklaráljunk static-nak a C/C++ változókat és a struktúrák mezőit rendezzük a méretűknek megfelelően csökkenő sorrendbe ahol lehet, helyettesítsük az egész osztásokat szorzással m = i / j / k; →m = i / (j * k);

20 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 20 C forráskód szintű optimizálások 3 a malloc függvény által visszatérített memória mutatókat szükség esetén ígazítsuk nagyságrend szerint a ciklusokból emeljük ki a ciklustól nem függő részeket for (i...) { if (CONSTANT0) { DoWork0(i); // Does not affect CONSTANT0. } else { DoWork1(i); // Does not affect CONSTANT0. } if (CONSTANT0) { for (i...) { DoWork0(i); } } else { for (i...) { DoWork1(i); }

21 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 21 C forráskód szintű optimizálások 4 a ciklusokat átírhatjuk explicit párhuzamosságot felhasználva double a[100], sum1, sum2, sum3, sum4, sum; int i; sum1 = 0.0; sum2 = 0.0; sum3 = 0.0; sum4 = 0.0; for (i = 0; i < 100; i + 4) { sum1 += a[i]; sum2 += a[i+1]; sum3 += a[i+2]; sum4 += a[i+3]; } sum = (sum4 + sum3) + (sum1 + sum2);

22 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 22 Asszembly szintű optimizálások 1 a lebegőpontos osztás és négyzetgyök sokszor elégséges single pontossággal /* Prototype for _controlfp function */ #include unsigned int orig_cw; /* Get current FPU control word and save it. */ orig_cw = _controlfp(0, 0); /* Set precision control in FPU control word to single precision. This reduces the latency of divide and square-root operations. */ _controlfp(_PC_24, MCW_PC); /* Restore original FPU control word. */ _controlfp(orig_cw, 0xfffff); 64 bites egész műveletekhez használjunk 64 bites regisztereket kiterjesztett pontosságú egész műveletekhez használjunk 64 bites regisztereket pl. 1024 bites szorzás 32 bites regiszterekkel 256 szorzást, 509 átviteles összeadást és 255 összeadást igényel 64 bites regiszterekkel 64 + 125 + 63

23 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 23 Asszembly szintű optimizálások 2 ha lehet használjunk 128 bites SSE utasításokat MMX és x87 helyett 32 bites egész műveletek számára használjunk 32 bites regisztereket (és ne 64 bitest) amikor lehet használjunk load-execute utasításokat movss xmm0, [float_var1] movss xmm12, [float_var2] mulss xmm0, xmm12 load-execute formában movss xmm0, [float_var1] mulss xmm0, [float_var2] az utasításokat kódoljuk a lehető legrövidebb formában 81 C0 78 56 34 12 add eax, 12345678h ; 2-byte opcode form (with ModRM) 81 C3 FB FF FF FF add ebx, -5 ; 32-bit immediate value 0F 84 05 00 00 00 jz label1 ; 2-byte opcode, 32-bit immediate minimális ábrázolással 05 78 56 34 12 add eax, 12345678h ; 1-byte opcode form 83 C3 FB add ebx, -5 ; 8-bit sign-extended immediate 74 05 jz label1 ; 1-byte opcode, 8-bit immediate

24 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 24 Asszembly szintű optimizálások 3 ha lehet, kerüljünk a részregiszterek használatát mov al, bl mov al, [ebx] movss xmm1, xmm2 optimálisabb használat movzx eax, bl movzx eax, byte ptr [ebx] movaps xmm1, xmm2 mindig igazítsuk az adatokat a nagyságrendüknek megfelelő határra SMP rendszerekben a több processzor között osztott (shared), cache vonalakban lévő adatok lényeges teljesítmény romláshoz vezethetnek időnként elkerülhetetlen, pl. szemaforok esetén megfelelő adatminták esetén használjunk PREFETCH utasításokat azonos cache vonalra ne helyezzünk el adatot és kódot egyaránt az ugró utasításokat ha lehet helyezzük úgy el, hogy ne lépjenek át egy 16 bájtos paragrafus határt egy paragrafusba ne helyezzünk el háromnál több ugró utasítást

25 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 25 Asszembly szintű optimizálások 4 ha lehet építsünk fel ugró utasítás mentes végrehajtást, főképp ott, ahol véletlenszerű (egyenletesen elosztott) az ugrás valószínűsége használjunk pl. CMOVxx utasítást a CALL és RET utasításokat használjunk mindig párossával kerüljük a LOOP és a távoli ugró/hívó utasítások használatát használjuk gyakran a MOVSX és MOVZX utasításokat a memóriából helyezzük közvetlenül a veremre a szükséges adatokat (és ne egy regiszteren keresztül) vigyázzunk arra, hogy minden SIMD adat helyesen legyen a méretének megfelelően igazítva a memóriában ha lehet kerüljük az MMX és áltlános regiszterek közötti közvetlen adatmozgató utasításokat (MOVD)

26 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 26 Asszembly szintű optimizálások 5 adatmásoló (pl. memcpy) eljárásokat implementáljunk MMX / SSE utasításokat felhasználva használjuk a PXOR / XORPS utasítást a SIMD értékek előjelének változtatására signmask DQ 8000000080000000h,8000000080000000h xorps xmm0, [signmask] a SIMD értékek abszolut értékének meghatározására használjunk PAND / ANDPS utasításokat absmask DQ 7FFFFFFF7FFFFFFFh,7FFFFFFF7FFFFFFFh andps xmm0, [absmask] a lebegőpontos és egész aritmetikát egyaránt próbáljuk meg átírni MMX / SSE-re

27 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 27 Optimizációs példa – Hangerősség 1 a hangadatok (minták) 16 bites, előjeles egészek sztereo hang esetén egymás után váltakozva helyezkednek el a két csatorna 16 bites mintái (együtt 32 bit egy BAL,JOBB páros) BAL k,JOBB k,BAL k+1,JOBB k+1,BAL k+2,JOBB k+2,... minta (sample) értékek 0 – hangtalan -32768, +32767 – maximális hangerő hangosítás = a minták szorzása konstanssal x 2 – kétszeres hangerő x 0.5 – fél hangerő a végső érzékelt hangerő nem úgyanúgy módosul; az embeli fül számára logaritmikus skálán kell módosítani a hangerőt (DB)

28 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 28 Hangerősség – Delphi // get volume factor 0 – 1024 fact := tckAmplify.Position; for i := start to stop do begin // amplify left channel temp := Wave.Buffer[2*i]; temp := (temp*fact) div 512; if (temp < -32768) then Wave.Buffer[2*i] := -32768 else if (temp > +32767) then Wave.Buffer[2*i] := +32767 else Wave.Buffer[2*i] := temp;... // amplify right channel temp := Wave.Buffer[2*i+1]; temp := (temp*fact) div 512; if (temp < -32768) then Wave.Buffer[2*i+1] := -32768 else if (temp > +32767) then Wave.Buffer[2*i+1] := +32767 else Wave.Buffer[2*i+1] := temp; end; x0 – x2 hangerő skála → 0 – 1024 0 – x0 hangerő 512 – x1 hangerő 1024 – x2 hangerő

29 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 29 Hangerősség – ASM 1 asm push edi push esi mov ecx, factor mov edi, paddr mov esi, start @again: movsx eax, WORD PTR [edi+esi*4] mul ecx sar eax, 9 cmp eax, -32768 jg @nb1 mov eax, -32768 jmp @done1 @nb1: cmp eax, +32767 jl @done1 mov eax, +32767 @done1: mov [edi+esi*4], ax... movsx eax, WORD PTR [edi+esi*4+2] mul ecx sar eax, 9 cmp eax, -32768 jg @nb2 mov eax, -32768 jmp @done2 @nb2: cmp eax, +32767 jl @done2 mov eax, +32767 @done2: mov [edi+esi*4+2], ax add esi, 1 cmp esi, stop jb @again pop esi pop edi end;

30 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 30 Hangerősség – ASM 2a asm push edi push esi push ebx mov ecx, factor mov edi, paddr mov esi, start mov ebx, -32768 @again: movsx eax, WORD PTR [edi+esi*4] mul ecx sar eax, 9 mov edx, +32767 cmp eax, ebx cmovl eax, ebx cmp eax, edx cmovg eax, edx mov [edi+esi*4], ax... movsx eax, WORD PTR [edi+esi*4+2] mul ecx sar eax, 9 mov edx, +32767 cmp eax, ebx cmovl eax, ebx cmp eax, edx cmovg eax, edx mov [edi+esi*4+2], ax movsx eax, WORD PTR [edi+esi*4+4] mul ecx sar eax, 9 mov edx, +32767 cmp eax, ebx cmovl eax, ebx cmp eax, edx cmovg eax, edx mov [edi+esi*4+4], ax...

31 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 31 Hangerősség – ASM 2a... movsx eax, WORD PTR [edi+esi*4+6] mul ecx sar eax, 9 mov edx, +32767 cmp eax, ebx cmovl eax, ebx cmp eax, edx cmovg eax, edx mov [edi+esi*4+6], ax add esi, 2 cmp esi, stop jb @again pop ebx pop esi pop edi end;

32 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 32 Hangerősség – SSE 1a 0000 XMM0 movd xmm1,factor pshufd xmm1,xmm1,$00 00.00.00.00 factor XMM1 pxor xmm0,xmm0 movdqu xmm2,[edx+eax*4] movdqu xmm3,xmm2 XMM2 A5A5 A4A4 A3A3 A2A2 A1A1 A0A0 A7A7 A6A6 XMM3 A5A5 A4A4 A3A3 A2A2 A1A1 A0A0 A7A7 A6A6

33 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 33 Hangerősség – SSE 1b punpcklwd xmm2,xmm0 punpckhwd xmm3,xmm0 XMM3 0A6A6 0A5A5 0A4A4 0A7A7 XMM2 0A2A2 0A1A1 0A0A0 0A3A3 pmaddwd xmm2,xmm1 pmaddwd xmm3,xmm1 A 7 *factorA 6 *factorA 5 *factorA 4 *factor XMM3 A 3 *factorA 2 *factorA 1 *factorA 0 *factor XMM2

34 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 34 Hangerősség – SSE 1c psrad xmm2,9 psrad xmm3,9 packssdw xmm2,xmm3 A 7 *factor >> 9A 6 *factor >> 9A 5 *factor >> 9A 4 *factor >> 9 XMM3 A 3 *factor >> 9A 2 *factor >> 9A 1 *factor >> 9A 0 *factor >> 9 XMM2 f*A 5 /512f*A 4 /512f*A 3 /512f*A 2 /512f*A 1 /512f*A 0 /512f*A 7 /512f*A 6 /512

35 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 35 Hangerősség – SSE 2 asm // setup indexing mov edx, paddr mov eax, start // eax = i // setup zero XMM register pxor xmm0, xmm0 // setup factor XMM register movd xmm1, factor pshufd xmm1, xmm1, $00 // load source wave samples @again: // process 2x16 bit samples(L/R) movdqu xmm2, [edx + eax*4] movdqu xmm3, xmm2 // unpack samples to 32 bit punpcklwd xmm2, xmm0 punpckhwd xmm3, xmm0... // multiply samples by 0 – 1024 // (and add with zero) pmaddwd xmm2, xmm1 pmaddwd xmm3, xmm1 // divide samples by 512 psrad xmm2, 9 psrad xmm3, 9 // pack samples to 16 bit with // signed saturation packssdw xmm2, xmm3 // store destination samples movdqu [edx + eax*4], xmm2 // loop to next samples // 4 x (2x16) bit each step add eax, 4 cmp eax, stop jb @again end;

36 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 36 Hangerősség – SSE 3a asm // setup indexing, ensure 16 byte allign mov edx, paddr mov eax, start // eax = i and edx, $fffffff0 and eax, $fffffffc // setup zero XMM register pxor xmm0, xmm0 // setup factor XMM register movd xmm1, factor pshufd xmm1, xmm1, $00 // load source wave samples, also // prefetch data for the next cycle @again: movdqa xmm2, [edx + eax*4] // we process 2 samples (L-R) // and each is 2 bytes movdqa xmm3, xmm2 movdqa xmm4, [edx + eax*4 + 16] movdqa xmm5, xmm4 movdqa xmm6, [edx + eax*4 + 32] movdqa xmm7, xmm6... // unpack samples to 32 bit punpcklwd xmm2, xmm0 punpckhwd xmm3, xmm0 punpcklwd xmm4, xmm0 punpckhwd xmm5, xmm0 punpcklwd xmm6, xmm0 punpckhwd xmm7, xmm0 prefetcht0 [edx + eax*4 + 48] // load into L0,L1,L2 cache // at least 32 bytes, multiply samples // by 0 - 1024 (and add with zero) pmaddwd xmm2, xmm1 pmaddwd xmm3, xmm1 pmaddwd xmm4, xmm1 pmaddwd xmm5, xmm1 pmaddwd xmm6, xmm1 pmaddwd xmm7, xmm1 prefetcht0 [edx + eax*4 + 80] // load into L0,L1,L2 cache at least 32 bytes...

37 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 37 Hangerősség – SSE 3b... // divide samples by 512 psrad xmm2, 9 psrad xmm3, 9 psrad xmm4, 9 psrad xmm5, 9 psrad xmm6, 9 psrad xmm7, 9 // pack samples back to 16 bit with signed saturation packssdw xmm2, xmm3 packssdw xmm4, xmm5 packssdw xmm6, xmm7 // store destination wave samples movdqa [edx + eax*4], xmm2 movdqa [edx + eax*4 + 16], xmm4 movdqa [edx + eax*4 + 32], xmm6 // loop to next samples add eax, 12 // process 12 x (2 x 16) bit samples each step // (2*i, 2*i+1), (2*i+2, 2*i+3),..., (2*i+22, 2*i+23) cmp eax, stop jb @again end;

38 2006BBTE, Alkalmazások és operációs rendszerek optimizálása 38 Köszönöm a figyelmet!


Letölteni ppt "Alkalmazások és operációs rendszerek optimizálása „Babeş-Bolyai” Tudományegyetem, Matematika-Informatika Kar Forráskód szintű optimizálások C-ben Assembly."

Hasonló előadás


Google Hirdetések