Nil Satis Nisi Optimum - Logoszféra fórum

üzenetek

hozzászólások

(#1) P.H.


    P.H.
    (senior tag)

    Blog.

    Magamnak.

    Sok dolog elveszett már az elmúlt évek alatt.

    Tehát mondjuk online archiválok. Mondjuk ide. Próba szerencse.

    Adott egy feladat: talán kétrétegű rajzolás lehetne a neve. Adott egy NxM pixel méretű 32 bites kép, amelyre rajzolni kell, de csak bizonyos mintában, amelyet egy 8x4 bites érték ír le: minden sorhoz egy 8 bites minta tartozik, amely ahol 1, az adott pixelen felül kell írni az eredeti képet a layeren lévő rajzzal, hacsak az nem egy előre kijelölt 'háttérszín'; és minden 4 sorhoz tartozik egy ismétlődő minta.

    A megvalósítási ötlet szerint mivel egy kép nem tartalmazhat 32 bites negatív pixel értéket (32 bites megjelenítés megkövetelt, ez alatt nincs értelme a SETDIBITSTODEVICE forrásadatában negatív értéket megadni), így a kisegítő layer (amire első körben a rajzolás történik) háttérszíne tetszőleges negatív szám lehet. A kisegítő layer legyen ugyancsak NxM-es tömb, erre lefutnak a módosítás nélküli rajzolási eljárások a kívánt pixeleket felülírva benne a megfelelő színre, ezután fésüljük össze a két 'képet' az adott minta szerint.

    pushad
    mov ecx,{képszélesség}
    mov ebx,{rajzolási maszk}
    mov esi,{layer címe}
    push {képmagasság}
    shl ecx,02h
    mov edi,{célkép címe}
    mov edx,ecx
    mov ebp,ebx
    @inner:
    sub ecx,04h
    js @outer
    ror bl,01h
    mov eax,[esi+ecx]
    mov dword ptr [esi+ecx],-1
    jnc @inner
    test eax,eax
    jl @inner
    mov [edi+ecx],eax
    jmp @inner
    @outer:
    ror ebp,08h
    add edi,edx
    add esi,edx
    sub dword ptr [esp],01h
    mov ecx,edx
    mov ebx,ebp
    jnz @inner
    @exit:
    add esp,04h
    popad
    ret

    Több ponton is bele lehet kötni a fentiekbe:
    - a Core 2 processzorok LSD-je 4x16 byte-nyi utasítást tud tárolni, benne legfejlebb 4 ugró utasítással, ret nélkül; a fenti @inner ciklus az @outer ciklussal együtt is bőven beleférne a 64 byte-ba, viszont 5 ugró utasítás van benne; ha egyet eliminálni lehetne, akkor a szükséges adatok egyszeri beolvasása után sosem kell a teljes kép feldolgozása során az L1 I-cache-hez fordulni.
    - a K8 CPU-k optimalizálási leírását bogarászva kitűnik, hogy a hardware prefetcher-e a cache-vonalakat csak növekvő sorrendben tudja előbetölteni, a fenti eljárás viszont egy adott képsoron visszafelé halad, mivel az @inner ciklusban az offszet (ecx) csökken.

    pushad
    mov ecx,{képszélesség}
    xor edx,edx
    mov ebx,{rajzolási maszk}
    mov esi,{layer címe}
    push {képmagasság}
    shl ecx,02h
    mov edi,{célkép címe}
    not ebx
    sub edx,ecx
    mov ebp,ebx
    @outer:
    sub edi,edx
    sub esi,edx
    sub dword ptr [esp],01h
    mov ebx,ebp
    lea ecx,[edx-04h]
    ror ebp,08h
    js @exit
    @inner:
    or eax,-1
    add ecx,04h
    jns @outer
    xor eax,[esi+ecx]
    mov dword ptr [esi+ecx],-1
    ror bl,01h
    jbe @inner
    not eax
    mov [edi+ecx],eax
    jmp @inner
    @exit:
    add esp,04h
    popad
    ret

    A következő változások történtek:
    - a korábbi "a layer háttérszíne tetszőleges negatív szám lehet" feltétel szűkült arra, hogy csakis -1 lehet
    - az @outer ciklus is elöltesztelős lett: átlép a következő sor elejére, így az @inner 0 felé egyre közelítő negatív offszettel fér a két tömb pixeleihez.
    - az @inner ciklusban eggyel kevesebb ugrás található, viszont miután az XOR -1,x utáni ROR reg,01h nem változtatja a ZF-et (sem, csak az OF-et és CF-et), így a JBE (jump if below or equal = jump if CF = 1 or ZF = 1) mindkét feltételt egyszerre kezeli; ehhez viszont bit-negálni kell a maszkot a ciklusok előtt.
    Ilyen jellegű megoldás nem létezik magas szintű programozási nyelvekben.

    A következőkben nem történt változás:
    - a 8 használható regiszter közül csak háromnak változik az értéke az @inner ciklusban, ezért képsoronként egyszer a Core 2 belefut az @outer ciklus elején a registerfile-olvasási korlátjába, mivel EDI, ESI, EDX, ESP és EBP is 'befagyott' register-nek tekinthető.
    - ha lenne még egy szabad register, amelyben a -1 konstans tárolható lenne, akkor 1+1+2 byte-tal kisebb lenne a két ciklus kódja, ez x64 alatt megoldható lenne.

    Az elméleti nyereség:
    - bármilyen egyszerű hardware prefetcher-rel ellátott microarchitecture esetén a két tömbön végigmenni minimális L1/L2 cache-tévesztéssel jár (az is nagyrészt csak a 4 KB-os lapok miatt van)
    - teljesen üres layer esetén csakis a jns @outer ugrásánál lehet téveszteni (soronként egyszer)
    - teljesen kitöltött layer esetén a ror bl,01h bizonyos, 8 esetenként ismétlődő minta szerint dolgozik, amit a többszintű ugrás-előrejelzőknek illik lekezelni
    - az algoritmus jól kezeli a layer folyamatos huzamosabb háttér- ill. előtér sorozatait, viszont a gyakori váltásokat nem (ott jobban teljesít az első algoritmus).

    A gyakorlati nyereség: K8 és két, különböző (Kb. 80% és 10%) kitöltöttségű ~2 megapixeles kép+layer esetén TSC-rel kimérve 25M/33M-ról 15M/24M órajel.

    [ Szerkesztve ]

    (#2) P.H.


      P.H.
      (senior tag)

      A Write-Combining pufferekből privát cache-be csak a rendszermemórián kereszül kerülhet adat, oda és vissza egyaránt, közvetlen kapcsolat nincs ~ olvasott cache-line felülírása non-termporal módon tilos.

      @SSE2rewriteALPHA:
      add ebp,ebx
      jns @retirePERFORM
      cmp [esi+ebp],eax
      jz @SSE2rewriteALPHA
      movd xmm2,[esi+ebp]
      movd xmm3,[edi+ebp]
      punpcklbw xmm2,xmm7
      punpcklbw xmm3,xmm7
      punpcklwd xmm2,xmm7
      punpcklwd xmm3,xmm7
      cvtdq2ps xmm2,xmm2
      mov [esi+ebp],eax <<<----
      cvtdq2ps xmm3,xmm3
      mulps xmm2,xmm0
      mulps xmm3,xmm1
      addps xmm2,xmm3
      cvtps2dq xmm2,xmm2
      packssdw xmm2,xmm2
      packuswb xmm2,xmm2
      movd [edi+ebp],xmm2
      jmp @SSE2rewriteALPHA

      K8 lefutás ~2 megapixeles képen 5% layer-kitöltöttség mellett 9M órajel, mov [esi+ebp],eax utasítás helyett movnti [esi+ebp],eax írva 11M órajel.

      Vajon
      - ez igaz a hardware prefetch-elt cache-vonalakra is?
      - az L3-mak jelenléte változtat a dolgon K10 és főleg Nehalem (inclusive) esetén?
      - ez csak az DL1-re igaz, vagy a VIA-féle prefetch cache tartalmára is?

      (#3) P.H.


        P.H.
        (senior tag)

        A 32 bites non-temporal store-ok K8-as megvalósítása hagy némi kívánnivalót, a sima x86 tárolássorozat gyorsabb (VectorPath REP STOSD kizárt).

        @unpackSSE2:
        movnti [edi],eax
        add edi,04h
        add ebp,ecx
        jnz @unpackSSE2
        @unpckSSE2:
        add ebx,04h
        mov eax,edx
        mov ebp,[esi+ebx]
        jg @fenceUNPACK
        and eax,ebp
        and ebp,ecx
        jmp @unpackSSE2
        @@UNPACKBMP: <<- entry
        lea eax,{tömörített adatra mutató pointer}
        cmp dword ptr [eax],00h
        jz @exitUNPACK
        pushad
        mov edi,{célkép}
        mov esi,[eax]
        mov ecx,0FF000000h
        mov ebx,[esi-04h]
        lea esi,[esi+ebx-04h]
        neg ebx
        cmp {van_SSE2?},cl
        jnz @unpckSSE2
        jmp @unpck
        @unpack:
        mov [edi],eax
        add edi,04h
        add ebp,ecx
        jnz @unpack
        @unpck:
        add ebx,04h
        mov eax,edx
        mov ebp,[esi+ebx]
        jg @returnUNPACK
        and eax,ebp
        and ebp,ecx
        jmp @unpack
        @fenceUNPACK:
        sfence
        @returnUNPACK:
        popad
        @exitUNPACK:
        ret 00h

        8 megapixeles kép esetén:
        K8:
        - előkészített REP STOSD: 153M órajel
        - @unpackSSE2 (movnti [edi],eax): 68M órajel
        - @unpack (mov [edi],eax): 62M órajel
        Netburst (Prescott):
        - előkészített REP STOSD: 410M órajel
        - @unpackSSE2 (movnti [edi],eax): 110M órajel

        64 byte-os cache-line jutó 3-nál több ugró utasítás hatása elhanyagolható, a code-padding befolyása jelentősebb nála.

        kérdés: esetleges téves elágazásbecslés miatt lefutott sfence-eknek van teljesítményvisszafogó hatásuk, vagy el kell távolítani az ágat a critical path közeléből?

        [ Szerkesztve ]

        (#4) P.H.


          P.H.
          (senior tag)

          32->8 bit signed szaturált érték létrehozása ugrással hatékonyabb, mint anélkül. A

          {input:EAX output:AL}
          mov edx,000000FFh
          cmp eax,edx
          jc @done
          shr eax,1Fh
          add al,cl
          @done:

          kód gyorsabb K8-on és Netburst-on egyaránt, mint a

          {input:EAX output:DL}
          mov ecx,000000FFh
          cmp eax,ecx
          mov edx,ecx
          sbb ebx,ebx
          adc dl,cl
          and ebx,eax
          add eax,eax
          adc dl,bl

          Netburst-ön érthető, hogy miért gyorsabb, de K8-on? Ott 5 órajel lenne az utóbbi.

          MMX nélkül nehéz az élet.

          Az előző kérdésre a válasz: nincs, az sfence sorbarendező utasítás.

          [ Szerkesztve ]

          (#5) P.H. P.H. (#3)


            P.H.
            (senior tag)

            Update:

            K8:
            - előkészített REP STOSD: 153M órajel
            - @unpackSSE2 (movnti [edi],eax): 68M órajel
            - @unpack (mov [edi],eax): 62M órajel
            Netburst (Prescott):
            - előkészített REP STOSD: 410M órajel
            - @unpackSSE2 (movnti [edi],eax): 110M órajel
            - @unpack (mov [edi],eax): 150M órajel

            Ez némi gondolkodnivalót ad a VectorPath, illetve úgy általában a microcode alapú utasításokról. A REP STOSD legrosszabb esetben is egyenértékű a

            @stosd:
            jcxz @done
            dec ecx
            mov [edi],eax
            lea edi,[edi+04h]
            jmp @stosd
            @done:

            sorozattal akár micro-op szinten is: a "service pending interrupts (if any);" lépést és (a debugger-ek tanulsága szerint) ESP-t befolyásoló ugrást mindkettő tartalmaz. A microcode-on alapuló utasítások micro-opjai a microarchitecture szélességére optimalizáltak, de mennyi az az ismétlésmennyiség, aminél a REP STOSD gyorsabb, mint a klasszikus legalapvetőbb egyszerű ciklus? Van egyáltalán ilyen eset?

            [ Szerkesztve ]

            (#6) P.H.


              P.H.
              (senior tag)

              Két PCHAR vagyis null-terminated karaktersorozat kisbetű/nagybetű azonosságú összehasonlítására Windows alatt az lstrcmpi utasítás helyett (ami Windows NT-k alatt a lokalizáció miatt a natív unicode-formátumára konvertálja belül a két forrás string-et az összehasonlításhoz minden hívás alkalmával, ehhez előtte végigmegy rajtuk a hosszuk meghatározásához, stb.) célszerűbb a következő:

              1. valahol a program indításakor elhelyezni egy 256 elemű _uppercase karakterbömtöt, feltölteni a 256 karakterrel, majd rá kiadni a

              CHARUPPERBUFF(@_uppercase,256) ;

              utasítást,

              2. a programban elhelyezni a következő függvényt:

              { EAX: src0 string address
              EDX: src1 string address }
              pushad
              xor esi,esi
              xor edi,edi
              mov ebx,offset(_UPPERCASE)
              add esi,eax
              jz @finalize
              add edi,edx
              jz @finalize
              @compare:
              xor eax,eax
              xor edx,edx
              xor ecx,ecx
              add al,[esi]
              lea esi[esi+01h]
              mov dl,[edi]
              mov al,[ebx+eax]
              jz @final
              add cl,[ebx+edx]
              lea edi,[edi+01h]
              jz @finalize
              cmp al,cl
              jz @compare
              @finalize:
              cmp eax,edx
              popad
              setz al ; elhagyható ASM szinten
              ret

              - procedure STREQUAL(src1,src2: PCHAR): boolean; magas szinten
              - csak a string egyenlőséget/nemegyenlőséget adja vissza BOOL formában, viszont a kisebb/nagyobb relációt is az EFLAGS-ben
              - a NULL pointer mindig a legkisebb a relációban
              - ha egyik bemenő paramétere NULL, a másik egy 00h byte-ra mutató érvényes pointer, akkor nem egyenlőek, a NULL kisebb

              [ Szerkesztve ]

              (#7) P.H. P.H. (#6)


                P.H.
                (senior tag)

                hotfix:

                { EAX: src0 string address
                EDX: src1 string address }
                pushad
                xor esi,esi
                xor edi,edi
                mov ebx,offset(_uppercase)
                add esi,eax
                jz @finalize
                add edi,edx
                jz @finalize
                @compare:
                xor eax,eax
                xor edx,edx
                xor ecx,ecx
                add al,[esi]
                lea esi[esi+01h]
                mov dl,[edi]
                mov al,[ebx+eax]
                jz @final
                add cl,[ebx+edx]
                lea edi,[edi+01h]
                jz @finalize
                cmp al,cl
                mov dl,cl
                jz @compare
                @finalize:
                cmp eax,edx
                popad
                setz al ; elhagyható ASM szinten
                ret

                A "viszont a kisebb/nagyobb relációt is az EFLAGS-ben" törölve (_uppercase átszerkesztés kell hozzá, mert z<ő)

                (#8) P.H.


                  P.H.
                  (senior tag)

                  Minő örömmel töltheti el a felhasználót, hogy amennyiben a Microsoft nem unicode-os API-hívásokkal fordítja saját software-eit (pl. a Windows Explorer, Live Messenger, ...cmd.exe), úgy néha megáll az élet 256 hosszú path-ok felett...

                  Eset: Windows Live Messenger, Shared Folder-be jönne egy file, ez először egy ideiglenes helyre kerül, majd a teljes átvitel után kerül a valós Shared Folder-be, aminek útvonala ezen a gépen a


                  H:\Documents and Settings\Administrator\Local Settings\Application Data\Microsoft\Messenger\ph2000@axelero.hu\Sharing Folders\xxxxxxxx@xxxxxxxx.hu

                  Ám a Windows kellemetlen szokása, hogy szereti az ideiglenes file-okat kvázi véletlenszerűen elnevezett vagy class ID-t tartalmazó mappákban/file-okban tárolni, jelen esetben a


                  H:\Documents and Settings\Administrator\Local Settings\Application Data\Microsoft\Messenger\ph2000@axelero.hu\SharingMetaData\xxxxxxxx@xxxxxxxx.hu\DFSR\Staging\CS{CA0CF46C-3723-B71A-CE04-F0655DF3F9BE}\48\

                  mappa alatti


                  48-{B287AD73-60BB-4C0A-9DD7-E10CE71C4C9D}-v48-{B287AD73-60B8-4C0A-9DD7-E10CE71C4C9D}-v48-Partial.frx

                  nevű file lenne az. Mivel a mappa neve még 256 karakternél rövidebb, viszont a file-névvel együtt az útvonal már messze hosszabb, ezzel maga a Live Messenger sem tud mit kezdeni az átvitel után, egyszerűen nem tudja áttenni a végleges helyére, pedig a partner szerint 100% feltöltöttséget mutat. A file-on sem Cut/Paste, sem Rename, sem Delete nem segít, sem az, ha a partner törli a Shared Folder-éből, csak a következő utasítássorozat:


                  subst z: H:\Documents and Settings\Administrator\Local Settings\Application Data\Microsoft\Messenger\ph2000@axelero.hu\SharingMetaData\xxxxxxxx@xxxxxxxx.hu\DFSR\Staging\CS{CA0CF46C-3723-B71A-CE04-F0655DF3F9BE}\48

                  del *.*

                  subst z: /d

                  [ Szerkesztve ]

                  (#9) P.H.


                    P.H.
                    (senior tag)

                    Under investigation: 2D gráfpont koordinátaszámítás (nagyítás + eltolás) és vágás több százezer ponton.

                    - x87-es kiindulási megoldás (extended precision):

                    @init:
                    fldz
                    @coor:
                    movzx eax,word ptr [edi+STRUCTURE.RSIZE]
                    mov cx,[LIMIT]
                    sub edx,01h
                    lea edi,[edi+eax+STRUCTURESIZE]
                    fstp st(0)
                    jle @sections
                    or byte ptr [edi+STRUCTURE.BITFIELD],$80
                    cmp [edi+STRUCTURE.RSIZE],cx
                    fld dword ptr [edi+STRUCTURE.X]
                    jle @coor
                    fmul st,st(3)
                    mov al,[BITFILTER]
                    fld dword ptr [edi+STRUCTURE.Y]
                    xor ecx,ecx
                    mov [esi],edi
                    fmul st,st(4)
                    fxch
                    test [edi+STRUCTURE.BITFIELD],al
                    fsub st,st(3)
                    mov eax,[IMAGEWIDTH]
                    fistp dword ptr [edi+STRUCTURE.XCOOR]
                    mov ebp,[IMAGEHEIGHT]
                    fsub st,st(1)
                    mov [esi+04h],ecx
                    fist dword ptr [edi+STRUCTURE.YCOOR]
                    jnz @coor
                    sub eax,[edi+STRUCTURE.XCOOR]
                    mov ecx,[edi+STRUCTURE.YCOOR]
                    or eax,[edi+STRUCTURE.XCOOR]
                    sub ebp,ecx
                    or eax,ecx
                    or eax,ebp
                    js @coor
                    and byte ptr [edi+STRUCTURE.BITFIELD],$7F
                    add esi,04h
                    jmp @coor
                    @sections:
                    ...

                    - SSE2 (double precision):

                    @initSSE:
                    mov bp,[LIMIT]
                    mov cl,[BITFILTER]
                    mov bl,[edi+STRUCTURE.BITFIELD]
                    @coorSSE:
                    movzx eax,word ptr [edi+STRUCTURE.RSIZE]
                    sub edx,01h
                    mov [edi+STRUCTURE.BITFIELD],bl
                    movapd xmm3,xmm4
                    lea edi,[edi+eax+STRUCTURESIZE]
                    mov bl,$80
                    jle @sectionSSE
                    cvtps2pd xmm0,[edi+STRUCTURE.X]
                    or bl,[edi+STRUCTURE.BITFIELD]
                    cmp [edi+STRUCTURE.RSIZE],bp
                    mulpd xmm0,xmm2
                    jle @coorSSE
                    subpd xmm0,xmm1
                    cvtpd2dq xmm0,xmm0
                    test bl,cl
                    psubd xmm3,xmm0
                    movq [edi+STRUCTURE.XCOOR],xmm0
                    jnz @coorSSE
                    por xmm3,xmm0
                    pmovmskb eax,xmm3
                    test al,88h
                    jnz @coorSSE
                    and bl,$7F
                    movnti [esi],edi
                    add esi,04h
                    jmp @coorSSE
                    @sectionSSE:
                    xor eax,eax
                    sfence
                    mov [esi],eax
                    ...

                    - 3DNow! (single precision):

                    @init3DNow:
                    mov bp,[LIMIT]
                    mov cl,[BITFILTER]
                    mov bl,[edi+STRUCTURE.BITFIELD]
                    @coor3DNow:
                    movq mm0,mm2
                    movzx eax,word ptr [edi+STRUCTURE.RSIZE]
                    sub edx,01h
                    mov [edi+STRUCTURE.BITFIELD],bl
                    movq mm3,mm4
                    lea edi,[edi+eax+STRUCTURESIZE]
                    mov bl,$80
                    jle @section3DNow
                    pfmul mm0,[edi+STRUCTURE.X]
                    or bl,[edi+STRUCTURE.BITFIELD]
                    cmp [edi+STRUCTURE.RSIZE],bp
                    pfsub mm0,mm1
                    jle @coor3DNow
                    pf2id mm0,mm0
                    test bl,cl
                    psubd mm3,mm0
                    movq [edi+STRUCTURE.XCOOR],mm0
                    jnz @coor3DNow
                    por mm3,mm0
                    pmovmskb eax,mm3
                    test al,88h
                    jnz @coor3DNow
                    and bl,$7F
                    mov [esi],edi
                    add esi,04h
                    jmp @coor3DNow
                    @section3DNow:
                    xor eax,eax
                    emms
                    mov [esi],eax
                    ...

                    A sorrend (TSC alapján):
                    - K8: 1.SSE2 2:3DNow! 3:x87 (kb. 5% eltéréssel)
                    - Netburst: 1:x87 2.SSE2 (elhanyagolható eltéréssel)

                    :F

                    [ Szerkesztve ]

                    (#10) P.H.


                      P.H.
                      (senior tag)

                      A korábbi pár munkaórás skiccek után egy valódi nagypálya, amelyben már több 10 munkaóra fekszik: a következő kódnak 100 megapixeles képeket kellene kezelnie 1 másodpercen belüli időhatárral; jelenleg 32 megapixeles képen tesztelve bőven megvan az 1 másodperc, de gyorsabbnak érződik 2.26 GHz-es CeleronD-n, mint 2.2 GHz-es Opteron-on. Első lépésben a kép erőteljesen tömörítve lesz, és talán vissza lesz az algoritmus írva integer alapra (MMX/SSE2), a színhelyesség megtartásával.

                      A kiindulási kód:

                      @decode:
                      movd esi,mm5
                      movd edx,mm4
                      movd ecx,mm7
                      movd ebx,mm6
                      movss xmm0,[ebp]
                      @temprow:
                      movzx eax,byte ptr [esi]
                      add esi,01h
                      shl eax,04h
                      sub edx,01h
                      movaps xmm3,[ecx+eax]
                      movaps [ebx],xmm3
                      lea ebx,[ebx+20h]
                      jg @temprow
                      add esi,[esp+_SROW]
                      mov ecx,edi
                      movd mm5,esi
                      mov edx,[ebp+08h]
                      @zoomvertSSE:
                      and edi,-32
                      movd esi,mm6
                      add edi,20h
                      shufps xmm0,xmm0,00000000b
                      movd eax,mm4
                      movaps xmm1,[edi]
                      @prevHpixelSSE:
                      movaps xmm4,[esi-00h]
                      movlps xmm2,[esi-10h]
                      mov ebx,[esi-10h+08h]
                      mulps xmm4,xmm0
                      shufps xmm2,xmm2,01000000b
                      movaps xmm3,xmm4
                      @pixelSSE:
                      test ebx,ebx
                      mulps xmm4,xmm2
                      @1pixelSSE:
                      addps xmm1,xmm4
                      jz @nextHpixelSSE
                      movaps [edi],xmm1
                      js @stepHelementSSE
                      add edi,10h
                      movaps xmm4,xmm3
                      sub ebx,01h
                      movaps xmm1,[edi]
                      jnz @1pixelSSE
                      @nextHpixelSSE: { EBX = 0 }
                      shufps xmm2,xmm2,11111111b
                      cmp [esi-10h+04h],ebx
                      lea ebx,[ebx-01h]
                      jnz @pixelSSE
                      @stepHelementSSE: { EBX = -1 }
                      add eax,ebx
                      lea esi,[esi+20h]
                      jnz @prevHpixelSSE
                      mov edi,ecx
                      @moreVrowsSSE: { EAX = 0 és EBX = -1 }
                      add edx,ebx
                      jns @cvtROW
                      cmp edx,ebx
                      jnz @stepVelementSSE
                      add eax,[ebp+04h]
                      movd xmm0,eax
                      jnz @zoomvertSSE
                      @stepVelementSSE:
                      add [esp+_VSIZE],ebx
                      lea ebp,[ebp+20h]
                      jnz @decode
                      mov edx,ebx
                      @cvtROW:
                      mov esi,ecx
                      mov eax,[esp+_INCREASE]
                      and esi,-32
                      sub edi,eax
                      @cvtRGB:
                      add esi,20h
                      cvtps2dq xmm0,[esi+00h]
                      movaps [esi+00h],xmm5
                      cvtps2dq xmm1,[esi+10h]
                      movaps [esi+10h],xmm5
                      packssdw xmm0,xmm1
                      packuswb xmm0,xmm1
                      movq [edi+eax],xmm0
                      add eax,08h
                      js @cvtRGB
                      test edx,edx
                      mov ecx,edi
                      jz @moreVrowsSSE
                      divss xmm0,xmm0
                      jns @zoomvertSSE

                      [ Szerkesztve ]

                      (#11) P.H.


                        P.H.
                        (senior tag)

                        Alakulgat:

                        @copyarraySSE:
                        pshufd xmm0,[eax],01010101b
                        @zoomvertSSE:
                        mov [esp+_DESTROW],edi
                        mov esi,[esp+_STRROWS]
                        xor ebx,ebx
                        and edi,-32
                        sub edx,[esp+_STRLEFT]
                        movd ebp,mm4
                        movd ecx,mm6
                        lea edi,[edi+20h]
                        mov esi,[esi]
                        movaps xmm1,[edi]
                        jge @newpixelSSE
                        @sourceLEFT:
                        mov bl,[esi]
                        add esi,02h
                        add edx,ebx
                        js @sourceLEFT
                        mov bl,[esi-01h]
                        jnz @initpixelSSE
                        @newpixelSSE:
                        movzx edx,word ptr [esi]
                        add esi,02h
                        movzx ebx,dh
                        @initpixelSSE:
                        shl ebx,04h
                        add ebx,[esp+_STRCOLORS]
                        movaps xmm7,[ebx]
                        jmp @nxpixelSSE
                        @prevHpixelSSE:
                        sub dl,01h
                        jz @newpixelSSE
                        @nxpixelSSE:
                        movaps xmm4,xmm7
                        movlps xmm6,[ecx+04h]
                        mov ebx,[ecx+00h]
                        mulps xmm4,xmm0
                        pshufd xmm2,xmm6,01000000b
                        shufps xmm6,xmm6,01010101b
                        movaps xmm3,xmm4
                        @pixelSSE:
                        test ebx,ebx
                        mulps xmm4,xmm2
                        @1pixelSSE:
                        addps xmm1,xmm4
                        jz @nextHpixelSSE
                        movaps [edi],xmm1
                        js @stepHelementSSE
                        add edi,10h
                        movaps xmm4,xmm3
                        sub ebx,01h
                        movaps xmm1,[edi]
                        jnz @1pixelSSE
                        @nextHpixelSSE:
                        cmp ebx,[ecx+08h]
                        movaps xmm2,xmm6
                        lea ebx,[ebx-01h]
                        jnz @pixelSSE
                        @stepHelementSSE:
                        add ebp,ebx
                        lea ecx,[ecx+10h]
                        jnz @prevHpixelSSE
                        mov edi,[esp+_DESTROW]
                        xor edx,edx
                        @moreVrowsSSE:
                        add [eax+00h],ebx
                        jns @cvtROW
                        cmp [eax+00h],ebx
                        jnz @stepVelementSSE
                        cmp ebp,[eax+08h]
                        pshufd xmm0,[eax],10101010b
                        jnz @zoomvertSSE
                        @stepVelementSSE:
                        add dword ptr [esp+_STRROWS],04h
                        add [esp+_VSIZE],ebx
                        lea eax,[eax+10h]
                        jnz @copyarraySSE
                        sub eax,10h
                        mov [eax+00h],ebx
                        @cvtROW:
                        mov esi,edi
                        mov ebp,[esp+_INCREASE]
                        and esi,-32
                        sub edi,ebp
                        @cvtRGB:
                        add esi,20h
                        cvtps2dq xmm3,[esi+00h]
                        movaps [esi+00h],xmm5
                        cvtps2dq xmm1,[esi+10h]
                        movaps [esi+10h],xmm5
                        packssdw xmm3,xmm1
                        packuswb xmm3,xmm1
                        movq [edi+ebp],xmm3
                        add ebp,08h
                        js @cvtRGB
                        cmp [eax+00h],edx
                        jz @moreVrowsSSE
                        divps xmm0,xmm0
                        jns @zoomvertSSE

                        x87:

                        fldz
                        @copyarray:
                        fadd dword ptr [eax+04h]
                        @zoomvert:
                        mov edi,[esp+_DESTROW]
                        mov ecx,[esp+_STRVAR+_ECX]
                        xor ebx,ebx
                        mov esi,[esp+_STRROWS]
                        mov ebp,[ecx-04h]
                        fld dword ptr [edi+00h]
                        mov esi,[esi]
                        fld dword ptr [edi+04h]
                        add ecx,[esp+_XADD]
                        xor edx,edx
                        sub ebx,[esp+_STRLEFT]
                        fld dword ptr [edi+08h]
                        jge @newpixelx86
                        @sourceLEFTx86:
                        mov dl,[esi]
                        add esi,02h
                        add ebx,edx
                        js @sourceLEFTx86
                        mov dl,[esi-01h]
                        jnz @initpixelx86
                        @newpixelx86:
                        movzx ebx,word ptr [esi]
                        add esi,02h
                        movzx edx,bh
                        @initpixelx86:
                        mov [esp+_TMPCOLOR],bl
                        shl edx,04h
                        add edx,[esp+_STRCOLORS]
                        jmp @nxpixelx86
                        @prevHpixel:
                        sub byte ptr [esp+_TMPCOLOR],01h
                        jz @newpixelx86
                        @nxpixelx86:
                        fld dword ptr [ecx+04h]
                        mov ebx,[ecx+00h]
                        @HANDLEPIXEL:
                        fmul st,st(4)
                        test ebx,ebx
                        fld dword ptr [edx+00h]
                        fmul st,st(1)
                        faddp st(4),st
                        fld dword ptr [edx+04h]
                        fmul st,st(1)
                        faddp st(3),st
                        fmul dword ptr [edx+08h]
                        fadd
                        js @stepHelement
                        fld1
                        jz @nextHpixel
                        fxch st(3)
                        fstp dword ptr [edi+00h]
                        fstp dword ptr [edi+08h]
                        fstp dword ptr [edi+04h]
                        add edi,0Ch
                        sub ebx,01h
                        fld dword ptr [edi+04h]
                        fld dword ptr [edi+08h]
                        fld dword ptr [edi+00h]
                        fxch st(3)
                        jnz @HANDLEPIXEL
                        @nextHpixel:
                        cmp [ecx+08h],ebx
                        lea ebx,[ebx-01h]
                        fmul dword ptr [ecx+08h]
                        jnz @HANDLEPIXEL
                        fstp st(0)
                        @stepHelement:
                        add ebp,ebx
                        lea ecx,[ecx+10h]
                        jnz @prevHpixel
                        fstp dword ptr [edi+08h]
                        fstp dword ptr [edi+04h]
                        fstp dword ptr [edi+00h]
                        @moreVrows:
                        add [eax+00h],ebx
                        fsub st,st(0)
                        mov edi,[esp+_DESTROW]
                        jns @cvtROWx86
                        @nextVrow:
                        cmp [eax+00h],ebx
                        jnz @stepVelement
                        cmp ebp,[eax+08h]
                        fadd dword ptr [eax+08h]
                        jnz @zoomvert
                        @stepVelement:
                        add dword ptr [esp+_STRROWS],04h
                        add eax,10h
                        add [esp+_VSIZE],ebx
                        fsub st,st(0)
                        jnz @copyarray
                        sub eax,10h
                        mov [eax+00],ebx
                        @cvtROWx86:
                        mov ecx,[esp+_INCREASE]
                        mov esi,edi
                        lea edx,[edi+ecx]
                        mov [esp+_DESTROW],edx
                        @cvtRGBx86:
                        fld dword ptr [esi+08h]
                        mov [esi+00h],ebp
                        fld dword ptr [esi+00h]
                        mov [esi+08h],ebp
                        fld dword ptr [esi+04h]
                        mov [esi+04h],ebp
                        fistp word ptr [esp+_TMPCOLOR]
                        add esi,0Ch
                        fistp word ptr [edi+00h]
                        mov dl,[esp+_TMPCOLOR]
                        sub ecx,04h
                        fistp word ptr [edi+02h]
                        mov [edi+01h],dl
                        lea edi,[edi+04h]
                        jnz @cvtRGBx86
                        fld1
                        cmp [eax+00h],ebp
                        fadd
                        jz @moreVrows
                        js @removeTEMP
                        jmp @zoomvert

                        [ Szerkesztve ]

                        (#12) P.H.


                          P.H.
                          (senior tag)

                          Under investigation: K8 utasítássorrend

                          ad 1:

                          @rewrite:
                          xor eax,eax
                          sub ecx,01h
                          js @finished
                          mov dl,[ebx+ecx]
                          add eax,[edi+ecx*04h]
                          mov ebp,[esi+edx*04h]
                          cmovz eax,ebp
                          test dl,dl
                          cmovz ebp,eax
                          mov [ebx+ecx*04h],ebp
                          jmp @rewrite

                          ad 2:
                          @rewrite:
                          xor eax,eax
                          sub ecx,01h
                          mov dl,[ebx+ecx]
                          js @finished
                          add eax,[edi+ecx*04h]
                          mov ebp,[esi+edx*04h]
                          cmovz eax,ebp
                          test dl,dl
                          cmovz ebp,eax
                          mov [ebx+ecx*04h],ebp
                          jmp @rewrite

                          ECX = 2 853 960 bemeneti értékkel az első ciklus lefutása 25M clock (~9 clock/pixel), a 2. ciklusé 30M clock (~10-11 clock/pixel). Az első cmovz általi átírás sosem fut le, a másodiké 90%-ban.

                          Ennek ellentmod, hogy a

                          test eax,eax
                          cmp eax,[eax-04h]

                          kód abban az esetben, ha EAX = 0, védelmi hibával leáll, tehát a cmovcc függ mindhárom bemeneti értékétől.

                          A referencia x86 kód 32M órajel:

                          @rewrite:
                          xor eax,eax
                          sub ecx,01h
                          mov dl,[ebx+ecx]
                          js @finished
                          add eax,[edi+ecx*04h]
                          mov ebp,[esi+edx*04h]
                          jz @store
                          test dl,dl
                          xchg ebp,eax
                          jz @store
                          mov ebp,eax
                          @store:
                          mov [ebx+ecx*04h],ebp
                          jmp @rewrite
                          @finished:

                          [ Szerkesztve ]


                          P.H.
                          (senior tag)

                          hotfix:

                          Ennek ellentmond, hogy a (dinamikusan allokált tömb méretének lekérdezése, ha a tömb nem NULL):

                          test eax,eax
                          cmovnz eax,[eax-04h]

                          kód EAX = 0 esetben védelmi hibával leáll, tehát a cmovcc függ mindkét bemeneti értékétől.

                          [ Szerkesztve ]

                          (#14) P.H.


                            P.H.
                            (senior tag)

                            Harmadik felvonás, az előző már érdemes volt egy gyors első generációs Netburst port issue elemzésre és TSC-mérésekre.

                            Előző (Prescott CeleronD): 735M clock
                            Az alábbi (Prescott CeleronD): 670M clock (-10%)
                            Az alábbi (K8 Opteron): 565M clock

                            movd xmm0,[eax+04h] // 6+6/2 p1+1+2 MMX_MSC+MMX_SH+LOAD
                            @zoomvertSSE: //
                            mov [esp+_DESTROW],edi // 2/d p3 STORE
                            xor ebx,ebx // d/d p0/1 ALU 0/1
                            mov esi,[esp+_STRROWS] // 2+d/d p0/1+2 ALU 0/1+LOAD
                            and edi,-64 // d/d p0/1 ALU 0/1
                            sub edx,[esp+_STRLEFT] // 2+d/d p0/1+2 ALU 0/1+LOAD
                            movd ebp,mm4 // 10/1 p0+1 FP_MOV+FP_MISC
                            pshufd xmm0,xmm0,00000000b // 4/2 p1 MMX_SH
                            movd ecx,mm6 // 10/1 p0+1 FP_MOV+FP_MISC
                            lea edi,[edi+40h] // d/d p0/1 ALU 0/1
                            mov esi,[esi] // 2+d/d p0/1+2 ALU 0/1+LOAD
                            cmovge edx,ebx //
                            movaps xmm1,[edi] // 6+6/1 p0+2 FP_MOV+LOAD
                            @sourceLEFT: //
                            mov bl,[esi] // 2+d/d p0/1+2 ALU 0/1+LOAD
                            add esi,02h // d/d p0/1 ALU 0/1
                            add edx,ebx // d/d p0/1 ALU 0/1
                            jle @sourceLEFT // -/d p0 ALU 0
                            mov bl,[esi-01h] // 2+d/d p0/1+2 ALU 0/1+LOAD
                            jmp @initpixelSSE // -/d p0 ALU 0
                            @newpixelSSE: //
                            movzx edx,word ptr [esi] // 2+d/d p0/1+2 ALU 0/1+LOAD
                            add esi,02h // d/d p0/1 ALU 0/1
                            movzx ebx,dh // d/d p0/1+2 ALU 0/1
                            @initpixelSSE: //
                            movaps xmm3,xmm0 // 6/1 p0 FP_MOV
                            shl ebx,04h // 4/1 p1 CMPXALU
                            add dl,01h // d/d p0/1 ALU 0/1
                            add ebx,[esp+_STRCOLORS] // 2+d/d p0/1+2 ALU 0/1+LOAD
                            mulps xmm3,[ebx] // 6+6/2 p1+2 FP_MUL+LOAD
                            @prevHpixelSSE: //
                            sub dl,01h // d/d p0/1 ALU 0/1
                            jz @newpixelSSE // -/d p0 ALU 0
                            pshufd xmm2,[ecx+00h],10010101b // 6+4/2 p1+2 MMX_SH+LOAD
                            movaps xmm4,xmm3 // 6/1 p0 FP_MOV
                            mov ebx,[ecx+00h] // 2+d/d p0/1+2 ALU 0/1+LOAD
                            @pixelSSE: //
                            mulps xmm4,xmm2 // 6/2 p1+2 FP_MUL
                            test ebx,ebx // d/d p0/1 ALU 0/1
                            @1pixelSSE: //
                            addps xmm1,xmm4 // 4/2 p1 FP_ADD
                            jz @nextHpixelSSE // -/d p0 ALU 0
                            movaps [edi],xmm1 // 6+6/1 p0+3 FP_STR+STORE
                            js @stepHelementSSE // -/d p0 ALU 0
                            add edi,10h // d/d p0/1 ALU 0/1
                            movaps xmm4,xmm3 // 6/1 p0 FP_MOV
                            sub ebx,01h // d/d p0/1 ALU 0/1
                            movaps xmm1,[edi] // 6+6/1 p0+2 FP_MOV+LOAD
                            jnz @1pixelSSE // -/d p0 ALU 0
                            @nextHpixelSSE: //
                            cmp ebx,[ecx+08h] // 2+d/d p0/1+2 ALU 0/1+LOAD
                            pshufd xmm2,xmm2,11111111b // 4/2 p1 MMX_SH
                            lea ebx,[ebx-01h] // d/d p0/1 ALU 0/1
                            jnz @pixelSSE // -/d p 1 ALU 0
                            @stepHelementSSE: //
                            add ebp,ebx // d/d p0/1 ALU 0/1
                            lea ecx,[ecx+10h] // d/d p0/1 ALU 0/1
                            jnz @prevHpixelSSE // -/d p0 ALU 0
                            mov edi,[esp+_DESTROW] // 2+d/d p0/1+2 ALU 0/1+LOAD
                            xor edx,edx // d/d p0/1 ALU 0/1
                            @moreVrowsSSE: //
                            add [eax+00h],ebx // 2+2+d/d p0+2+3 ALU 0/1+LOAD+STORE
                            jns @cvtROW // -/d p0 ALU 0
                            cmp ebx,[eax+00h] // 2+d/d p0/1+2 ALU 0/1+LOAD
                            jnz @stepVelementSSE // -/d p0 ALU 0
                            add ebp,[eax+08h] // 2+d/d p0/1+2 ALU 0/1+LOAD
                            movd xmm0,ebp // 6/2 p1 MMX_MSC+MMX_SH
                            jnz @zoomvertSSE // -/d p0 ALU 0
                            @stepVelementSSE: //
                            add dword ptr [esp+_STRROWS],04h // 2+2+d/d p0+1+3 ALU 0/1+LOAD+STORE
                            add [esp+_VSIZE],ebx // 2+2+d/d p0+1+3 ALU 0/1+LOAD+STORE
                            lea eax,[eax+10h] // d/d p0/1 ALU 0/1
                            jnz @copyarraySSE // -/d p0 ALU 0
                            sub eax,10h // d/d p0/1 ALU 0/1
                            mov [eax+00h],ebx // 2/d p3 STORE
                            @cvtROW: //
                            mov esi,edi // d/d p0/1 ALU 0/1
                            mov ebp,[esp+_INCREASE] // 2+d/d p0/1+2 ALU 0/1+LOAD
                            and esi,-64 // d/d p0/1 ALU 0/1
                            sub edi,ebp // d/d p0/1 ALU 0/1
                            @cvtRGB: //
                            add esi,40h // d/d p0/1 ALU 0/1
                            cvtps2dq xmm1,[esi+00h] // 6+5/1 p1 FP_ADD+LOAD
                            cvtps2dq xmm2,[esi+10h] // 6+5/1 p1 FP_ADD+LOAD
                            cvtps2dq xmm3,[esi+20h] // 6+5/1 p1 FP_ADD+LOAD
                            cvtps2dq xmm4,[esi+30h] // 6+5/1 p1 FP_ADD+LOAD
                            movaps [esi+00h],xmm5 // 6+6/1 p0+3 FP_STR+STORE
                            movaps [esi+10h],xmm5 // 6+6/1 p0+3 FP_STR+STORE
                            movaps [esi+20h],xmm5 // 6+6/1 p0+3 FP_STR+STORE
                            movaps [esi+30h],xmm5 // 6+6/1 p0+3 FP_STR+STORE
                            packssdw xmm1,xmm2 // 2/1 p1 MMX_SHF
                            packssdw xmm3,xmm4 // 2/1 p1 MMX_SHF
                            packuswb xmm1,xmm3 // 2/1 p1 MMX_SHF
                            movups [edi+ebp],xmm1 // 6/1 p0 FP_MOV
                            add ebp,10h // d/d p0/1 ALU 0/1
                            js @cvtRGB // -/d p0 ALU 0
                            cmp [eax+00h],edx // 2+d/d p0/1+2 ALU 0/1+LOAD
                            jz @moreVrowsSSE // -/d p0 ALU 0
                            divss xmm0,xmm0 // 23/23 p1 FP_DIV
                            jns @zoomvertSSE // -/d p0 ALU 0

                            [ Szerkesztve ]

                            (#15) P.H.


                              P.H.
                              (senior tag)

                              Azt hiszem, elérhetetlen céljaim egyike, hogy a Netburst-öt megértsem...

                              Prescott CeleronD: 630M clock (-4%)
                              K8 Opteron: 585M clock (+4%)

                              Csupán két utasítás sorrendjének felcserélésével (melynek mellékhatásaként a memóriaparaméteres PSHUFD 3 millió helyett 6 milliószor fut le).

                              K8 analízis (túl sok a VectorPath):

                              @copyarraySSE: //
                              movd xmm0,[eax+04h] // 9/- FPUvector
                              @zoomvertSSE: //
                              mov [esp],edi // 3/1 p0/1/2 ALU 0/1/2
                              xor ebx,ebx // 1/1 p0/1/2 ALU 0/1/2
                              mov esi,[esp+_STRROWS] // 3/1 p0/1/2 ALU 0/1/2
                              and edi,-64 // 1/1 p0/1/2 ALU 0/1/2
                              sub edx,[esp+_STRLEFT] // 4/1 p0/1/2 ALU 0/1/2
                              movd ebp,mm4 // 4/- FPUvector
                              pshufd xmm0,xmm0,00000000b // 4/- FPUvector
                              movd ecx,mm6 // 4/- FPUvector
                              lea edi,[edi+40h] // 1/1 p0/1/2 ALU 0/1/2
                              mov esi,[esi] // 3/1 p0/1/2 ALU 0/1/2
                              cmovge edx,ebx // 1/1 p0/1/2 ALU 0/1/2
                              movaps xmm1,[edi] // 4/- p5 FSTORE
                              @sourceLEFT: //
                              mov bl,[esi] // 4/1 p0/1/2 ALU 0/1/2
                              add esi,02h // 1/1 p0/1/2 ALU 0/1/2
                              add edx,ebx // 1/1 p0/1/2 ALU 0/1/2
                              jle @sourceLEFT // 1/1 p0/1/2 ALU 0/1/2
                              mov bl,[esi-01h] // 4/1 p0/1/2 ALU 0/1/2
                              jmp @initpixelSSE // 1/1 p0/1/2 ALU 0/1/2
                              @newpixelSSE: //
                              movzx edx,word ptr [esi] // 1/1 p0/1/2 ALU 0/1/2
                              add esi,02h // 1/1 p0/1/2 ALU 0/1/2
                              movzx ebx,dh // 1/1 p0/1/2 ALU 0/1/2
                              @initpixelSSE: //
                              movaps xmm3,xmm0 // 2/1 p3/4 FADD/FMUL
                              shl ebx,04h // 1/1 p0/1/2 ALU 0/1/2
                              add dl,01h // 1/1 p0/1/2 ALU 0/1/2
                              add ebx,[esp+_STRCOLORS] // 4/1 p0/1/2 ALU 0/1/2
                              mulps xmm3,[ebx] // 7/2 p4 FMUL
                              @prevHpixelSSE: //
                              sub dl,01h // 1/1 p0/1/2 ALU 0/1/2
                              pshufd xmm2,[ecx+00h],10010101b // 4/- FPUvector
                              jz @newpixelSSE // 1/1 p0/1/2 ALU 0/1/2
                              movaps xmm4,xmm3 // 2/1 p3/4 FADD/FMUL
                              mov ebx,[ecx+00h] // 4/1 p0/1/2 ALU 0/1/2
                              @pixelSSE: //
                              mulps xmm4,xmm2 // 7/2 p4 FMUL
                              test ebx,ebx // 1/1 p0/1/2 ALU 0/1/2
                              @1pixelSSE: //
                              addps xmm1,xmm4 // 5/2 p3 FADD
                              jz @nextHpixelSSE // 1/1 p0/1/2 ALU 0/1/2
                              movaps [edi],xmm1 // 3/- p5 FSTORE
                              js @stepHelementSSE // 1/1 p0/1/2 ALU 0/1/2
                              add edi,10h // 1/1 p0/1/2 ALU 0/1/2
                              movaps xmm4,xmm3 // 2/1 p3/4 FADD/FMUL
                              sub ebx,01h // 1/1 p0/1/2 ALU 0/1/2
                              movaps xmm1,[edi] // 4/- p5 FSTORE
                              jnz @1pixelSSE // 1/1 p0/1/2 ALU 0/1/2
                              @nextHpixelSSE: //
                              cmp ebx,[ecx+08h] // 4/1 p0/1/2 ALU 0/1/2
                              pshufd xmm2,xmm2,11111111b // 4/- FPUvector
                              lea ebx,[ebx-01h] // 1/1 p0/1/2 ALU 0/1/2
                              jnz @pixelSSE // 1/1 p0/1/2 ALU 0/1/2
                              @stepHelementSSE: //
                              add ebp,ebx // 1/1 p0/1/2 ALU 0/1/2
                              lea ecx,[ecx+10h] // 1/1 p0/1/2 ALU 0/1/2
                              jnz @prevHpixelSSE // 1/1 p0/1/2 ALU 0/1/2
                              mov edi,[esp] // 4/1 p0/1/2 ALU 0/1/2
                              xor edx,edx // 1/1 p0/1/2 ALU 0/1/2
                              @moreVrowsSSE: //
                              add [eax+00h],ebx // 4/1 p0/1/2 ALU 0/1/2
                              jns @cvtROW // 1/1 p0/1/2 ALU 0/1/2
                              cmp ebx,[eax+00h] // 4/1 p0/1/2 ALU 0/1/2
                              jnz @stepVelementSSE // 1/1 p0/1/2 ALU 0/1/2
                              add ebp,[eax+08h] // 4/1 p0/1/2 ALU 0/1/2
                              movd xmm0,ebp // 9/- FPUvector
                              jnz @zoomvertSSE // 1/1 p0/1/2 ALU 0/1/2
                              @stepVelementSSE: //
                              add dword ptr [esp+_STRROWS],04h // 4/1 p0/1/2 ALU 0/1/2
                              add [esp+_VSIZE],ebx // 4/1 p0/1/2 ALU 0/1/2
                              lea eax,[eax+10h] // 1/1 p0/1/2 ALU 0/1/2
                              jnz @copyarraySSE // 1/1 p0/1/2 ALU 0/1/2
                              sub eax,10h // 1/1 p0/1/2 ALU 0/1/2
                              mov [eax+00h],ebx // 3/1 p0/1/2 ALU 0/1/2
                              @cvtROW: //
                              mov esi,edi // 1/1 p0/1/2 ALU 0/1/2
                              mov ebp,[esp+_INCREASE] // 4/1 p0/1/2 ALU 0/1/2
                              and esi,-64 // 1/1 p0/1/2 ALU 0/1/2
                              sub edi,ebp // 1/1 p0/1/2 ALU 0/1/2
                              @cvtRGB: //
                              add esi,40h // 1/1 p0/1/2 ALU 0/1/2
                              cvtps2dq xmm1,[esi+00h] // 7/2 p5 FSTORE
                              cvtps2dq xmm2,[esi+10h] // 7/2 p5 FSTORE
                              cvtps2dq xmm3,[esi+20h] // 7/2 p5 FSTORE
                              cvtps2dq xmm4,[esi+30h] // 7/2 p5 FSTORE
                              movaps [esi+00h],xmm5 // 3/- p5 FSTORE
                              packssdw xmm1,xmm2 // 2/- p3/4 FADD/FMUL
                              movaps [esi+10h],xmm5 // 3/- p5 FSTORE
                              packssdw xmm3,xmm4 // 2/- p3/4 FADD/FMUL
                              movaps [esi+20h],xmm5 // 3/- p5 FSTORE
                              packuswb xmm1,xmm3 // 2/- p3/4 FADD/FMUL
                              movaps [esi+30h],xmm5 // 3/- p5 FSTORE
                              movups [edi+ebp],xmm1 //
                              add ebp,10h // 1/1 p0/1/2 ALU 0/1/2
                              js @cvtRGB // 1/1 p0/1/2 ALU 0/1/2
                              cmp [eax+00h],edx // 4/1 p0/1/2 ALU 0/1/2
                              jz @moreVrowsSSE // 1/1 p0/1/2 ALU 0/1/2
                              divss xmm0,xmm0 //16/- p4 FMUL
                              jns @zoomvertSSE // 1/1 p0/1/2 ALU 0/1/2

                              Nem látom Netburst-ön tovább az utat: a 19 clock/forráspixeles globális sebességet PSHUFD-MOVAPS-MULPS-ADDPS kvartett kifeszíti, a többi utasítás futását szinte teljesen elrejti.

                              Most már kíváncsi vagyok, hogy egy P3-on mit lehet kihozni.

                              [ Szerkesztve ]

                              (#16) P.H.


                                P.H.
                                (senior tag)

                                .

                                [ Szerkesztve ]

                                (#17) P.H.


                                  P.H.
                                  (senior tag)

                                  .

                                  [ Szerkesztve ]

                                  (#18) P.H.


                                    P.H.
                                    (senior tag)

                                    A dolog befejettnek tekinthető, végső stat:

                                    - SSE2-kód Prescott CeleronD + DDR: 630M clock
                                    - SSE2-kód Northwood Celeron + SDRAM: 635M clock
                                    - SSE2-kód K8 Opteron + DDR2: 585M clock
                                    - SSE1-kód P3 Coppermine + SDRAM: 670M clock
                                    - x87-kód Prescott CeleronD + DDR: 950M clock
                                    - x87-kód K8 Opteron + DDR2: 590M clock

                                    (#19) P.H.


                                      P.H.
                                      (senior tag)

                                      Perfmonitor: x87-kód - K8 - végtelen ciklusban

                                      PerfMonitor Record file
                                      Counter 0 : Non-halted clock cycles
                                      Counter 1 : Instructions per cycle (IPC) (átlag: 1.6 IPC)
                                      Counter 2 : Retired x87 instructions
                                      Counter 3 : Retired uops (átlag: 1.67 uop/cycle)

                                      T(ms) c0(M/s) c1(i/c) c2(M/s) c3(M/s)
                                      50 2147.3 1.7 1764.7 3557.5
                                      100 2144.6 1.7 1789.1 3574.9
                                      150 2148.1 1.6 1743.1 3523.0
                                      200 2144.3 1.6 1737.0 3516.0
                                      250 2145.9 1.6 1749.0 3534.2
                                      300 1951.9 1.5 1518.6 3068.6
                                      350 1951.9 1.5 1518.6 3068.6
                                      400 2166.6 1.6 1784.2 3573.8
                                      450 2145.0 1.6 1740.0 3515.3
                                      500 2148.4 1.6 1739.3 3521.1
                                      550 2080.0 1.7 1728.9 3469.3
                                      600 2080.0 1.7 1728.9 3469.3
                                      650 2174.7 1.7 1815.4 3625.6
                                      700 2146.9 1.6 1735.7 3510.5
                                      750 2153.0 1.6 1739.5 3522.5
                                      800 2146.5 1.7 1776.5 3573.7
                                      850 2146.5 1.7 1776.5 3573.7
                                      900 2161.3 1.7 1810.6 3611.2
                                      950 2145.1 1.6 1735.2 3509.7
                                      1000 2143.9 1.6 1736.8 3513.5
                                      1050 2149.8 1.7 1766.1 3560.8
                                      1100 1901.3 1.4 1373.4 2820.3
                                      1150 1901.3 1.4 1373.4 2820.3
                                      1200 2170.7 1.6 1773.8 3565.8
                                      1250 2149.7 1.6 1745.0 3526.8
                                      1300 2146.6 1.6 1754.7 3542.4
                                      1350 1917.8 1.4 1437.8 2919.8
                                      1400 1917.8 1.4 1437.8 2919.8
                                      1450 2175.2 1.7 1794.4 3596.8
                                      1500 2143.4 1.6 1739.3 3513.9
                                      1550 2146.2 1.6 1739.8 3521.4
                                      1600 2007.6 1.6 1621.3 3281.0
                                      1650 2007.6 1.6 1621.3 3281.0
                                      1700 2168.2 1.7 1806.2 3609.1
                                      1750 2147.8 1.6 1742.8 3521.1
                                      1800 2146.3 1.6 1732.0 3508.8
                                      1850 2148.4 1.7 1782.0 3582.2
                                      1900 1912.0 1.4 1362.6 2799.5
                                      1950 1912.0 1.4 1362.6 2799.5
                                      2000 2173.2 1.6 1776.2 3570.1

                                      Perfmonitor: SSE2-kód - K8 - végtelen ciklusban
                                      (ott fut a kód, ahol a counter 2 oszlop 0.0)

                                      PerfMonitor Record file
                                      Counter 0 : Non-halted clock cycles
                                      Counter 1 : Instructions per cycle (IPC) (átlag: 1.2 IPC)
                                      Counter 2 : Retired x87 instructions
                                      Counter 3 : Retired uops (átlag: 1.89 uop/cycle)

                                      T(ms) c0(M/s) c1(i/c) c2(M/s) c3(M/s)
                                      50 2144.4 1.2 0.0 3937.9
                                      100 2124.2 1.2 0.0 3932.0
                                      150 2124.2 1.2 0.0 3932.0
                                      200 2163.4 1.3 0.0 4087.8
                                      250 2151.2 1.2 0.0 3928.3
                                      300 2148.1 1.2 0.0 3949.5
                                      350 2150.4 1.3 0.0 4026.4
                                      400 2150.4 1.3 0.0 4026.4
                                      450 2113.7 1.3 0.0 3985.9
                                      500 2145.0 1.2 0.0 3944.8
                                      550 2140.1 1.2 0.0 3936.2
                                      600 1997.1 1.2 91.2 3642.2
                                      650 1997.1 1.2 91.2 3642.2
                                      700 2169.1 1.2 0.0 4043.4
                                      750 2145.4 1.2 0.0 3945.1
                                      800 2145.3 1.2 0.0 3987.8
                                      850 1915.7 1.1 269.3 3111.7
                                      900 2146.0 1.3 0.0 4045.9
                                      950 2146.0 1.3 0.0 4045.9
                                      1000 2170.9 1.2 0.0 4005.7
                                      1050 2141.6 1.3 0.0 4013.2
                                      1100 1906.3 1.1 269.3 3077.8
                                      1150 2148.3 1.3 0.0 4031.8
                                      1200 2148.3 1.3 0.0 4031.8
                                      1250 2170.4 1.2 0.0 3984.1
                                      1300 1972.1 1.2 140.0 3523.7
                                      1350 2086.6 1.2 129.3 3613.1
                                      1400 2144.9 1.2 0.0 3973.6
                                      1450 2144.9 1.2 0.0 3973.6
                                      1500 2163.4 1.2 0.0 4044.9
                                      1550 1376.2 1.1 128.3 2225.5
                                      1600 2077.9 1.2 141.0 3582.1
                                      1650 2149.2 1.2 0.0 3983.2
                                      1700 2150.4 1.2 0.0 3957.1
                                      1750 2150.4 1.2 0.0 3957.1
                                      1800 1931.8 1.1 269.2 3197.0
                                      1850 2151.3 1.3 0.0 4054.5
                                      1900 2148.0 1.2 0.0 3947.1
                                      1950 2142.7 1.2 0.0 3929.8
                                      2000 2142.7 1.2 0.0 3929.8

                                      [ Szerkesztve ]

                                      (#20) P.H.


                                        P.H.
                                        (senior tag)

                                        Perfmonitor: x87-kód - K10.5 - végtelen ciklusban

                                        PerfMonitor Record file
                                        Counter 0 : Non-halted clock cycles
                                        Counter 1 : Instructions per cycle (IPC) (átlag: 2.1 IPC)
                                        Counter 2 : Retired x87 instructions
                                        Counter 3 : Retired uops (átlag: 2.16 uop/cycle)

                                        T(ms) c0(M/s) c1(i/c) c2(M/s) c3(M/s)
                                        50 3285.4 2.2 3529.4 7076.8
                                        100 3063.2 2.0 3099.1 6264.5
                                        150 3284.3 2.2 3543.0 7099.7
                                        200 3188.5 2.1 3319.6 6680.5
                                        250 3272.3 2.1 3450.2 6938.7
                                        300 3255.9 2.2 3497.3 7011.3
                                        350 3173.4 2.0 3247.4 6558.3
                                        400 3285.2 2.1 3496.2 7020.2
                                        450 3133.1 2.0 3214.7 6477.7
                                        500 3241.0 2.1 3432.2 6899.0
                                        550 3162.5 2.1 3294.7 6630.9
                                        600 3282.7 2.1 3463.3 6967.7
                                        650 3143.3 2.0 3247.2 6534.4
                                        700 3279.9 2.1 3463.5 6966.5
                                        750 3168.5 2.1 3330.2 6697.5
                                        800 3160.7 2.1 3303.5 6645.5
                                        850 3257.3 2.1 3398.0 6837.9
                                        900 3286.2 2.1 3517.0 7055.1
                                        950 3156.7 2.0 3244.1 6546.1
                                        1000 3286.9 2.1 3495.6 7020.8
                                        1050 3147.3 2.0 3259.4 6566.0
                                        1100 3284.1 2.1 3478.9 6992.5
                                        1150 3157.7 2.0 3279.2 6601.2
                                        1200 3282.2 2.1 3461.4 6964.0
                                        1250 3142.5 2.0 3248.9 6537.4
                                        1300 3248.4 2.1 3428.5 6896.7
                                        1350 3168.8 2.0 3285.2 6617.9
                                        1400 3276.6 2.1 3488.3 7006.2
                                        1450 3160.6 2.0 3217.0 6490.4
                                        1500 3283.6 2.2 3526.5 7071.4
                                        1550 3164.2 2.0 3229.8 6524.4
                                        1600 3280.5 2.2 3538.5 7090.2
                                        1650 3160.1 2.0 3219.3 6506.2
                                        1700 3277.7 2.2 3538.4 7089.3
                                        1750 3227.3 2.1 3442.4 6909.4
                                        1800 3140.5 2.0 3214.9 6486.7
                                        1850 3284.8 2.1 3499.9 7027.2
                                        1900 3164.0 2.0 3272.6 6594.4
                                        1950 3246.3 2.1 3346.8 6746.4
                                        2000 3283.9 2.2 3539.6 7093.4

                                        Perfmonitor: SSE2-kód - K10.5 - végtelen ciklusban
                                        (ott fut a tisztán kód, ahol a counter 2 oszlop 0.0)

                                        PerfMonitor Record file
                                        Counter 0 : Non-halted clock cycles
                                        Counter 1 : Instructions per cycle (IPC) (átlag: 1.7 IPC)
                                        Counter 2 : Retired x87 instructions
                                        Counter 3 : Retired uops (átlag: 1.67 uop/cycle)

                                        T(ms) c0(M/s) c1(i/c) c2(M/s) c3(M/s)
                                        50 3110.8 1.7 0.0 5212.7
                                        100 3119.8 1.6 219.1 5110.6
                                        150 3138.6 1.6 195.4 5217.6
                                        200 3280.6 1.6 23.5 5409.9
                                        250 3163.5 1.6 219.1 5193.5
                                        300 3291.7 1.7 0.0 5519.1
                                        350 3125.2 1.6 219.4 5141.1
                                        400 3299.2 1.7 0.0 5514.0
                                        450 3175.4 1.6 218.8 5266.7
                                        500 3279.5 1.7 0.0 5465.3
                                        550 3145.7 1.6 219.0 5146.2
                                        600 3296.9 1.7 0.0 5542.1
                                        650 3172.3 1.6 218.8 5205.1
                                        700 3172.6 1.6 218.7 5211.1
                                        750 3275.5 1.7 0.0 5503.3
                                        800 3167.4 1.6 220.0 5211.2
                                        850 3296.8 1.7 0.0 5519.2
                                        900 3146.2 1.6 219.0 5161.8
                                        950 3299.9 1.7 0.0 5507.0
                                        1000 3157.2 1.6 218.6 5227.3
                                        1050 3300.9 1.7 0.0 5518.8
                                        1100 3175.5 1.6 218.9 5230.2
                                        1150 3200.4 1.6 141.9 5361.2
                                        1200 3227.2 1.6 77.2 5275.1
                                        1250 3167.0 1.6 218.9 5195.1
                                        1300 3294.7 1.7 0.0 5516.8
                                        1350 3159.2 1.6 218.8 5212.8
                                        1400 3298.6 1.7 0.0 5512.2
                                        1450 3169.7 1.6 218.9 5254.5
                                        1500 3300.2 1.7 0.0 5509.1
                                        1550 3089.0 1.6 216.1 5077.3
                                        1600 3297.4 1.7 0.0 5527.0
                                        1650 3173.8 1.6 219.0 5221.7
                                        1700 3137.5 1.6 217.2 5211.7
                                        1750 3293.4 1.7 1.6 5442.9
                                        1800 3157.7 1.6 218.7 5185.6
                                        1850 3292.4 1.7 0.0 5518.1
                                        1900 3142.9 1.6 219.0 5171.3
                                        1950 3298.1 1.7 0.0 5506.7
                                        2000 3174.0 1.6 218.8 5261.2

                                        üzenetek