geschwindigkeit bei if-abfrage(n)

  • VB6

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von Fremder.

    geschwindigkeit bei if-abfrage(n)

    hallo,

    ich würde gerne meinen code etwas auf geschwindigkeit trimmen und habe folgende situation:


    > hauptroutine (wird ebenso ca. 4096 x durchlaufen ...

    K = array mit ca. 24000 datensätzen oder mehr ...

    Visual Basic-Quellcode

    1. for i = 1 to 24000 (oder mehr)
    2. Zustand1 = K(i,1)
    3. Zustand2 = K(i,2)
    4. Zustand3 = K(i,3)
    5. if Zustand1 = 1 and Zustand2 = 63 then TuDies = 3
    6. ' diese if-abfrage füge ich ca. 100 x in die for i schleife ein ....
    7. ' dadurch wird die geschwindigkeit arg reduziert ....
    8. next i


    wäre es da nicht schneller ... eine funktion zu erstellen
    die widerrum eine liste abfragt und dann eben TuDies
    auf 1 bis (z.B) 12 setzt !?

    hat da jemand nen guten "Tipp" ? .-)

    vielen dank ..


    Edit by Mad Andy:
    VB-Tag eingefügt.

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „Mad Andy“ ()

    :) na ja, es ist ja auch eine datenbank ...

    der ansatz ist halt der ...

    4096 x 24000 x ... = 1 TEST .. wobei ich eben

    Zustand1 = 1 to 64 "möglichkeiten"
    mit
    Zustand2 = 1 to 64 "möglichkeiten"
    mit
    Zustand3 = 1 to 64 "möglichkeiten"

    kombiniere ... was dann rechnerisch schon arg an
    meiner rechenzeit zerrt :(

    ich hab da noch gut in "errinerung" ...

    ich such mal unter "listen" :-9

    dennoch danke
    Im Bereich Datenbank-Programmierung gehts um Fragen, die sich direkt mit Datenbanken beschäftigen, du willst eine Schleife optimieren.
    Ich verschiebe mal eben das Topic.

    Das einzige, das ich dir mit auf den Weg für dein Problem geben kann ist, dass du einfach solang rumbasteln kannst, wie dus für nötig hältst und immer die benötigte Zeit misst.


    so long..
    Andy

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Mad Andy“ ()

    Konditionale Abfragen sind generell kostspielig, was
    daran liegt, dass der Computer im Code herumspringen
    muss. Ein Funktionsaufruf ist generell sogar noch kostspieliger,
    weil der Computer nicht nur im Code herumspringen,
    sondern auch noch auf dem Stack Daten ablegen muss.

    Die Frage ist: Sind die Zustände und die Anweisung
    TuDies wirklich numerische Werte ? Wenn ja: Dann
    solltest du dir ein System ausdenken, mit dem du
    den Wert von TuDies anhand des Zustandes berechnen
    kannst. Das würde deinen Code sicherlich signifikant
    beschleunigen.

    RE: geschwindigkeit bei if-abfrage(n)

    Original von Fremder
    ich würde gerne meinen code etwas auf geschwindigkeit trimmen und habe folgende situation:

    if Zustand1 = 1 and Zustand2 = 63 then TuDies = 3


    Das geht schneller, wenn Du 2 IF-Abfragen reinbaust, weil dann die zweite nur abgefragt wird, wenn die erste bereits erfüllt ist. also etwa so:

    Visual Basic-Quellcode

    1. if Zustand1 = 1 then
    2. if Zustand2 = 63 then ...

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „zippozappo“ ()

    jo .. TESTEN is halt doch immer (noch) die beste sache :)

    die abfrage "if Zustand1 = x AND Zustand2 = y ... " bedingt doch
    dass Zustand2 NUR abgefragt wird .. wenn Zustand1 der bedingung
    entspricht ! ?

    oder wäre da so:

    IF Zustand1 = 1 then
    IF Zustand2 = 63 then TuDies = 3
    endif

    "schneller"

    ein guter LINK .. welcher die geschwindigkeitsoptimierung sehr
    gut veranschaulicht ist:

    activevb.de/tutorials/tut_primzahlen/primzahlen.html
    - aus ~600 MS wurden ~ 3.3 MS .-)


    wird ja heutzutage WIRKLICH arg unterschätzt ... bzw. vergessen
    - dank der superschnellen hardware :) -
    Original von Fremder
    die abfrage "if Zustand1 = x AND Zustand2 = y ... " bedingt doch
    dass Zustand2 NUR abgefragt wird .. wenn Zustand1 der bedingung
    entspricht ! ?


    :)
    Hab mal ein kleines Testprogramm geschrieben:

    Visual Basic-Quellcode

    1. startzeit! = Timer
    2. For i = 1 To 10000
    3. For j = 1 To 10000
    4. If i Mod 10 = 0 Then
    5. If j Mod 10 = 0 Then
    6. 'do nothing
    7. End If
    8. End If
    9. Next
    10. Next
    11. Me.Caption = Timer - startzeit!


    In der IDE und ohne irgendwelche Deklarationen braucht das so 13,2 Sekunden. Änder ich das doppelte IF zu einem AND brauchts 30,7 Sekunden. Noch Fragen? :)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „zippozappo“ ()

    Hey Fremder,

    über Geschwindigkeitsoptimierug wurden ja schon ganze Bücher geschrieben und alles was hier bisher gepostet wurde, sind gute Tipps, wobei ich das, was Unknown schrieb, für das Wichtigste halte, denn ein Programm ist nur so gut (schnell), wie die Intelligenz (Effizienz) seiner Algorithmen. Es wäre also hilfreich zu wissen, welche Zustände (Werte) Deine 3 Zustands-Variablen annehmen und welche 'Aktionen' (Werte von TuDies) daraus entstehen können.

    Andererseits darfst Du nicht vergessen, dass Deine Schleifen ca. 100.000.000 ! mal durchlaufen werden und da kann man auch einiges mit Codeoptimierung erreichen. Laß Dir mal Folgendes (an Deinem Beispiel) durch den Kopf gehen:

    Visual Basic-Quellcode

    1. ' ===== ca. 37 Sec.
    2. For jCt = 1 To 4096
    3. For iCt = 1 To 24000
    4. ' ===== ca. 0,5 Sec ohne die nächsten 3 Zeilen!
    5. Zustand1 = K(iCt, 1)
    6. Zustand2 = K(iCt, 2)
    7. Zustand3 = K(iCt, 3)
    8. Next iCt
    9. Next jCt

    Also nur für die Tatsache, dass Du die Werte in andere Variablen schaufelst!?
    mfG DHB

    Ich meine:
    :P Es sollten nur ernstzunehmende Beiträge eingestellt werden!
    :( Beiträge, die nur deren Anzahl in die Höhe treiben sollen, stehlen Lesern deren Zeit und schenken nur Frust.
    ;) Wenn ein Autor sein Thema für erledigt hält, sollte er dies kurz als letzten Eintrag vermerken.
    8) Leser wüssten dann, dass hier weitere Beiträge nicht mehr sinnvoll sind.
    mich würde ja als "laienhafter VBnutzer" interessieren ... ob die folgende LOGIK sinn macht:

    als beispiel gerne dein CODE ...

    Original von DHB

    Visual Basic-Quellcode

    1. ' ===== ca. 37 Sec.
    2. For jCt = 1 To 4096
    3. For iCt = 1 To 24000
    4. ' ===== ca. 0,5 Sec ohne die nächsten 3 Zeilen!
    5. Zustand1 = K(iCt, 1)
    6. Zustand2 = K(iCt, 2)
    7. Zustand3 = K(iCt, 3)
    8. Next iCt
    9. Next jCt



    in VB dauert dies nun ca. 30 sec.
    in C "denke ich mal" ca. 8 bis 12 sec. ! ?
    in ASSEMBLER wohl nur noch 3 bis 5 sec. ! ?

    wenn ich nun VB mit C bzw. ASS kombinieren würde
    geht der Geschwindigkeitsvorteil denn in die knie ?


    Visual Basic-Quellcode

    1. For jCt = 1 To 4096
    2. '(hier die 24000 oder mehr schleifen)
    3. call C_programm (iCt)
    4. Zustand1 = ausCA
    5. Zustand2 = ausCB
    6. Zustand3 = ausCC
    7. Next jCt



    wäre dies denkbar und geschwindigkeitsmässig sinnvoll ?
    Hey Fremder,

    um es direkt zu sagen: "Es macht mit Sicherheit keinen Sinn! Edit: Es sei denn, Du legst die kompletten Schleifen mit ins UP, womit dann auch das Hin- und Herspringen entfallen würde". Denke daran, das Du ca. 100000000 mal in eine 'Sub' springst, hierfür brauchst Du schon viel Zeit und die Berechnungen dort ebenfalls noch einmal. Probier es doch aus, indem Du einfach in eine 'leere Sub' rein und wieder raus springst und die dafür benötigte Zeit im Verhältnis ohne Sprung stoppst!

    Hast Du auf meine oben aufgeführten Werte geschaut? Nur für das Umschaufeln von Werten verlängert sich die Zeit schon immens! 100000000 mal ist auch für einen Rechner (wenn er was tun soll!) eben kein Pappenstiel!

    Probieren (und messen) geht halt über studieren.

    MfG DHB

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DHB“ ()

    nachtrag *würg*

    also ich hätts ja nicht gedacht ...

    in Access2000 VisualBasic
    dauert
    ========================
    Dim i As Integer
    Dim y As Integer
    For i = 1 To 4096

    For y = 1 To 24000
    Test = Test + 1
    Test = Test + 1
    Test = Test + 1
    Next y

    Next i
    ========================
    ca. 5 !!! SEKUNDEN *würg*

    selbiger code in
    VB 2500 ExpressEdition NUR 859 MS :(

    ich hätte ja echt nen kleinen unterschied erwartet ... aber
    gleich um ~500% schneller ???!!!

    sakradi :)
    damit ist s umschreiben beschlossene sache

    servus
    Bei VBA (z.B. in Access oder Excel) handelt es sich nicht um Machine-Code, sondern um P-Code, der zusätzlich auch noch überwacht und nicht direkt, sondern per API ausgeführt wird. Das macht das ganze ziemlich langsam.
    Am schnellsten ist der Code m.E. mit VB6 als Native-Code kompeliert, wenn man Overflow-Checks und Array-Bound-Checks raus nimmt.


    so long..
    Andy

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Mad Andy“ ()

    ooh :)

    gut zu wissen ... nun noch eine FRAGE ...

    ich überlege gerade ob ich Access auf die 2007er version
    update ...

    ist dort des selbe problem ? aufzufinden .. und

    wenn ja ... WAS kann ich tun um in VB200X zu arbeiten und

    um - eben - die vielen datensätze (bis zu 800.000) zu analysieren/testen etc. und dann in access oder sonstwo (ein tipp) anzusehen ... bzw. CHART-technisch anzuzeigen ...

    mfg - r.b
    meinegüte ...

    nun widerspricht sich doch so einiges .. denn

    wenn ich folgendes ausprobiere:
    (in VB 2005 Express Ed.)
    =========================
    For i = 1 To 4096


    For y = 1 To 24000
    Xtest = Xtest + 1
    Xtest = Xtest + 1
    Xtest = Xtest + 1

    Next y



    Next i
    =========================
    dauerts ca. 850 MS!

    stattdessen dauerts bei:

    =========================
    For i = 1 To 4096


    For y = 1 To 24000
    CallXtest
    Next y



    Next i

    sub CallXtest()

    Xtest = Xtest + 1
    Xtest = Xtest + 1
    Xtest = Xtest + 1

    end Sub
    =========================
    dauerts grad mal 385 MS ! ?

    oben hats doch geheissen .. dass SPRÜNGE zeit kosten
    .. scheinbar nicht immer :)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Fremder“ ()

    Was ich sagte, war folgendes:


    [..] Ein Funktionsaufruf ist generell sogar noch kostspieliger [..]


    Generell bedeutet in diesem Fall: Würde der Code
    direkt in Maschinencode umgewandelt werden, wäre
    ein Funktionsaufruf kostspieliger. Ich erkläre mal kurz
    warum:

    Die CPU hat Zugriff auf mehrere Speicher, die unterschiedliche
    Zugriffszeiten besitzen. Es gibt unter anderem den
    Speicher, der direkt auf der CPU sitzt und praktisch
    keine Verzögerung besitzt und den Arbeitsspeicher
    der im Vergleich dazu sehr langsam ist.

    Der Code sitzt normalerweise im Arbeitsspeicher, die
    CPU müsste also ständig die Daten von einem relativ
    langsamen Speicher transferieren. Damit das verhindert
    wird, hat man sogenannte Prefetch-Queues entwickelt.
    Die Prefetch-Queue speichert einfach eine bestimmte
    Menge von Code im voraus, auf die die CPU dann
    schnellen Zugriff hat, weil sie nicht mehr auf den
    langsamen Arbeitsspeicher zurückgreifen muss.
    Während die CPU also einen Befehl ausführt, sammelt
    die Prefetch-Queue (ohne die CPU zu behindern) die
    nächsten x Anweisungen im Speicher.

    Auf deinen Code angewandt würde das bedeuten:
    Während die CPU die 1. Anweisung

    Quellcode

    1. Xtest = Xtest + 1


    ausführt, versucht die Prefetch-Queue die nächsten
    beiden Anweisungen vorzuspeichern. Was ist jetzt
    das Problem bei einem Funktionsaufruf ?
    Stell dir folgenden Code vor:

    Quellcode

    1. Xtest = Xtest + 1
    2. Call Foo()
    3. Ytest = Ytest + 1
    4. Ztest = Ztest + 1
    5. ...
    6. Sub Foo()
    7. Atest = Atest + 1
    8. Btest = Btest + 1
    9. End Sub


    Wenn die CPU bei der Anweisung "Foo"
    angelangt ist, dann sind in der Prefetch-Queue die
    beiden Befehle "Ytest = Ytest + 1" und "Ztest =
    Ztest + 1" vorgespeichert. Die CPU springt jetzt aber
    in die Funktion "Foo" und invalidiert somit den in der
    Prefetch-Queue enthaltenen Code! Die CPU muss
    jetzt auf die Prefetch-Queue warten, die erst mit den
    Daten aus dem langsamen Arbeitsspeicher befüllt
    werden muss. Das Programm büßt somit an
    Geschwindigkeit ein.

    Und das ist nicht das einzige Problem: Die CPU besitzt
    die Möglichkeit, Code aus der Prefetch-Queue, der
    nicht von anderem Code abhängt, parallel auszuführen.
    Das bedeutet: Wären die Anweisungen aus der
    Funktion "Foo" in den Programm-Code ausgelagert
    worden, wären sie mit großer Wahrscheinlichkeit in
    einem Prozessorzyklus, zusammen mit der Anweisung
    "Xtest = Xtest + 1" ausgeführt worden.

    Warum ist dein Funktionsaufruf nun schneller ?
    Die von mir oben genannten Beispiele gelten - wie bereits
    erwähnt - für den Fall, dass der Code so in Maschinen-
    code übersetzt wird. Tatsache ist aber, dass dem nicht
    so ist. In C gibt es das Schlüsselwort "inline". Damit
    kann man den Compiler (dem Programm, dass deinen
    Code in Maschinencode übersetzt) darauf hinweisen, dass
    eine Funktion nicht durch einen Funktionsaufruf
    (also einem Sprung) aufgerufen werden soll, sondern
    direkt in den Code eingebettet wird. Wie gesagt:
    hinweisen. Ob dies tatsächlich gemacht wird, liegt
    allein im Ermessen des Compilers. In VB gibt es das
    Schlüsselwort "inline" gar nicht mehr. Ob ein
    Compiler den Code also direkt einbettet hängt nur
    noch vom Compiler selbst ab. Und genau der hat bei
    dir entschieden, dass die Einbettung hier vorteilhaft ist.
    wau :)

    ich habs VERSTANDEN .. und wirklich DANKE !! eine echt sehr kompetente erklärung ...

    danke ...

    soll dann wohl auch heissen ..

    dass wenns dem compiler zuviel wird (viele subs oder so ...) dann
    wirds wieder lastvoll und entsprechend langsam ...

    ich werd einfach immer die stopuhr laufen lassen

    danke nochmal