If ohne Then
Übersicht

SirrusBetreff: If ohne Then |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Da bei If ein Then und der Then-Anweisungsteil optional sind wenn Else da ist, verwende ich gewöhnlich "If <Ausdruck> Else", wenn ich einen Ausdruck auf 0 testen will.
Ein Freund kannte das so gar nicht, meinte aber dass "If Not(<Ausdruck>) Then" schneller wäre, konnte allerdings nicht sagen warum. Darum habe ich ein kleines Testprogramm geschrieben: Code: [AUSKLAPPEN] Print "Teststart:"
Bei mir ist "Else" mit Blitz3D deutlich am schnellsten, bei BlitzPlus jedoch ist <Ausdruck>=0 etwas schneller. Not(<Ausdruck>) ist immer am langsamsten. (Jedoch Blitz3D ist mehr als 4x so schnell wie BlitzPlus)
t=MilliSecs() For n=1 To 10000000 If n-n Else A=1 Next t=MilliSecs()-t Print "If <Ausdruck> Else: "+t+" Millisekunden" t=MilliSecs() For n=1 To 10000000 If n-n=0 Then A=1 Next t=MilliSecs()-t Print "If <Ausdruck>=0 Then "+t+" Millisekunden" t=MilliSecs() For n=1 To 10000000 If Not(n-n) Then A=1 Next t=MilliSecs()-t Print "If Not(<Ausdruck>) Then "+t+" Millisekunden" WaitKey End Mich würde interessieren, ob das jetzt an meinem alten PC(Vista) liegt, bzw was bei euch am schnellsten ist. Kann ja auch mal jemand mit BlitzMax probieren. |
||
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ins blaue geraten:
bei not wird der Ausruck erstmal noch mit der boolschen Algebra verknüft, was etwas mehr Code erzeugen dürfte. Bei if else hingegen übersetzt der Compiler das direkt in eine Verzweigung. Warum nun B+ bei dem einen schneller ist und B3d bei dem anderen kann ich nur raten. Hab das Ganze unter BMax mal getestet, allerdings mit einer Milliarde iterationen statt 10 Millionen: Debug: If <Ausdruck> Else: 8453 Millisekunden If <Ausdruck>=0 Then 8752 Millisekunden If Not(<Ausdruck>) Then 8475 Millisekunden non-debug: If <Ausdruck> Else: 597 Millisekunden If <Ausdruck>=0 Then 549 Millisekunden If Not(<Ausdruck>) Then 552 Millisekunden Habe dann noch testweise die Ausdücke an andere Stelle des Tests geschoben, die Ergebnisse blieben identisch. Somit scheint unter Debugger else am schnellsten, in der nicht-Debugger-Version ist Ausdruck = 0 das flotteste. Wirklich viel nehmen die sich allerdings nicht, immerhin ist der Speed von Langsamstem zu Schnellstem gerade mal mit 3,5% (debugger) und knapp 8%(non-debug) erhöht. Das macht im Milliardenbereich mal ne drittel Sekunde aus, aber im normalen Programmablauf solte das nicht spürbar sein. |
||
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 |
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
Sodale, ich hab mir das auch mal angeschaut.
Meine Ergebnisse waren die Folgenden: Code: [AUSKLAPPEN] B+ Debug B+ B3D Debug B3D else: 4640 59.30 1847 59.72 =0 : 4818 58.91 1916 59.83 not : 4650 58.98 2359 58.90 Pro 10000000 Durchläufe. Die Nicht-Debug-Läufe haben 100 Mal mehr Durchläufe gehabt, deswegen runtergerechnet die zwei Nachkommastellen. Mein BMax wirft irgendwie gerade lauter Linkerfehler, deswegen hab ich das jetzt nicht reingenommen, aber BR hat es ja ganz gut analysiert. Das Erste, was auffällt, ist, dass (zumindest im Nicht-Debug-Modus) die Werte allesamt quasi gleich sind. Die Unterschiede zwischen dem besten und dem schlechtesten Wert sind 0.66% (B+), 1.37% (B3D) und 8.04% (BMax). Im klassischen Blitz ist hiermit die Debatte komplett zu Ende. Eine Optimierung, die rund 1% Performance bringt, ist es nicht mal wert angeschaut zu werden. Vor allem, weil die 1% Performance nur dann rauskommen, wenn man im gesamten Programm nichts anderes macht. Die rund 8% bei BMax sind schon ein wenig mehr, allerdings wird das auch wenig Leistung aus irgendeinem echten Programm holen. Das hier ist eine absolute Mikrooptimierung. In dem Beispiel von BladeRunner würde man pro einer Milliarde if-Vergleichen 45 Millisekunden gewinnen. Pro If-Vergleich macht das satte 0.045 Nanosekunden Einsparung. Das ist immer noch komplett witzlos. Viele Leute, die mit Optimierungen nicht viel am Hut haben, versuchen durch solche Tricks ein paar Nanosekunden rauszuquetschen, programmieren dabei aber auf Algorithmus-Level komplett ineffizient und verlieren in der Größenordnung von 10 Millisekunden. In diesem Fall, programmier so wie es dir leichter lesbar ist, und wie der Code besser verständlich ist. Der Performance-Gewinn, den du davon haben wirst, der ist absolut marginal. |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
![]() |
Thunder |
![]() Antworten mit Zitat ![]() |
---|---|---|
Interessante Beobachtung! Aber:
Vertauscht mal die Tests der Varianten. Ich bekomme beim Original (mit 1 Mrd. Durchläufe): Zitat: Teststart:
If <Ausdruck> Else: 161 Millisekunden If <Ausdruck>=0 Then 99 Millisekunden If Not(<Ausdruck>) Then 87 Millisekunden und mit Vertauschung: Zitat: Teststart:
If <Ausdruck>=0 Then 181 Millisekunden If Not(<Ausdruck>) Then 102 Millisekunden If <Ausdruck> Else: 73 Millisekunden BlitzMax generiert übrigens für alle 3 Loops äquivalenten Assembler-Code Code: [AUSKLAPPEN] 1. Loop:
1. Loop: jmp _21 _6: mov eax,edx sub eax,edx cmp eax,0 je _22 jmp _23 _22: _23: _4: add edx,1 _21: cmp edx,100000000 jle _6 2. Loop: jmp _25 _11: mov eax,edx sub eax,edx cmp eax,0 jne _26 _26: _9: add edx,1 _25: cmp edx,100000000 jle _11 3. Loop: jmp _27 _15: mov eax,edx sub eax,edx cmp eax,0 jne _28 _28: _13: add edx,1 _27: cmp edx,100000000 jle _15 Was man hier erkennt ist meiner Meinung nach der Branch Predictor in der CPU, der nach der 1. Loop seine predictions angepasst hat und deswegen die Pipeline der CPU bei den nächsten zwei Loops nicht so oft stallt. PS: ich testete nur mit BlitzMax (auf Linux) |
||
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit |
Sirrus |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Danke an alle
war auch interessant, eure Zeiten zu sehen, die sind bei mir nicht so viel schlechter, wie ich erwartet hatte besonders der Assembler-Code von Thunder ist interessant Ich kann also die Form verwenden, in der für mich mein Progamm am übersichtlichsten ist, der Code bleibt gleich ![]() |
||
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich hab probiert, den B+ und B3D-Code zu disassemblieren, hat aber mangels sinnvoller (sprich teurer) Disassembler-Software nicht so recht funktionieren.
Aber ich denke, auch dort ist der Code recht gleich. Solche Microbenchmarks sind aber gerade wegen Effekten, wie sie Thunder anspricht, recht wertlos. Verschiedene CPUs arbeiten den gleichen Code verschieden schnell ab. Manchmal auch der Compiler kann da gut dazwischenpfuschen. Ich hab mal so ein Benchmark gehabt, und war verblüfft, wie genial schnell der getestete Code gelaufen ist. Bis ich dann rausgefunden habe, dass der Compiler den getesteten Code für überflüssig befunden (er hat ja nichts Sinnvolles getan) und ihn wegoptimiert hat. Dadurch, das verschiedene CPUs anders arbeiten, ist, je nach CPU, die eine oder andere Variante mal schneller oder langsamer, gerade, wenn der Unterschied so marginal ist. Das mit der Branch Prediction von Thunder macht schon allein wegen der Einsparung Sinn. Die 0.045 Nanosekunden entsprechen etwa einem Zehnteltakt einer 2 GHz-CPU. Das ist also viel zu wenig, als was durch eine einzige Instruktion weniger eingespart werden kann. Eine andere Möglichkeit ist, das sich der Prozessor hochtaktet. Aktuelle CPUs laufen auf einem niedrigen Takt, wenn nicht viel los ist (zum Stromsparen) und takten sich dann automatisch hoch, wenn die CPU auf Volllast fährt. Das braucht allerdings ein wenig, kann also auch sein, dass die CPU dann erst nach dem halben ersten Durchlauf auf Volltakt fährt. |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group