Programmcode optimieren

Anfängerfragen zum Programmieren mit PureBasic.
ms
Beiträge: 26
Registriert: 24.08.2006 21:56

Programmcode optimieren

Beitrag 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
no name, no woman, no job, no money, no worries - just tired
Benutzeravatar
Thorsten1867
Beiträge: 1360
Registriert: 04.02.2005 15:40
Computerausstattung: [Windows 10 x64] [PB V5.7x]
Wohnort: Kaufbeuren
Kontaktdaten:

Re: Programmcode optimieren

Beitrag von Thorsten1867 »

Code: Alles auswählen

For k = 0 To 7 : m.w(k) = 0  : Next k
Eigentlich sollte das reichen, um einen Array zu löschen.

Code: Alles auswählen

Dim m.w(7)
Das dürfte kürzer sein:

Code: Alles auswählen

If x1.w >2 : m.w(X1.w) = m.w(X1.w) + 1 : EndIf

Code: Alles auswählen

If x1 > 2 : m(X1.w) + 1 : EndIf
Download of PureBasic - Module
Download of PureBasic - Programmes

[Windows 11 x64] [PB V6]

Bild
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

>> VBA6 ist ca.30% schneller
VB6 halte ich zwar für unwahrscheinlich, aber VBA ist in jedem Falle langsamer :mrgreen:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Thorsten1867
Beiträge: 1360
Registriert: 04.02.2005 15:40
Computerausstattung: [Windows 10 x64] [PB V5.7x]
Wohnort: Kaufbeuren
Kontaktdaten:

Beitrag 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
Download of PureBasic - Module
Download of PureBasic - Programmes

[Windows 11 x64] [PB V6]

Bild
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag 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.
Benutzeravatar
uweb
Beiträge: 461
Registriert: 13.07.2005 08:39

Beitrag 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

Code: Alles auswählen

For k = 1 To 7 ... Next k
durch sieben mal fast identischen Code ersetzt wird ist das zwar nicht elegant aber schnell.
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag 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
Zuletzt geändert von Helle am 05.11.2006 22:33, insgesamt 1-mal geändert.
ms
Beiträge: 26
Registriert: 24.08.2006 21:56

Beitrag 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
no name, no woman, no job, no money, no worries - just tired
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag 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 :mrgreen:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
ms
Beiträge: 26
Registriert: 24.08.2006 21:56

Beitrag 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.)
no name, no woman, no job, no money, no worries - just tired
Antworten