| |
|
|
Andreas Koch | Hallo zusammen,
ich müsste nach Möglichkeit einen Teil meines Programms um Einiges beschleunigen.
Dabei handelt es sich um eine Prozedur, der entweder eine Reihe von Variablen übergeben werden oder die direkt auf die globalen Variablen zugreifen muss. Bei den Variablen handelt es sich aktuell (noch) um Arrays. Der gesamte Quellcode nimmt so um die 40 Zeilen ein. Laufen müsste das Ganze auf einem 64-bit System.
Welche Möglichkeiten gibt es da für mich? Im Verdacht habe ich die Themengebiete: Assembler, XPIA, XPSE, Profan2CPP und "natives" Programmieren. Mit welchem Thema sollte ich mich da näher beschäftigen?
Mit freundlichen Grüßen
Andreas Koch |
|
|
| |
|
|
|
| Grüße!
Nimmste einfach nProcs: [...] -
quasi natives Profan genau für Deinen Zweck entwickelt.
Gibt hier auch schon sehr viele Funktionen jeweils als Proc und nProc gepostet -
einfach nachfragen. Brauchst ein konkretes Beispiel? |
|
|
| |
|
|
|
Andreas Koch | Hallo iF,
danke für die entschiedene Antwort. Das spart Zeit. Ein konkretes Beispiel wäre nicht schlecht, am Besten mit Übergabe von Arrays. Gibt es einen Anhaltspunkt, um wieviel das Ganze dann schneller wird? |
|
|
| |
|
|
|
| Je nach Operation haben wir schon gemessen das eine nProc 2.000 mal schneller
als eine Proc sein kann. In nProcs kannst auch Assembler verwenden. Schreib einfach
mal ein kleines Beispielprogramm mit einer Proc und dann mache ich Dir daraus eine
nProc. |
|
|
| |
|
|
|
Andreas Koch | 2000 mal schneller ist Musik in meinen Ohren. Ein vernünftiges Beispiel kann ich allerdings erst morgen erstellen, da ich den Programmcode nicht zu Hause habe.
Wünsche wohl zu ruhen. |
|
|
| |
|
|
|
Andreas Koch | Hallo iF, hier habe ich jetzt das Beispiel.
Ich habe meine Prozedur noch einmal in zwei kleinere gesplittet, die etwas übersichtlicher sind. Das Ganze soll das Gaußsche Eliminationsverfahren für eine Matrix beliebiger Größe und beliebig vielen Vektoren auf der rechten Seite abbilden. Vorraussetzung für die Lösbarkeit sind die Singularität der Matrix und sämtliche Einträge auf der Diagonalen<>0.
Da die beiden Prozeduren nur zusammen Sinn ergeben, habe ich sie beide angehängt.
Wenn du nun die Prozedur "Solver" in eine nProc umwandeln könntest, wäre das eine prima Sache. Ich würde mich dann anschließend mit der Prozedur "Dreiecksmatrix" befassen. KompilierenMarkierenSeparierencls
var size!=6
Declare A![size!-1,size!-1], Zeile&, Spalte&, Diagonale&, Faktor!, aux!,Lastenarray![0,size!-1],Lastfall%,Verschiebungsarray![0,size!-1]
'Erzeugung zweier Zufallsmatrizen
WhileLoop 0,size!-1
Spalte&=&loop
WhileLoop 0,size!-1
Zeile&=&loop
A![Spalte&,Zeile&]=Rnd()
If Zeile&<1
Lastenarray![Zeile&,Spalte&]=Rnd()
EndIf
EndWhile
EndWhile
'Umformung, Erzeugung einer Dreiecksmatrix
proc Dreiecksmatrix
WhileLoop 0,size!-1,1
Diagonale&=&loop
WhileLoop Diagonale&+1,size!-1,1
Zeile&=&loop
Faktor!=A![Diagonale&,Zeile&]/A![Diagonale&,Diagonale&]
if Faktor!<>0
WhileLoop 0
Lastfall%=&loop
Lastenarray![Lastfall%,Zeile&]=Lastenarray![Lastfall%,Zeile&]-Faktor!*Lastenarray![Lastfall%,Diagonale&]
EndWhile
WhileLoop 0,size!-1,1
Spalte&=&loop
A![Spalte&,Zeile&]=A![Spalte&,Zeile&]-Faktor!*A![Spalte&,Diagonale&]
EndWhile
EndIf
EndWhile
EndWhile
EndProc
'Rücksubstitution
Proc Solver
Parameters Lastfall%
WhileLoop size!,1,-1
Diagonale&=&loop-1
aux!=0
WhileLoop Diagonale&+1,size!-1,1
Spalte&=&loop
aux!=aux!+A![Spalte&,Diagonale&]*Verschiebungsarray![Lastfall%,Spalte&]
EndWhile
Verschiebungsarray![Lastfall%,Diagonale&]=(Lastenarray![Lastfall%,Diagonale&]-aux!)/A![Diagonale&,Diagonale&]
EndWhile
EndProc
Dreiecksmatrix
Solver(0)
WaitInput
PS: Wenn irgendjemandem ein Fehler im Code auffällt, insbesondere ein Rechenfehler, bitte ich darum, mich darüber zu informieren.
PPS: Kann man mit einer nProc auch das Zeichnen auf einer Bitmap beschleunigen? |
|
|
| |
|
|
|
| Klar auch das Zeichnen beschleunigen, kannst alles mit machen - gibt ja quasi unendlich viele Anwendungsgebiete. Ist halt natives "Profan" mit allen APIs.
Sinus: [...] Sand auf Kugel: [...] Hier ne Include Pixels.inc: [...] Hier Ameisenpixel aus eigenem Thread: [...] Und ganz wichtig die hPic.inc: [...]
Oder andere Beispiele für nProc-Verwendung:
asyncMsgBox.inc - Rückmeldungen asynchroner MessageBoxen: [...] Canvas.inc: [...] CanvasListBoxen: [...] Keyboardhook nach UserMessages: [...] miclevel-inc-mikrophon-eingangslautstaerke: [...] OGL-2DUI: [...] RGB-Funktionen: [...]
...
das sind nur ein paar... gibt mtlw. so viel Schnulli... auch bei den Includes: [...]
Das hier ist klasse: [...] und solltest Dir mal anschauen - mit sowas kamma auch ganz schnell einfache Spiele herzaubern wie z.B. den Hubi: [...]
Deine Code kann ich mir vermutlich erst heute abend genauer ansehen - jetzt muss ich erstmal zum Zahnarzt. |
|
|
| |
|
|
|
Andreas Koch | Da scheint es ja alles Mögliche zu geben. Das werde ich mir mal in Ruhe anschauen müssen. Auf jeden Fall danke für die Hilfe. |
|
|
| |
|
|
|
| So,
lass uns das bitte zusammen erarbeiten sodass dann auch klar ist, wie es funktioniert und warum.
nProcs sind Thread- und APC ( [...] )- sicher und unheimlich schnell, weil der Code als Maschinencode ausgeführt wird.
Damit nProcs Thread- und APC-sicher sein können, kann auf globale Variablen nur lesend zugegriffen werden, sei denn, man koordiniert die Schreibzugriffe z.B. per Semaphore ( [...] ) .
Die sauberste und schnellste nProc kommt ohne globale Variablen aus und verarbeitet die als Parameter übergebenen Werte zu einem Rückgabewert. Lokale Variablen (also in der nProc angelegte Variablen) wiederum kann man so viele deklarieren wie man möchte.
Beispiel: KompilierenMarkierenSeparieren Auch mögliche Syntax: KompilierenMarkierenSeparieren Weitere mögliche Syntax: KompilierenMarkierenSeparieren Deine Proc solver verwendet jedoch globale Variablen und überschreibt auch die Inhalte. Also wäre der erste Schritt, diese Prozedur so umzuschreiben, dass ihr die verwendeten Arrays als Parameter übergeben werden und auch der Rückgabewert dementsprechend ein Array ist sodass sie für sich alleine nur das verarbeitet was ihr als Parameter übergeben wurde ohne das sie sich was aus dem Hauptprogramm saugen muss. Das ist auch unabhängig von nProc bei Procs die vorzuziehende oder "saubere" Programmiertechnik.
Kannst Du das fix umstellen? |
|
|
| |
|
|
|
Andreas Koch | Ok, Problematik verstanden. Hier ist der neue Code, wobei jetzt alle Variablen übergeben oder intern deklariert werden. KompilierenMarkierenSeparierencls
var size!=6
Declare A![size!-1,size!-1], Zeile&, Spalte&, Diagonale&, Faktor!, aux!,Lastenarray![0,size!-1],Lastfall%,Verschiebungsarray![0,size!-1]
Lastfall%=0
'Erzeugung zweier Zufallsmatrizen
WhileLoop 0,size!-1
Spalte&=&loop
WhileLoop 0,size!-1
Zeile&=&loop
A![Spalte&,Zeile&]=Rnd()
If Zeile&<1
Lastenarray![Zeile&,Spalte&]=Rnd()
EndIf
EndWhile
EndWhile
'Umformung, Erzeugung einer Dreiecksmatrix
proc Dreiecksmatrix
WhileLoop 0,size!-1,1
Diagonale&=&loop
WhileLoop Diagonale&+1,size!-1,1
Zeile&=&loop
Faktor!=A![Diagonale&,Zeile&]/A![Diagonale&,Diagonale&]
if Faktor!<>0
WhileLoop 0
Lastfall%=&loop
Lastenarray![Lastfall%,Zeile&]=Lastenarray![Lastfall%,Zeile&]-Faktor!*Lastenarray![Lastfall%,Diagonale&]
EndWhile
WhileLoop 0,size!-1,1
Spalte&=&loop
A![Spalte&,Zeile&]=A![Spalte&,Zeile&]-Faktor!*A![Spalte&,Diagonale&]
EndWhile
EndIf
EndWhile
EndWhile
EndProc
'Rücksubstitution
Proc Solver
Parameters Lastfall%, A![], Verschiebungsarray![], size!
Declare aux!, Zeile&, Spalte&, Diagonale&
WhileLoop size!,1,-1
Diagonale&=&loop-1
aux!=0
WhileLoop Diagonale&+1,size!-1,1
Spalte&=&loop
aux!=aux!+A![Spalte&,Diagonale&]*Verschiebungsarray![Lastfall%,Spalte&]
EndWhile
Verschiebungsarray![Lastfall%,Diagonale&]=(Lastenarray![Lastfall%,Diagonale&]-aux!)/A![Diagonale&,Diagonale&]
EndWhile
Return Verschiebungsarray![]
EndProc
Dreiecksmatrix
Verschiebungsarray![]=Solver(Lastfall%, A![],Verschiebungsarray![], size!)
WhileLoop 0,size!-1
Print Verschiebungsarray![0,&loop]
EndWhile
WaitInput
Was mache ich denn, wenn ich zwei Arrays übergeben und wieder zurückgeben muss (so wie bei der Prozedur "Dreiecksmatrix")? Mir fällt dazu nur ein, dass ich das eine Array an das andere anfügen müsste... |
|
|
| |
|
|
|
| Mehrere Werte (egal ob Array etc) zurückgeben einfach so wie die APIs es auch tun indem einfach ein Handle/ Speicher zurückgegeben wird/ Struktur. KompilierenMarkierenSeparieren Man kann also beliebig viele Werte zurückgeben indem man einfach ein Handle eines Speichers zurückgibt der die zu erwartenden Werte enthält wobei die Werte natürlich selbst auch wiederum Speicherhandles sein können womit man wiederum beliebig strukturierte Rückgaben produzieren kann. |
|
|
| |
|
|