Geschwindigkeit optimieren ... ?



  • In diversen Grafiktests (vor allem im guten alten ModeX) hab ich unterschiedliche Routinen eingesetzt: den Aufruf des Interrupt 10h, eine direkte Adressierung für einen Pixel und zu guter letzt für unterschiedliche Funktionen (Rechteck, Linie, ...) speziell optimierte Routinen.

    Als Vergleich hab ich dann noch die Multiplikation durch ein Bitshifting und ne Addition ersetzt, also
    ein

    MOV ax,320
    MUL [y]
    mov di,ax

    wurde zu

    mov di,[y]
    mov cl,6
    shl di,cl
    mov ax,[y]
    xchg ah,al
    add di,ax

    auch wenn er länger ist, so wird der zweite Code auf meinen älteren Rechnern (386, 486) schnell ausgeführt, als der erste (wegen der Umgehung der Multiplikation).
    Als ich das Prog aber auf nem AMD K2 - 450 laufen lies, war die erste Routine schneller fertig, als die zweite...
    Kanns jetzt sein, dass durch das immer Voranschreitende Anpassen der Prozessoren die "alten, optimierten" Routinen nun langsamer sind als die Standardroutinen?

    mfg ETNA



  • Fangen wir mal mit den älteren prozessoren an. Da ergeben sich als Takzeiten:

    8086 | 80186 | 80286 | 80386 | 80486 |       Pentium
                          |       |       |       |       | einzeln    tatsächlich
    ----------------------+-------+-------+-------+-------+------------------------
    mov ax,320          4 |   3-4 |     2 |     2 |     1 |    1  UV        1
    mul [y]       129-144 | 41-43 |    24 | 12-25 | 13-25 |   11  NP       11
    mov di,ax           2 |     2 |     2 |     2 |     1 |    1  UV        1
    ----------------------+-------+-------+-------+-------+------------------------
    Total         135-150 | 46-49 |    28 | 16-29 | 15-27 |                13
    
                     8086 | 80186 | 80286 | 80386 | 80486 |       Pentium
                          |       |       |       |       | einzeln    tatsächlich
    ----------------------+-------+-------+-------+-------+------------------------
    mov di,[y]         17 |    12 |     5 |     4 |     1 |    1 UV         1
    mov cl,6            4 |   3-4 |     2 |     2 |     1 |    1 UV
    shl di,cl          32 |    11 |    11 |     3 |     3 |    4 NP         4
    mov ax,[y]         17 |    12 |     5 |     4 |     1 |    1 UV         1
    xchg ah,al          3 |     3 |     2 |     2 |     1 |    1 UV         1
    add di,ax           3 |     3 |     2 |     2 |     1 |    1 UV         1
    ----------------------+-------+-------+-------+-------+------------------------
    Total              76 | 44-45 |    27 |    17 |     8 |                 8
    

    Auf den AMD-Prozessoren wird das ganze nun wesentlich interessanter, weil die ja die Befehle sowieso erstmal in eine interne Microcode-Struktur umwandeln. Daher ist ne genaue Taktzyklen-berechnung da auch schwer, ich versuch mich mal grob 🙂
    Auf AMD-Prozessoren unterscheidet man DirectPath- und VectorPath-Anweisungen. DirectPath-Anweisungen lassen sich direkt in einen Microcode umwandeln und können schnell vom Prozessor bearbeitet werden. VectorPath-Anweisungen müssen erst durch nen Dekoder und brauchen daher nen Moment länger.

    Taktzyklen        Path
    ---------------------------------------------------
    mov ax,320             1         DirectPath         
    mul [y]                8         VectorPath
    mov di,ax              1         DirectPath
    ---------------------------------------------------
    Total                 10    (keine Parallelisierung, da jede Instruktion
                                 von der vorherigen abhängt)
    
                      Taktzyklen        Path
    ---------------------------------------------------
    mov di,[y]             3         DirectPath
    mov cl,6               1         DirectPath
    shl di,cl              1         DirectPath
    mov ax,[y]             3         DirectPath
    xchg ah,al             2         VectorPath
    add di,ax              1         DirectPath
    ---------------------------------------------------
    Total                 11
    
    Bestmögliche Parallelisierung:
    
    |                    T a k t z y k l e n                     |
    |     1    ||    2     ||    3     ||     4     ||     5     |
    +----------++----------++----------++-----------++-----------+
    [----------- mov di,[y] -----------][ shl dl,cl ][ add di,ax ]
    [ mov cl,6 ][mov ax,[y]][xchg ah,al]--------------------------
    
    5 Taktzyklen
    

    Ergo: Prinzipiell ist die zweite Lösung immernoch die günstigere. Entweder hast du dich vermessen 😉 oder die Cachepolitik von AMD-Prozessoren sind im ersten Fall immernoch günstiger und verlangsamern im zweiten Fall die Berechnung 🙂

    Zusatz:
    Ich hab mal eben die beiden Sources in ein kelines Prog gebaut, den Code jeweils 0x0fffffff-mal 😉 ausführen lassen und komme auf 2 Sekunden für den ersten und 1,8 Sekunden für den zweiten. Also auf meinem AMD Duron funktioniert die Berechnung 🙂

    [ Dieser Beitrag wurde am 03.09.2002 um 02:36 Uhr von TriPhoenix editiert. ]



  • Ich bin total beeindruckt, wo hast du denn diese Infos her über die Parallelisierung her, hab ich noch nie so genau verstanden...

    Die Messung verlief immer gleich: Die Bereichnung wurde mehrere tausend Male wiederholt und dann hab ich einfach den Wert der Uhr (Unterschiede zwischen Start und Ende des Progs - INT 1Ahex) ausgelesen.
    Die Algorithmen waren bei den meisten neuen Rechnern ziemlich gleich, nur der AMD 450 hatte bei Nr. 2 diesen perversen Vorsprung.
    Mein Duron 750 verhält sich hingegen wieder normal, obwohl er (wie auch der AMD 450) bei gefüllten Rechtecken die eigens optimierte Assemblerschleife gar nicht mehr sonderlich schneller erscheinen lässt, als wenn ich nur ne einzelne PutPixel-Routine habe und die von ner externen Schleife aus (mit Koordinaten übergabe) aufrufen lasse...
    is schon wirklich komisch, dass die Optimierungen jetzt schon fast langsamer sind als die "einfachen" Codes...
    Beim 386 war der Beschleunigungseffekt am höchsten, hat micht total gefreut, neue Prozessoren sind da irgend wie eine Entäuschung, da freut man sich endlich den ASM ein bisschen zu verstehen und dann sowas...
    Jedenfalls Danke für die INFO

    mfg ETNA



  • Original erstellt von etna:
    **Ich bin total beeindruckt, wo hast du denn diese Infos her über die Parallelisierung her, hab ich noch nie so genau verstanden...
    **

    AMD Athlon Processor Optimization Guide 🙂 (Und ne handvoll Leserei in diversen Seiten/Büchern ;))

    **
    Beim 386 war der Beschleunigungseffekt am höchsten, hat micht total gefreut, neue Prozessoren sind da irgend wie eine Entäuschung, da freut man sich endlich den ASM ein bisschen zu verstehen und dann sowas...
    **

    Tja...moderne Prozessoren sind leider so undurchsichtig für den Programmierer konstuiert worden, dass man wahrschheinlich mit garnichts mehr rechnen darf. Eine mehrstufige Pipeline, dazu ein paar merkwürdige Microcode-Umsetzungen (die Intel natürlich genauso wie AMD macht) und noch ein unkontrollierbarer Cache, da soll noch mal jemand sagen, ein Computer wäre deterministisch 😉

    [ Dieser Beitrag wurde am 03.09.2002 um 02:49 Uhr von TriPhoenix editiert. ]


Anmelden zum Antworten