ASM Anfänger bittet um erste Tipps

Anfängerfragen zum Programmieren mit PureBasic.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

ZeHa hat geschrieben:
es ist föllig egal
:shock:

Sowas ist mir aber nicht egal ;)
boah :shock: vuck, was für ein häßlicher flüchtigkeitsfehler...


@Didi
yo sorry, den absatz hab ich wohl überlesen...
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
PureLust
Beiträge: 1145
Registriert: 21.07.2005 00:02
Computerausstattung: Hab aktuell im Grunde nur noch 'nen Lenovo Yoga 2 Pro im Einsatz.
Wohnort: am schönen Niederrhein

Beitrag von PureLust »

DarkDragon hat geschrieben:... wenn PB intelligent wäre würde es auch Pow als Compiler-Inside-Makro halten und es ersetzen ...
Wäre aber wohl nur für einen zur Compilezeit feststehenden Exponenten von 2, vielleicht noch 3 oder 4 sinnig.
Bei einem variablen Exponenten fällt diese Optimierungmöglichkeit ja ehh flach.
[Dynamic-Dialogs] - komplexe dynamische GUIs einfach erstellen
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Damit hier wenigstens mal ´ne Zeile ASM-Code auftaucht folgendes Beispiel mit SSE3 (Achtung! Entsprechende CPU muß vorhanden sein!). Ich will damit zeigen, das mit einer halbwegs modernen CPU für so eine Aufgabe nicht seitenlanger Assembler-Code geschrieben werden muß, sondern schlappe 6 Zeilen ausreichen.

Code: Alles auswählen

;- Achtung! Benötigt eine CPU, die mit SSE3 etwas anfangen kann! 
Global PosX1.f=300
Global PosX2.f=400
Global PosY1.f=750
Global PosY2.f=900
Global Result1.f
Global Result2.f
Global Result3.f

Macro DistancePow() 
  Result1=Sqr(Pow(PosX1-PosX2,2)+Pow(PosY1-PosY2,2)) 
EndMacro

Macro DistanceMul() 
  Result2=Sqr(((PosX1-PosX2)*(PosX1-PosX2))+((PosY1-PosY2)*(PosY1-PosY2))) 
EndMacro

Macro DistanceSSE3()         ;benötigt SSE3
!movupd xmm0,dqword[v_PosX1]
!hsubps xmm0,xmm0
!mulps xmm0,xmm0
!haddps xmm0,xmm0
!sqrtss xmm0,xmm0
  ;!rsqrtss xmm0,xmm0        ;kann sqrtss ersetzen, wenn´s nicht so genau sein muß 
  ;!rcpss xmm0,xmm0 
!movss dword[v_Result3],xmm0
EndMacro

T1=GetTickCount_() 
For t=1 To 10000000 
  DistancePow() 
Next 
T1=GetTickCount_()-T1
Str1$="PB mit Potenzierung : "+StrF(Result1)+"    Zeit : "+Str(T1)+" ms"

T2=GetTickCount_() 
For t=1 To 10000000 
  DistanceMul() 
Next 
T2=GetTickCount_()-T2
Str2$="PB mit Multiplikation : "+StrF(Result2)+"    Zeit : "+Str(T2)+" ms"

T3=GetTickCount_() 
For t=1 To 10000000 
  DistanceSSE3() 
Next 
T3=GetTickCount_()-T3
Str3$="PB mit SSE3 :             "+StrF(Result3)+"    Zeit : "+Str(T3)+" ms"

MessageRequester("Distance",Str1$+#LFCR$+Str2$+#LFCR$+Str3$)
Gruß
Helle
Benutzeravatar
PureLust
Beiträge: 1145
Registriert: 21.07.2005 00:02
Computerausstattung: Hab aktuell im Grunde nur noch 'nen Lenovo Yoga 2 Pro im Einsatz.
Wohnort: am schönen Niederrhein

Beitrag von PureLust »

Helle hat geschrieben:... folgendes Beispiel mit SSE3 (Achtung! Entsprechende CPU muß vorhanden sein!).
Auha ... mein Athlon64 3200+ scheint wohl nicht dazu zu gehören. :(

Aber mal 'ne Frage zu Deinem ASM-Macro:
Wo ist denn da "PosX2" abgeblieben? :shock:
[Dynamic-Dialogs] - komplexe dynamische GUIs einfach erstellen
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Jaja, der gute alte Athlon64 3200+! Hab ich auch seit Ende 2003 genutzt, aber inzwischen durch einen Sempron mit SSE3 und geringerer Wärme-Entwicklung ersetzt (knapp 60 Euronen). Tat zwar in der Seele weh, aber der technische Fortschritt fordert halt Opfer...
Zum Code: Die erste Zeile liest ein Double-Quad-Word ein, also alle 4 Werte auf einmal. Wichtig ist dabei natürlich die "richtige" Reihenfolge der Variablen.

Gruß
Helle
Benutzeravatar
PureLust
Beiträge: 1145
Registriert: 21.07.2005 00:02
Computerausstattung: Hab aktuell im Grunde nur noch 'nen Lenovo Yoga 2 Pro im Einsatz.
Wohnort: am schönen Niederrhein

Beitrag von PureLust »

Helle hat geschrieben:Jaja, der gute alte Athlon64 3200+! Hab ich auch seit Ende 2003 genutzt, aber inzwischen durch einen Sempron mit SSE3 und geringerer Wärme-Entwicklung ersetzt (knapp 60 Euronen).
Jo ... der gute A64 3200+ ist zwar schon etwas in die "Jahre" gekommen aber für meinen alten Sockel-754 lohnt sich eine Aufrüstung nicht mehr wirklich. :roll:
Helle hat geschrieben:Zum Code: Die erste Zeile liest ein Double-Quad-Word ein, also alle 4 Werte auf einmal.
Ahh ... hatte mich schon über das "dqword[]" gewundert.
Helle hat geschrieben:Wichtig ist dabei natürlich die "richtige" Reihenfolge der Variablen.
Naja ... ist dann halt wirklich eine extrem spezielle Variante eines Distance()-Macros, da vermutlich ja nur sehr selten die X/Y-Werte von 2 zu vergleichenden Punkten direkt im Speicher hintereinander liegen werden.
Normalerweise würde man so ein Macro ja eher wie folgt gestallten:

Code: Alles auswählen

Macro Distance(x1,y2,x2,y2)
...
EndMacro
Für die Macros in nativem PureBasic würde das keinen Unterschied machen, aber bei Deinem Macro müsstest Du ja vermutlich dafür noch einiges ändern.

Machen denn diese speziellen SS3-Commandos eine solche Geschichte wirklich um soviel schneller als die "üblichen" ASM- oder MMX/SSE/SSE2-Befehle?
(Wie gesagt - kann Dein SSE3-Beispiel bei mir ja nicht testen.)

Gruß
PL.
[Dynamic-Dialogs] - komplexe dynamische GUIs einfach erstellen
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Zu den Variablen: PB sortiert benötigte Variablen einer Grösse alphabetisch, egal wo deklariert oder irgendwo benötigt. Die 4 Variablen Posxx in meinem Beispiel stehen im Speicher solange in dieser Reihenfolge hintereinander, wie nicht z.B. irgendwo eine 4-Byte-Variable
mit Namen PosX10 verwendet wird. Die würde sich an 2.Stelle einreihen.
Das Sortieren finde ich übrigens gar nicht gut, denn bei der Assembler-Programmierung ist es durchaus üblich, Variablen so anzulegen, daß mehrere mit einem Speicher-Zugriff bearbeitet werden können. FAsm u.a. belassen die Reihenfolge so, wie der Programmierer sie angelegt hat (in Assembler muß jede Variable explizit deklariert werden). Dies ist eine nicht zu unterschätzende Form der Optimierung! Man sitzt mitunter ganz schön lange, um die richtigen Reihenfolgen zu ermitteln.
Zu den Ausführungszeiten: Der Gewinn ist nicht soo berauschend (Sempron 3400+): PBMul=125ms zu SSE3=94ms. Wird das genaue Wurzelziehen durch die Reziprok-Befehle ersetzt, beträgt die Ausführungszeit nur noch 47ms. Für ein Spiel z.B. zur Bildschirm-Positions-Berechnung (Float wegen Winkel-Funktionen) würde diese Genauigkeit aber ausreichen.

Gruß
Helle
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

...und ich wiederhole noch mal diesen hinweis:
Kaeru Gaman hat geschrieben:2.) wenn man distanzen vergleichen will, kann man sich bei beiden das wurzelziehen sparen.
dann verwendet man gleich D2 zum vergleichen, der rest des algorithmus entfällt.
das ist ein nicht zu unterschätzender punkt.

auch wenn man eine bestimmte "meldedistanz" prüfen will

Code: Alles auswählen

If Sqr(DX*DX+DY*DY) < A
sollte man das lieber so machen:

Code: Alles auswählen

If DX*DX+DY*DY < A*A
wichtig ist halt, zu sehen, wo man das wie anwenden kann.

es bringt weniger, die 47ms ASM-Variante zu benutzen,
als gleich so zu konzipieren, dass man komplett auf die wurzel verzichtet.


[edit]
und nochmal zum Macro...
dieses

Code: Alles auswählen

Macro DistanceMul(PosX1,PosY1,PosX2,PosY1)
  Sqr(((PosX1-PosX2)*(PosX1-PosX2))+((PosY1-PosY2)*(PosY1-PosY2)))
EndMacro 
welches dann so aufgerufen wird

Code: Alles auswählen

Result2 = DistanceMul(PosX1,PosY1,PosX2,PosY1)
kann man auch ersetzen durch

Code: Alles auswählen

Macro DistanceMul(PosX1,PosY1,PosX2,PosY1,Result)
  DX = (PosX1-PosX2)
  DY = (PosY1-PosY2)
  Result = Sqr(DX*DX+DY*DY)
EndMacro 
welches dann so aufgerufen wird

Code: Alles auswählen

DistanceMul(PosX1,PosY1,PosX2,PosY1,Result)
natürlich ist man gewohnt, ergebnisse von funktionen mit "=" zuzuweisen,
aber in diesem fall kann man durch die übergabe des ziels als argument
die doppelte subtraktion sparen.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Scarabol
Beiträge: 1427
Registriert: 30.11.2005 21:00

Beitrag von Scarabol »

Bringt das wirklich was die Werte in Variablen (DX, DY) zu speichern?

Gruß
Scarabol
Abgeschlossen Projekte:
Schreibmaschine, Bildschirmlupe, Wings3DtoOgreMeshConverter
Watch: PureArea

PB-V: 4
WinXP
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

Scarabol hat geschrieben:Bringt das wirklich was die Werte in Variablen (DX, DY) zu speichern?
nur dann, wenn man in nachfolgenden berechnungen die berechnung von DX mehr als einmal aufrufen müsste.

also, in diesem beispiel bringt es etwas, DX vorab zu berechnen,
weil man sonst die subtraktion 2x durchführen müsste.

und das gilt für jede berechnung in jedem algorithmus.

wenn man in einem algorithmus ein ergebnis mehr als einmal braucht,
das on-the-fly berechnet werden müsste, bringt es einen performance-gewinn,
diese berechnung nur einmal auszuführen und ihr ergebnis zwischenzuspeichern.

das ist die erste faustregel der optimierung.

die zweite faustregel ist, eine komplexe funktion nur dann aufzurufen,
wenn sie wirklich benötigt wird, was ich oben mit

Code: Alles auswählen

If DX*DX+DY*DY < A*A
ausgeführt habe.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Antworten