Hallo Besucher, der Thread wurde 12k mal aufgerufen und enthält 70 Antworten

letzter Beitrag von detlef am

BASIC-Code beschleunigen/optimieren

  • Das hat doch sicher Bill Gates höchstpersönlich verbuggt. Da bin ich ja froh, dass er an Windows nicht selbst mitentwickelt hat...

    ... was Windows aber auch nicht unbedingt bugfreier macht :bgdev

  • Das kann aber auch zu unerwarteten Ergebnissen führen, wenn ein Ausdruck mit Integer-Zahlen daher kommt, aber vom Programmierer eigentlich ein Fließkommaergebnis erwartet wird: wenn PRINT 1/2 auf einmal 0 statt 0.5 ausdruckt, ist das Stirnrunzeln garantiert.

    Deswegen hab ich auch ausdrücklich von solchen Ausdrücken gesprochen, wo etwa der Ergebnis explizit bekannt ist (also etwa bei A%=...) und dort dann etwa strikt in Integer-Arithmetik auswertet. Das wäre m.E. ja das einfachste. Typlose Ausdrücke, also solche, die im Vorhinein nichts über den Typ preisgeben bleiben beim "mächtigeren" Float-Typ, solange man nicht Casting-Operatoren einführt. Und klar, das macht natürlich die Programmierung nicht "einfacher", wenn man als Entwickler etwaige Nebenwirkungen und Randbedingungen hinsichtlich Float- und Integerarithmetik berücksichtigen muss.
    So gesehen wird ja in BASIC V2 ein Programmierer von all dem Kopfzerbrechen, den C-Programmier oder so mit dem Typsystem hat, entbunden - zum Leid der Speed-Freaks, die vielleicht gerne mehr Kontrolle darüber gehabt hätten. :D

  • Naja, warum gleich so extrem: Divison sowie exp, log, sqrt, trig. Funktionen etc. immer automatisch nach Fließkomma umwandeln und der Rest wenn es geht Integer ginge auch.

    Also die Division ist auch im Integer-Bereich sinnvoll und muss nicht zwangsläufig nur zu Floats führen. Wäre lästig bei grafischen Berechnungen, wo eine Skalierungsrechnung von Floats ausgebremst wird. Problematischer sähe ich den 16-Bit-Wertebereich, der da schnell zu klein werden könnte.
    Wie gesagt, mein minimalistischer Ansatz wäre gewesen, die Integer-Arithmetik zusätzlich, parallel zu den Floats (wie dies gewissermaßen auch bei Strings der Fall ist) eingebettet zu sehen - keinen hochtrabenden allumfassenden, alle Informatikerherzen höher schlagenden Ansatz, der sozusagen alles erschlagen können soll.


    Aber wie Mike schon ausgeführt hat, solche Sachen wären nur nützlich, wenn sie billig zu haben sind. Der Aufwand steht nicht dafür, wenn es Sinnvolleres im ROM unterzubringen gilt. ;)

  • Deswegen hab ich auch ausdrücklich von solchen Ausdrücken gesprochen, wo etwa der Ergebnis explizit bekannt ist (also etwa bei A%=...) und dort dann etwa strikt in Integer-Arithmetik auswertet. Das wäre m.E. ja das einfachste. Typlose Ausdrücke, also solche, die im Vorhinein nichts über den Typ preisgeben bleiben beim "mächtigeren" Float-Typ, solange man nicht Casting-Operatoren einführt. Und klar, das macht natürlich die Programmierung nicht "einfacher", wenn man als Entwickler etwaige Nebenwirkungen und Randbedingungen hinsichtlich Float- und Integerarithmetik berücksichtigen muss.So gesehen wird ja in BASIC V2 ein Programmierer von all dem Kopfzerbrechen, den C-Programmier oder so mit dem Typsystem hat, entbunden - zum Leid der Speed-Freaks, die vielleicht gerne mehr Kontrolle darüber gehabt hätten. :D

    "so gesehen" :gruebel ?
    Nix "so gesehen": Vergesst bitte nicht für was das Akronym BASIC steht und für wen die Sprache adressiert war/ist.
    Es ist so auch richtig, dass man sich als Beginner nicht viel Kopfzerbrechen machen *muss* mit BASIC. Speed ist da mal nicht so wichtig. Höchstens Speed beim Lernen und Verstehen der Sprache.


    Die "Freiheiten" (=Probleme) in C/C++ mit der ganzen Typsystem und Memoryhandling zeigt ja genau, dass so eine Sprache in falschen Händen einfach nicht geeignet ist, als Anfängersprache zu dienen. Ist nicht von ungefähr, dass nach dem Hype in 90ern mit C++ für Schulen an das unbedarfte Publikum eher Java und andere, zum Lernen besser geeignete Programmiersprachen gewählt wurden. Und ich rede jetzt wirklich nicht von einem IT Studiengang, wo man dort vielleicht auch noch C++ nehmen kann.

  • "so gesehen" ?
    Nix "so gesehen": Vergesst bitte nicht für was das Akronym BASIC steht und für wen die Sprache adressiert war/ist.
    Es ist so auch richtig, dass man sich als Beginner nicht viel Kopfzerbrechen machen *muss* mit BASIC. Speed ist da mal nicht so wichtig. Höchstens Speed beim Lernen und Verstehen der Sprache.

    Bitte nicht falsch verstehen oder jetzt jeden Phrase auf die Goldwaage legen, aber auf das wollte ich ja hinaus, dass hier allzu arge Finessen in der Sprache hier nicht "förderlich" ist. Nur gebe ich auch zu bedenken, das das eingebaute BASIC nicht nur ein BASIC an sich ist, sondern quasi die Shell, die interaktive Standardumgebung und auch die Basis für jede Form des "Scriptings" war (weil es einfach im ROM "da" war) und ist und damit nicht nur "Anfänger" konfrontiert sind. Erstens sind und bleiben Leute, die sich mit BASIC beschäftigen nicht ewig "Anfänger" (ok, es gibt und gab natürlich auch solche, die nie irgendetwas Programmiert haben) und zweitens, dass die Sprache einem Anfänger einen leichten Zugang gewährt, heißt noch lange nicht, dass sie nichts mehr für Fortgeschrittene oder Profis zu bieten hat (oder haben darf). Das möchte ich vielleicht auch noch mal klarstellen. Und dass der Bedarf da war oder ist, kann man rückblickend ja anhand der auch anspruchsvollen Software unter BASIC sehen. Oder auch, dass es bis heute Leute gibt, die dem naheliegenden, aber leider falschen Glauben erliegen, dass die Existenz von Integer-Variablen auch Integer-Arithmetik impliziert. ;)
    Ich hätte mir, hätte es den Platz im ROM gegeben hätte Integer-Arithmetik bzw. Integer-Zuweisungen mit Integer-Auswertung gewünscht. Aber wie Mike schon gesagt hat, da hätte es mehr gebraucht, um einen signifikanten Geschwindigkeitsvorteil in allen Lagen herauszuholen (also da hätte man Variablenorganisation, Sprünge, etc. auch investieren müssen). Sämtlich BASIC-Neuauflagen oder sonstige Erweiterungen, haben allerdings stets in immer mächtigere Befehle investiert, um die Schmerzen der etwaig fehlenden Interger-Arithmetik und interpreter-bedingten Langsamkeit zu lindern. :D

  • Ich poste dies mal hier hinein, obwohl es BASIC 3.5 ist.


    Folgendes Problem (oder eigentlich keins) bzw. gibt es hier Optimierungsmöglichkeiten?

    Code
    1. 18 ifv<xthenifma(v+m,w)<6thencn=.:char,a+v,b+w,t$(k):v=v+m:char,a+v,b+w,c$(cn+xo):return
    2. 19 ifw<ythenifma(v,w+m)<6thencn=9:char,a+v,b+w,t$(k):w=w+m:char,a+v,b+w,c$(cn+xo):return
    3. 20 ifv>xthenifma(v-m,w)<6thencn=3:char,a+v,b+w,t$(k):v=v-m:char,a+v,b+w,c$(cn+xo):return
    4. 21 ifw>ythenifma(v,w-m)<6thencn=6:char,a+v,b+w,t$(k):w=w-m:char,a+v,b+w,c$(cn+xo):return

    IF...THEN ist langsam! Daher habe ich z.B. die Spielersteuerung in ON...GOSUB ausgelagert, was einen herheblichen Geschwindigkeitsboost bringt. Ich möchte dies gern auch bei der Steuerung des Computers haben. Gibt es da die Möglichkeit mit ON...GOSUB Waagrecht und Senkrecht in eine Zeile zu packen?

  • In eine Zeile fällt mir nix ein.


    Du könntest es aber wohl mit wahr/unwahr etwas beschleunigen:


    18 on (v<x and -ma(v+m,w)<6) goto xx
    etc.


    xx cn=.:char, etc.

  • Ich hab's vorhin nur (abgespeckt) in einer 100er-Schleife getestet: Da waren es so 52:70. Probier doch mal.


    Edit:


    Wenn man das noch aufsplittet z. B. auf:


    on -(v<x) goto xx
    on -(w<y) goto xy
    etc.


    xx on -(m<6) goto yy
    etc.


    bringt das anscheinend richtig was. Die nicht-zutreffenden Vergleiche werden damit ja recht rasant abgearbeitet.

  • Das kann ich mir nicht als schneller vorstellen. Hier wird genau das gemacht, was die obige IF-THEN-Kaskadierung vermeidet, nämlich dass v<x und der ma()-Zugriff mit Vergleich immer ausgewertet werden müssen.
    Blöd ist freilich die Subtraktion/Addition beim Array-Zugriff ma() für die Indizes.
    Die Konstante 6 in eine Variable zu geben ist - wenn überhaupt - auch nur dann schneller, wenn sie vielleicht als einer der ersten Variablen deklariert ist.


    Auch ein on-goto-Ansatz, der die Zeilen zusammenfasst wie sowas


    160 on 2+sgn(v-x) goto 180,170,200
    170 on 2+sgn(w-y) goto 190,171,210


    171 return
    180 ifma(v+m,w)<6thencn=.:char,a+v,b+w,t$(k):v=v+m:char,a+v,b+w,c$(cn+xo):return
    181 return
    190 ifma(v,w+m)<6thencn=9:char,a+v,b+w,t$(k):w=w+m:char,a+v,b+w,c$(cn+xo):return
    191 return
    200 ifma(v-m,w)<6thencn=3:char,a+v,b+w,t$(k):v=v-m:char,a+v,b+w,c$(cn+xo):return
    201 return
    210 ifma(v,w-m)<6thencn=6:char,a+v,b+w,t$(k):w=w-m:char,a+v,b+w,c$(cn+xo):return


    brauchen wegen der Addition und Subtraktion länger als 2 Vergleiche im IF.
    Auch alle 4 IF in ein ON-GOTO gegossen, in etwas sowas


    160 onv<xand1orw<yand2 ... goto ...


    braucht in der Auswertung (auch um +/- oder * zu vermeiden) braucht leider länger als 4 vergleichende IFs, weil auch das Parsing, obwohl in einer Zeile länger dauert ...

  • on-(v<x)goto ist langsamer als ifv<xthen...

  • Was da Zeit kostet sind die Array-Zugrife. Zahl-Konstanten sind auch eher langsam, das dürfte hier aber wenig ausmachen. Falls BASIC 3.5 echte Integer-Arithmetik kann wäre damit natürlich noch einiges rauszuholen- ich hab da aber grad den Überblick verloren, ob CBM-Basic das jemals konnte, und wenn ja in welchen Versionen.

  • Das kann ich mir nicht als schneller vorstellen.

    Getestet und für gut befunden.


    on-(v<x)goto ist langsamer als ifv<xthen...

    Da gebe ich dir recht.



    Und wie sieht dein (besserer) Lösungsvorschlag nun aus :search: ?

  • Was da Zeit kostet sind die Array-Zugrife. Zahl-Konstanten sind auch eher langsam, das dürfte hier aber wenig ausmachen. Falls BASIC 3.5 echte Integer-Arithmetik kann wäre damit natürlich noch einiges rauszuholen- ich hab da aber grad den Überblick verloren, ob CBM-Basic das jemals konnte, und wenn ja in welchen Versionen.

    Array-Zugrif an sich würde ich nicht so verteufeln. Man muss das schon in Summe sehen:

    • Array-Variable linear in Array-Bereich suchen (geht relativ schnell, wenn nicht viele Arrays vorhanden sind).
    • Ausdrücke der Indizis auswerten: Dafür die Variablen suchen (auch linear in der sicher größeren Liste der einfachen Variablen) und auch noch Floatingpoint-Rechnen (auch wenn es nur eine Subtraktion ist).
    • Array-Elementposition berechnen: Das ist Integer-Arithmetik, geht also recht flott. Aber jede Dimension ist eine Multiplikation mehr.
    • Kostantenumwandlung in Floatingpoint. Ist umso langwieriger, je mehr Ziffern eine Konstante hat. Bei einer Ziffer ist aber mit einer Variablen statt dessen nicht viel rauszuhholen (wenn überhaupt).


    CBM-BASIC hat nie direkt Integer-Arithmetik gehabt, in keiner mir bekannten Version.
    Auch dann, ist dann noch immer das Parsing, die lineare Suchen von Variablen usw. übrig. Das lässt die Laufzeit auch bei einer Integer-Arithmetik nicht so weit schrumpfen, dass dann plötzlich ein Vielfaches der Geschwindigkeit zu erwarten wäre.

  • Ich hab ja nur mal ein Brainstorming dazu gemacht. Da kommen auch die Sachen vor, die nicht gehen.
    In diesem Fall ist die IF-Kaskade und -Reihe schon optimal. Man kann nur bei Variablen (früh definieren) und Vermeidung von Konstanten (durch Vars ersetzen) bisschen herausholen.
    Es kommt dann drauf, wenn man ein Profiling machen würde, wie häufig die erste IF-Abfrage überwunden wird und ob dann dahinter zu optimieren sich auszahlen könnte.

  • Es kommt dann drauf, wenn man ein Profiling machen würde, wie häufig die erste IF-Abfrage überwunden wird und ob dann dahinter zu optimieren sich auszahlen könnte.

    Mein Bauchgefühl/Gedanke war halt auch, die nicht-zutreffenden möglichst schnell zu verwerfen. Ich hatte auch das BASIC 3.5 ganz verdrängt. Keine Ahnung, wie sich das überhaupt geschwindigkeitstechnisch verhält.


    Ich hab ja nur mal ein Brainstorming dazu gemacht.

    Dito. Hätte ja was bei raus kommen können :) .


    Ergo: "Kacke, geht nicht besser?" :poop:?(

  • Hatte ich bereits mehrfach getestet und es lief definitiv langsamer als mit IF...THEN. Diese Variante benutz ich aber für die Steuerung per Tastatur/Joystick ;).



    Ich empfehle da eher den Basic Boss Compiler. Der kann wesentlich mehr als der Austro Compiler, vor allem wenn man die Anleitung gelesen hat. :)

    Schade, daß es diesen Compiler nicht für C264er also BASIC 3.5 gibt. ;)


    Kurze Info.: es geht hier um mein Projekt Balloon Breaker. Ich hab nun irre viel Geschwindigkeit herausgeholt. Aber, ich will noch ein wenig mehr haben; deshalb meine obrige Frage.
    Wenn ich eine Beta veröffentliche, kann ja der eine oder andere drüber schauen und mir ggf. Tipps zur Optimierung (der Spielschleife) geben, bütte ^^.


    Danke auch für eure Ideen/Antworten! :)


    Nächste Frage bezüglich dieses Themas:
    Ich benutz ja Arrays für die Kollisionsabfrage. Wäre PEEK, also das Auslesen des Bildschirmspeichers, da nicht schneller?
    Ich vermute mal, NEIN oder?

  • also ich wuerde vermuten das peek da etwas schneller waere, da ja (meinem verstaendniss nach) der ganze adress berechnugs overhead
    ,der beim zugriff auf arrays entsteht, entfeallt. genau weis ich das aber nich :/

    Hängt auch vom Umfeld ab. Wenn im PEEK-Parameter gerechnet werden muss, kann der Vorteil von PEEK schnell dahin sein.
    PEEK(A-U)
    dürfte aber schneller als etwa ein
    AR(X-U,Y)
    sein. In beiden Fällen muss im Parameter gerechnet werden, hebt sich also auf. Ab im 2-dimensionalen Array muss (wenn auch nur in Integer) multipliziert werden, um das Array-Element zu finden. Bei PEEK fällt die Konvertierung des gelesenen Byte-Wertes in einen Floating-Pointzahl nicht mehr ins Gewicht - kostet ja nicht wirklich viel im Vergleich zu Array-Elementberechnung.
    Dass PEEK schneller ist, hat sich auch bei Grafikprogrammen (3D-Hut voriges Jahr im Forum) gezeigt, dass die Hires-Bitmap in ein Integer-Array gelegt, wo die Elemente die Bitmap adressieren keine Verbesserung brachte (auch wenn die Variante elegant wirkt und gewieft ist). Da mit dem Drumherum für die Positionsberechnung, beide Varianten etwa die gleiche Rechnerei nötig hatten, standen PEEK und Array-Zugriff dann auch nahezu direkt gegenüber und PEEK hatte die Nase vorn.