Animations-/ Optimierungsfrage bei ImageWobbler

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

Flush

Betreff: Animations-/ Optimierungsfrage bei ImageWobbler

BeitragDo, Dez 22, 2016 19:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo Leute Very Happy ,

wie oben schon gesagt habe ich eine Frage zu Optimierung einer SinusAnimation eines Images.
Ich habe alle Werte die möglich waren in BlitzArrays geschrieben um in der Funktion drawWobblePic(k) so wenige Berechnungen wie möglich zu haben und soviel Geschwindigkeit herauszuholen wie es nur geht.
In der Funktion drawWobblePic(k) lasse ich durch SinusWerte die Höhen der einzelnen Spalten meines Images bestimmen um den WobbelEffekt zu bekommen.
Die Variable k nutze ich um die SinusBewegung in X-Richtung (Breite des Images) zu verschieben. Mit Mod 360 teste ich ob die Grenzen des Arrays erreicht sind und fange von vorn an falls dem so ist.
Ich hoffe meine Gedanken sind bis hierhin richtig Question Exclamation

In einem Thread habe ich gelesen dass man anstatt Mod 360 besser And $2FF verwenden sollte da Modulo eine Division darstellt die Zeit kostet. Das kann ich nachvollziehen.
Wenn ich aber den Code ausführe bekomme ich einen sehr seltsamen Effekt.

Könnt Ihr mir erklären was ich falsch mache Embarassed und wie es richtig geht Wink

Ich weiss wie AND funktioniert (Wahrheitstabelle) aber wieso $2FF das ist dez 767?!


Vielen Dank für Eure Mühe und Hilfe,
Flush

P.S.: Hier noch der Link zu dem erwähnten Thread 9. Beitrag von "Der Wnderer":
https://www.blitzforum.de/foru...inus+sinus



BlitzBasic: [AUSKLAPPEN]

Graphics 640, 480, 24, 2
SetBuffer BackBuffer()
Global bild = LoadImage ("King Tut.bmp")
Global bildBreite = ImageWidth (bild)
Global bildHoehe = ImageHeight (bild)

Global arr_Sin%[360]
Global x_arr%[384]
k = 0

For i= 0 To bildBreite
x_arr[i] = 100 + i
Next

For j = 0 To 359
sinus = Sin(j)*50
arr_Sin[j] = sinus
Next


While Not KeyHit(1)
Cls
drawWobblePic(k)
k = k + 1
Flip
Wend
WaitMouse()
End()

Function drawWobblePic(k)
For i=0 To bildBreite
DrawImageRect bild,x_arr[i],
100+arr_Sin[(i+k) And $2ff],
i,1,1,bildHoehe
Next
End Function



----------
Das benötigte Bild (muß in bmp konvertiert werden):

user posted image

Xeres

Moderator

BeitragDo, Dez 22, 2016 20:19
Antworten mit Zitat
Benutzer-Profile anzeigen
In dem 10 Jahre alten Thread da geht es um die schnelle Generierung einen sin/cos lookup tables - einfach so "AND $2ff" benutzen obwohl nirgendwo gezeigt wird, wie das funktionieren soll, wird nicht klappen.
Benutzt mod, fertig. Alles andere läuft unter premature optimization.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

Flush

BeitragDo, Dez 22, 2016 20:22
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi Xerxes,

schon klar dass nirgendwo gezeigt wird wie das AND $2FF funktioniert. Drum habe ich ja diesen Thread aufgemacht um zu verstehen wie das geht. Geschwindigkeit ist immer ein Grund für Optimierungsversuche. Das interessiert vielleicht alle!?


Viele Grüße,
Flush

BladeRunner

Moderator

BeitragDo, Dez 22, 2016 22:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Des weiteren würde ich eine Scala von Zweierpotenzen für den LUT wählen, und statt MOD (erfordert eine Division!) ein bitweises AND nehmen, also etwa sowas wie

sinus = sinTable(alpha AND $2FF)

Wenn der Table 1024 einträge hat.

Hier liegt der Teufel im Detail. 1024 Einträge wären $400, also von $000-$3ff, da hat sich ienfach wer vertippt.
Der von der Wanderer Beschriebene Fall geht also davon aus, dass eine Tabelle mit 1024 Einträgen vorliegt und mittels des AND blendet er einfach drüberliegende Bit aus um Geschwindigkeit zu gewinnen.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Thunder

BeitragDo, Dez 22, 2016 22:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn dich die paar Takte, die du dadurch gewinnst (falls du sie gewinnst - siehe zB Out of Order execution), interessieren, dann solltest du nicht in BlitzBasic programmmieren.
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit

BladeRunner

Moderator

BeitragDo, Dez 22, 2016 22:55
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, hier kommen wir ja in einen Bereich wo unter Umständen mehrere Hunderttausend Pixel betrachtet werden müssen - da mag das sogar wirklich ienen Unterschied machen. Und selbst wenn nicht hat man was gelernt Smile
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Flush

BeitragFr, Dez 23, 2016 18:41
Antworten mit Zitat
Benutzer-Profile anzeigen
Ahhhhh! Exclamation Idea
Danke, die Infos sind schon mal sehr hilfreich.
Die paar Takte interessieren in jedem Fall in eigentlich jeder Sprache!
Gelernt hab ich auch was Cool , falls ich noch Fragen hab melde ich mich nochmal!


Vilen Dank für Eure Hilfe und Mühe,
Flush Very Happy

DAK

BeitragSo, Jan 01, 2017 22:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Bei solchen Mikrooptimierungen musst du aufpassen, da sie eventuell nichts bringen oder sogar schaden können.

Im vorliegenden Fall wirst du bei den meisten modernen Prozessoren gar keinen Vorteil messen. Divisionen werden heutzutage auf den meisten Prozessoren in Hardware gemacht und brauchen gleich lang wie eine Und-Verknüpfung.

Bei solchen Mikrooptimierungen lässt sich auf Grund der vielen Abstraktionsschichten nicht sagen, ob und wie viel Leistung sie bringen und die Antwort unterscheidet sich oft von Prozessor zu Prozessor. Dein BB-Code wird zu C-Code kompiliert, der dann zu Assembler kompiliert wird. Der Assemblercode wird zu Maschinencode, in diesem Fall x86er-Maschinencode. Der wird dann vom Microcode des Prozessors interpretiert, der das dann in Hardware-Befehle umwandelt.
Dabei spielen Pipelining, Caching, (eventuell lernende) Branch Prediction und je nach Prozessor Out-of-Order-Execution, Hyperthreading oder Superskalarität (nur um ein paar Dinge zu nennen) eine Rolle. Je nach Prozessor funktionieren alle diese einzelnen Elemente anders. Dabei können sich selbst zwei i5-Prozessoren der gleichen Generation (aber unterschiedliche Modelle) drastisch unterscheiden. Viele dieser Abstraktionsschichten versuchen heutzutage intelligent die üblichen Performance-Fallen, die Programmierer einbauen, automatisch zu korrigieren.

Mit so kleinen Mikrooptimierereien machst du mit Glück den Code auf deiner Maschine marginal schneller, aber das sagt nichts darüber aus, wie der Code bei wem anderen rennt. Eventuell ist der Code dann sogar langsamer. Sowas funktioniert gut auf dummen Microcontrollern (wie den ATMega- oder ATTiny-Reihen) oder sehr alten Prozessoren, wie dem 6510er, der im C64 verbaut wurde. Als Faustregel kann man sagen, dass (fast) alles, was 32-bit hat, besser optimiert als man selbst.

Und selbst wenn deine Optimierung bei deinem Computer greift, ist die Optimierung meist nichts wert.

Sagen wir mal, eine Division braucht hypothetisch 4 Takte (nicht das es so ist, nur als Beispiel) und die Und-Verknüpfung braucht eine.
Der Funktionsaufruf von DrawWobblePic() braucht rund 10 Takte. Die Schleife hochzählen braucht rund 2 Takte pro Schleifendurchlauf. Der Funktionsaufruf von DrawImageRect() wird rund 20-30 Takte brauchen (viele Parameter kosten mehr). Dazu hat der intern eine Schleife, die für jedes Pixel in der Spalte noch mal rund 5 Takte braucht.

Also, bei einem Bild mit 10x20 Pixeln hast du mit der Division rund 10+(2+4+25+5*20)*10 = 1320 Takte. Bei der Version mit der Und-Verknüpfung sind es dann 10+(2+1+25+5*20) = 1290 Takte. Das ist eine Verbesserung von rund 2%. Bei einem größeren Bild, wie deinem Beispielbild mit 384x271 schaut die Rechnung noch mal deutlich schlechter aus. Hier hast du 10+(2+4+25+5*271)*384 = 532 234 Takte vs 10+(2+1+25+5*271)*384 = 531 234. Hier ergibt es nur mehr eine Verbesserung von 0.2%. Je größer das Bild, desto verschwindend geringer die Vorteile.

Auf der Anderen Seite hast du für diese marginale Optimierung Code verwendet, den du nicht verstanden hast (immer sehr gefährlich) und der noch dazu falsch war (Tippfehler mit $2FF statt $3FF). Das Debuggen und den Post erstellen hat dich sicher mehr Zeit gebraucht, als du jemals durch diese Optimierung einsparen kannst.

Worum es mir mit diesem Post geht, ist, zu veranschaulichen, warum solche Mikrooptimierungen seit dem 90ern nichts mehr bringen und eher gefährlich sind, als sonst was. Ich habe schon viele Stunden nutzlos verschwendet, indem ich Bugs suchen hab müssen, die irgendwer im Zuge von absolut wertlosen Mikrooptimierungen eingebaut hat.

Optimieren bringt oft sehr viel, aber meist nur, wenn man den gesamten Algoritmus optimiert und fast nie, wenn man einzelne Takte irgendwo rauskitzelt. Sowas wie die Sinuswerte cachen, das bringt was. Aber eine Division einsparen üblicherweise absolut wertlos.
Gewinner der 6. und der 68. BlitzCodeCompo

hectic

Sieger des IS Talentwettbewerb 2006

BeitragDi, Jan 03, 2017 16:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich würde DAK gerne einen Daumen nach oben geben, finde hier aber leider keinen. Sehr schön erklärt.
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D

DAK

BeitragDi, Jan 03, 2017 17:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke Hectic. Da das Thema doch sehr oft aufkommt, hab ich mir überlegt, einen Referenzpost zu erstellen, der dann bei solchen Fragen verlinkt werden kann.
Gewinner der 6. und der 68. BlitzCodeCompo

Flush

BeitragSa, Jan 07, 2017 16:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi,

vielen Dank DAK Very Happy !
Du hast vollkommen Recht mit Deinem Statement!
Die Idee mit dem Referenzpost halte ich für sehr gut

Gruß,
Flush

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group