Seite 1 von 2
Programmcode optimieren
Verfasst: 04.11.2006 21:05
von ms
Hat jemand eine Idee wie man diese Auswertung signifikant beschleunigen kann ?
Das Feld ldaten.b befindet sich bereits im RAM.
anzahl.w ist ca. 3000.
Der Code wird ca. 13.000.000 mal ausgeführt.
VBA6 ist ca.30% schneller
Code: Alles auswählen
For k = 0 To 7 : m.w(k) = 0 : Next k ;merkerfeld für neue reihe löschen
For start = anzahl.w To 1 Step -1
X1.w = 0
For k = 1 To 7 :CC = ldaten.b(start, k)
If CC = r1.w Or CC = r2.w Or CC = r3.w Or CC = r4.w Or CC = r5.w Or CC = r6.w : X1.w = X1.w + 1 :EndIf
Next k
If x1.w >2 : m.w(X1.w) = m.w(X1.w) + 1 : EndIf ;Wenn mehr als 2 treffer, dann eintragen
If X1.w = 3 : start1 = start: EndIf ;wenn 3 richtige Ziehungsnummer und Datum merken
Next start
Re: Programmcode optimieren
Verfasst: 05.11.2006 00:30
von Thorsten1867
Eigentlich sollte das reichen, um einen Array zu löschen.
Das dürfte kürzer sein:
Verfasst: 05.11.2006 00:52
von ts-soft
>> VBA6 ist ca.30% schneller
VB6 halte ich zwar für unwahrscheinlich, aber VBA ist in jedem Falle langsamer

Verfasst: 05.11.2006 00:53
von Thorsten1867
Ich würde das so machen:
Code: Alles auswählen
Define.w X1, start, start1, anzahl, r1, r2, r3, r4, r5, r6
; .......
Dim m.w(7) ; Array löschen
For start = anzahl To 1 Step -1
X1 = 0
For k = 1 To 7
Select ldaten.b(start, k)
Case r1, r2, r3, r4, r5, r6
X1 + 1
EndSelect
Next k
If X1 > 2 : m(X1) + 1 : EndIf
If X1 = 3 : start1 = start : EndIf
Next start
Verfasst: 05.11.2006 01:37
von Helle
Wenn man stolzer Besitzer mindestens eines Pentium 3 oder Athlon 4 ist kann folgendes die Sache enorm beschleunigen:
Code: Alles auswählen
;es wird vorausgesetzt: die jeweilige Zahlenreihe im Speicher ist aufwärts geordnet,
;also die kleinste Zahl zuerst usw. Die Zahlen sind Byte-Werte (eben wie ldaten.b)!
;Z1 und Z2 sind die 6 Zahlen der aktuellen Ziehung, hier 1,2,3,4,5,6. Z1 und Z2 sind
;dann wie unten zu belegen! Auf Hex achten!
Global Anzahl.l = 3000 ;anpassen!
Global Start.l
Global Ende.l
Global Z1.l = $0605 ;sind die letzten zwei Zahlen r6 bis r5
Global Z2.l = $04030201 ;sind die ersten vier Zahlen r4 bis r1
Global X1.w
Start = AllocateMemory(Anzahl*7) ;8 besser!
Ende = Start + (Anzahl*7)
!mov esi,[v_Ende]
!mov eax,[v_Z1]
!movd mm1,eax
!psllq mm1,32
!mov eax,dword[v_Z2]
!movd mm2,eax
!por mm1,mm2 ;in mm1 stehen jetzt die 6 Zahlen r1 bis r6 (Z1 und Z2)
;nur für Demo! Start 0-5 mit 1,2,3,4,5,6 belegen
!mov edi,[v_Start]
;!add edi,21 ;für weitere Tests, immer 7-er Abstände!
!mov eax,1
!mov ecx,6
W0:
!mov [edi-1+eax],al
!inc eax
!dec ecx
!jnz l_w0
For k = 0 To 7
; m.w(k) = 0 ;hier auskommentiert, weil nicht vorhanden
Next k ;merkerfeld für neue reihe löschen
;For start = anzahl.w To 1 Step -1 ;anzahl ca.3000
For x = Ende - 7 To Start Step -7 ;8 wäre natürlich besser!
X1 = 0
;------------------------------------
; For k = 1 To 7
; CC = ldaten.b(start, k)
; If CC = r1.w Or CC = r2.w Or CC = r3.w Or CC = r4.w Or CC = r5.w Or CC = r6.w
; X1.w = X1.w + 1
; EndIf
; Next k
;------------------------------------
;------------------------------------
!xor edi,edi
!sub esi,7
W2:
!movq mm0,[esi+edi]
!pcmpeqb mm0,mm1
!pmovmskb eax,mm0 ;für jede Übereinstimmung ist in al ein Bit gesetzt
!mov ecx,6
W1:
!shr al,1
!adc [v_X1],0
!dec ecx
!jnz l_w1
!inc edi
!cmp edi,6
!jb l_w2
;nur für Demo!
!pushad
Debug X1
!popad
;------------------------------------
If X1.w >2
; m.w(X1.w) = m.w(X1.w) + 1 ;hier auskommentiert, weil nicht vorhanden
EndIf ;Wenn mehr als 2 treffer, dann eintragen
If X1.w = 3
start1 = start
EndIf ;wenn 3 richtige Ziehungsnummer und Datum merken
;Next start
Next x
Gruss
Helle
Edit: Zusatzschleife eingefügt.
Verfasst: 05.11.2006 11:16
von uweb
Es ist zwar ziemlich trivial (um nicht plump zu sagen) aber dürfte etwas bingen :
Schleifen kosten Zeit und der Zugriff auf Konstanten ist schneller als der auf Variablen !
Wenn
durch sieben mal fast identischen Code ersetzt wird ist das zwar nicht elegant aber schnell.
Verfasst: 05.11.2006 20:12
von Helle
Hier eine überarbeitete (Test-)Version:
Code: Alles auswählen
;- überprüft, ob (6) Zahlen in einem Bereich von (7) Zahlen (alles Byte-Werte) vorkommen
;- funktioniert auch mit ungeordneten Zahlenfolgen
;- "Helle" Klaus Helbing, 05.11.2006, PB v4.01
;- nutzt MMX und SSE
Global Anzahl.l = 1 ;hier für Test nur 1
Global Start.l
Global Z1.l = $0405070c ;sind die ersten vier Test-Zahlen (von 4,5,7,12,43,45)
Global Z2.l = $2b2df0f0 ;sind die letzten zwei Test-Zahlen mit 2 Platzhalter aufgefüllt
Global X1.w ; diese Platzhalter evtl. nicht nötig (?), ungleich Wert von unten (f1)!
Start = AllocateMemory(Anzahl*8) ;8 ist fast schon zwingend! Alignment!
;- Im RAM würden alle zu untersuchenden Zahlenfolgen stehen (im 8-ter Byte-Abstand)
!mov esi,[v_Start]
;- 8 Werte ins RAM schreiben für Test
!mov eax,50c1116h ;5,12,17,22,34,35,43 als Simulation vorhandener Werte im RAM
!mov [esi+4],eax
!mov eax,22232bf1h ;f1 als Platzhalter muss sein! Wert > max.möglicher Wert
!mov [esi],eax
!mov edx,0fdh ;irgend ein nicht möglicher Wert
!movd mm4,edx ;"Füllwert" ungleich Null
!mov eax,[v_Z1]
!movd mm1,eax
!psllq mm1,32 ;um 4 Bytes nach links verschieben
!mov eax,dword[v_Z2]
!movd mm2,eax
!por mm1,mm2 ;in mm1 stehen jetzt die 6 Zahlen (Z1 und Z2)
!movq mm3,mm1 ;mm1 sichern = Testzahlen
!movq mm0,[esi]
!movq mm5,mm0 ;mm0 sichern = Testfeld
;-------- zuerst die Linksverschiebung
!mov edi,5 ;abhängig von Anzahl der Zahlen!
W2:
!pcmpeqb mm0,mm3
!pmovmskb eax,mm0 ;für jede Übereinstimmung ist in al ein Bit gesetzt
!mov ecx,8
W1:
!shr al,1
!adc [v_X1],0
!dec ecx
!jnz l_w1
!dec edi
!jz l_w3
!psllq mm3,8
!por mm3,mm4
!movq mm0,mm5 ;mm0 wieder herstellen
!jmp l_w2
W3:
;-------- und jetzt die Rechtsverschiebung
!mov edi,6 ;abhängig von Anzahl der Zahlen!
!movq mm0,mm5 ;mm0 wieder herstellen
!movq mm3,mm1
!psrlq mm3,8
!mov edx,0fd000000h ;irgend ein nicht möglicher Wert
!movd mm4,edx ;"Füllwert" ungleich Null
!psllq mm4,32
W2R:
!pcmpeqb mm0,mm3
!pmovmskb eax,mm0 ;für jede Übereinstimmung ist in al ein Bit gesetzt
!mov ecx,8
W1R:
!shr al,1
!adc [v_X1],0
!dec ecx
!jnz l_w1r
!dec edi
!jz l_w3r
!psrlq mm3,8
!por mm3,mm4
!movq mm0,mm5 ;mm0 wieder herstellen
!jmp l_w2r
W3R:
MessageRequester("Übereinstimmungstest","Gefundene Übereinstimmungen : " + Str(X1))
!emms
End
Gruss
Helle
Verfasst: 05.11.2006 21:58
von ms
Danke für die vielen Antworten
Eigentlich sollte das reichen, um einen Array zu löschen.
Code:
Dim m.w(7)
stimmt - aber viel schneller ?
Code:
If x1 > 2 : m(X1.w) + 1 : EndIf
stimmt
>> VBA6 ist ca.30% schneller
VB6 halte ich zwar für unwahrscheinlich, aber VBA ist in jedem Falle langsamer Mr. Green
Das Projekt ist bereits unter VBA5 / VBA6 realisiert - die Auswerungszeiten sind definitiv ca. 25 - 30 % schneller - z. B 2200 / 2900 sec.
Helle, danke für Deinen Assembler Code. Werde in dieser Richtung noch einige Test´s anstellen
Verfasst: 05.11.2006 22:12
von ts-soft
VBA5 oder 6 sind die Versionen, die sich in Office, CorelDraw u. a. befinden.
Die kompilieren nicht Nativ.
VB6 (ohne A) kompiliert nativ. da könnte es sein, aber Meßfehler halte ich für
wahrscheinlicher

Verfasst: 05.11.2006 22:31
von ms
ts-soft, da liegst Du leider falsch. VBA6 (ich benutze SP6) ist ein vollwertiger Compiler. Unter der Hilfe / Info meldet sich z. B. VBA 6.0.9782. Dieser Compiler hat nichts mit den Programmierhilfen von MS Office etc. zu tun - außer vielleicht in einigen Teilen die Syntax.
Unter Visual Basic 6 mit dem Service Pack 6 sind die Auswertezeiten definitiv um 25 - 30 % schneller. Wer es nicht glaubt sollte es testen. Ich bin aber trotzdem auf Purebasic umgestiegen aus mehreren Gründen (Multiplattform, kompakter, schneller ?, kein MS !!, etc.)