Beiträge von Andy
-
-
die Idee ist soweit nicht schlecht....ABER:
Der Stack ist nur nach oben, und IMMER nur nach oben konsistent! Beim Aufrufen einer jedwegen Funktion steht die Rücksprungadresse immer auf [esp+0]. Wenn du die jetzt nach "unten" schiebst, passiert folgendes:
Wenn der Call bzw. die aufgerufene Funktion sich über SUB esp,1024 Platz (1024 Bytes) auf dem Stack für bspv. Variablen reserviert, dann ist dieser Platz (will sagen der Inhalt dort) nach dem Funktionsaufruf natürlich auch noch dort!
Die Funktion "schiebt" lediglich am Ende den Stackpointer wieder in die richtige Position per ADD esp,1024.
Capice?
Du "schiebst" die Rücksprungaddresse mit deinem POP vom Stack "nach unten" ins Datengrab, denn irgendwann wird IMMER irgendetwas auf dem Stack reserviert^^
Also musst du die Rücksprungaddresse sichern, könntest du irgendwie machen, sicherer ist immer die Methode SICHER!
C
Alles anzeigen#include <WinAPI.au3> #include <Array.au3> #include <GDIPlus.au3> #include <assembleit2_64.au3> #cs _addToPath use32 start: mov eax,[esp+4] mov ebx,[esp+8] mov ecx,[esp+12] mov edx,[esp+16] push edx push ecx push ebx ;~ _ASMDBG_() call eax ret #ce _GDIPlus_Startup() $hKERNEL32 = DllOpen("kernel32.dll") ;~ $hGDIPLUS = dllopen("gdiplus.dll") $handle= _WinAPI_GetModuleHandle("gdiplus.dll") ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $handle = ' & $handle & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $pointer= DllCall($hKERNEL32, "ptr", "GetProcAddress", "ptr", $handle, "str", "GdipAddPathLine2") ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $pointer[0] = ' & $pointer[0] & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $hGUI = GUICreate("") GUISetState() $tPoints = DllStructCreate("float [4]") DllStructSetData($tPoints, 1, 10.0, 1) DllStructSetData($tPoints, 1, 10.0, 2) DllStructSetData($tPoints, 1, 150.0, 3) DllStructSetData($tPoints, 1, 150.0, 4) $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI) $hPath = _GDIPlus_PathCreate() ;~ _GDIPlus_PathAddLine($hPath, 10, 10, 10, 10) ;~ _GDIPlus_PathAddLine($hPath, 150, 150, 150, 150) $ret = _AssembleIt2("int", "_addToPath", "ptr", $pointer[0], "ptr", $hPath, "ptr", DllStructGetPtr($tPoints), "int", 2) ConsoleWrite($ret & @CRLF) _GDIPlus_GraphicsDrawPath($hGraphics, $hPath) While GUIGetMsg() <> -3 WEnd//EDIT
Denn du weißt auch nicht, welche Inhalte auf dem Stack "über" deinen Funktionsparametern noch gebraucht werden, denn da stehen natürlich auch die Parameter, die die aufrufenden Funktionen dort abgelegt haben...
-
Hi,
für den Kollegen minx hatte ich vor einigen Jahren eine Optimierung in Assembler geschrieben, da war u.a. auch eine pow(a,b)-Funktion dabei, kannst du ja mal ausprobieren!
Dazu muss man sagen, dass AutoIt intern die Bibliotheken von Microsoft verwendet bzw. von dessen Compiler.
Dieser rechnet NICHT mit den von der FPU bereitgestellten 80 Bit Genauigkeit, sondern "nur" mit einer 53 Bit Mantisse, also 64 Bit Genauigkeit!!!
Daher, um "gleiche" Ergebnisse von AutoIt und dem ASM-Code zu erhalten, sollte man dieses Verhalten anpassen.
Beispiel für POW incl. setzen auf 53Bit Mantisse
Code
Alles anzeigen#include <assembleit2_64.au3> #cs _pow() ;a^b use32 sub esp,2 ;platz für controlword auf dem stack 2 Bytes finit fstcw word[esp] ;FPU controlword laden and word[esp], 001011111111b ;bit 8+9 ;64 Bit genauigkeit, 53Bits Mantisse ; or word[esp], 110000000000b ;bit 10+11 abrunden wg INT fldcw word[esp] ;FPU controlword speichern mov ax,word[esp] ;falls sich das jemand im Debugger angucken will^^ add esp,2 ;stack wieder restaurieren power: ;ST0=a^b fld qword[esp+12] ;double fld qword[esp+4] ;double ;~ _asmdbg_() fyl2x fld1 fld st1 fprem f2xm1 faddp st1, st0 fscale fstp st1 ret #ce $a = 1 / Log(11) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $a = ' & $a & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $b = Log(0.01) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $b = ' & $b & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $c = $a ^ $b ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $c = ' & $c & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $ret = _AssembleIt2("double", "_pow()", "double", $a, "double", $b) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ret = ' & $ret & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug ConsoleJetzt hab ich mir mal dein Script angeschaut, dein ASM-Code läuft bei mir 0,02Millisekunden, da ist nicht mehr viel zu optimieren, jedenfalls nicht merkbar^^
Der darauffolgende loop allerdings hat es in sich, der läuft 5 Millisekunden, und liest doch eigentlich nur eine Struct mit Werten aus.
Schau dir mal Func _GDIPlus_PathAddLine2($hPath, $aPoints) an!
Du musst dort in den dllcall doch nur den pointer auf die vom ASM-Code gefüllte Struct übergeben, dann hast du das ganze doppelt berechnete und hin- und herstructausgelese nicht mehr!
Das wären dann ca. 300-400 Zyklen
Ist es möglich die _GDIPlus_PathAddLine2 aus dem ASM-Code aufzurufen?
Na klar^^
Du musst dir nur den Pointer auf die Funktion holen per
Code#include <WinAPI.au3> $hKERNEL32 = DllOpen("kernel32.dll") $hGDIPLUS = dllopen("gdiplus.dll") $handle= _WinAPI_GetModuleHandle("gdiplus.dll") ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $handle = ' & $handle & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $pointer= DllCall($hKERNEL32, "ptr", "GetProcAddress", "ptr", $handle, "str", "GdipAddPathLine2") _arraydisplay($pointer) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $pointer[0] = ' & $pointer[0] & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Consolediesen Pointer an den ASM-code übergeben und dort CALLen.
Die Parameter werden auf den Stack gepushed
Zurück bekommst du in EAX den Pointer bzw. das Ergebnis
//EDIT4 Beispiel
C
Alles anzeigen#include <assembleit2_64.au3> ;https://msdn.microsoft.com/en-us/library/windows/desktop/ms645505(v=vs.85).aspx #cs _msgbox use32 mov eax,[esp+4] ;hwnd mov ebx,[esp+8] ;lptext mov ecx,[esp+12] ;lpcaption mov edx,[esp+16] ;utype mov esi,[esp+20] ; pointer auf die msgbox-funktion push edx push ecx push ebx push eax ;alles in umgekehrter Reihenfolge auf den stack call esi ;msgbox aufrufen ret ;rückgabe immer in EAX #ce #include <WinAPI.au3> $hKERNEL32 = DllOpen("kernel32.dll") $hUSER32 = DllOpen("user32.dll") $handle = _WinAPI_GetModuleHandle("user32.dll") ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $handle = ' & $handle & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $msgboxpointer = DllCall($hKERNEL32, "ptr", "GetProcAddress", "ptr", $handle, "str", "MessageBoxA") _ArrayDisplay($msgboxpointer) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $msgboxpointer[0] = ' & $msgboxpointer[0] & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $inhalt = "Hallo AutoIt" $titel = "TEST" $buttons = 4 ;vbyesno $ret = _AssembleIt2("uint", "_msgbox", "hwnd", 0, "str", $inhalt, "str", $titel, "uint", $buttons, "ptr", $msgboxpointer[0]) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ret = ' & $ret & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug ConsoleDer CALL bereinigt selbstständig den Stack!
-
Meine erste Festplatte hatte doch tatsächlich 30 MB das war ca. das Speichervolumen von 30 Disketten . Das Ding war so groß wie eine Stange Camel.
hehe, meine erste Festplatte hatte 10MB, die steckte in einem orginal IBM-PC, den ich sehr günstig gebraucht erstanden habe. 8088 Prozessor @4,77Mhz und CGA Grafikkarte https://de.wikipedia.org/wiki/Color_Graphics_Adapter...
Betriebssystem waren diverse DOS-Clone bis ich schliesslich bei Novell-DOS gelandet bin.
Damals hatte man noch irre Angst vor Headcrashes der Festplatte, ich hab also den Rechner gekauft und einen Kumpel gebeten mein Auto (Käfer BJ1965) zu fahren von Wiesbaden nach Mainz, ich auf dem Rücksitz und den Rechner freischwebend in den Händen gehalten um ja die kleinste Erschütterung abzufangen. Ich hatte, um mir das Gerät zu kaufen, neben der Schule ca. ein Jahr gearbeitet. Ich glaube ich hatte in meinem Leben nie so geschwitzt wie auf dieser Fahrt^^
Heutzutage fällt ein Laptop vom Tisch und während der ersten 3cm freien Falls merkt das die Festplatte, schreibt gemütlich während der nächsten 2cm des Fallens den Cacheinhalt auf die Platte zurück, fährt die Köpfe in in die Parkposition, legt das System schlafen, und wartet gemütlich auf den Einschlag....
Für die Fließkommaberechnungen konnte man einen 8087 Koprozessor kaufen und in den dafür vorgesehenen Sockel stecken, den hab ich mir dann irgendwann geleistet, und konnte somit die FPU-Befehle direkt ausführen, das hat etliche Programme zig mal schneller gemacht, u.a. mein in Assembler programmiertes Apfelmännchen. Da bin ich heute noch stolz drauf, denn das lief komplett im 8 Speicherzellen großen Stack der FPU, btw. ist der Code heute noch exakt so lauffähig auf neuester CPU!
Mein nächster Rechner war ein gebrauchter 80386sx, auch orginal IBM PS2-Modell, den hatte ich dann während des Studiums. Ich könnte heute noch die IBM-Jungs verdreschen, das System war derartig geil, aber leider wollten die für Zusatzkarten für den Microchannel irre hohe Lizenzkosten. Ansonsten hätte der Microchannel die restliche PC-Welt hinweggefegt.
Ich kam günstig an eine Netzwerkkarte, Rechner aufgemacht, Karte in den Microchannel gesteckt, Rechner gebootet, fertig. HEUTE, 30 Jahre später lädt JEDES PC-Betriebsystem aus dem Internet erst mal Treiber nach...ohne Internet keine Hardwarebenutzung, wtf!!!
Im Microchannelsystem befand sich alles zum Betrieb notwendige im ROM der Karte, incl. aller Systemparameter. Karte an Microchannel: "Hey, ich bin die neue Netzwerkkarte, meine ID lautet blablub und alle Infos zu mir sind an Adresse tralala!" Microchannel an Karte:" Hey Netzwerkkarte, willkommen im Club, deine Kumpels Festplatte XYZ, Grafikkarte 123, Soundkarte, PCMCIA, SCSI und und und und die anderen Mitglieder der Party heißen dich willkommen! ". Systemboot, Fertig.
Über OS/2 (hiess bei mir nur OShalbe^^) verliere ich aus Pietätsgründen besser kein Wort. IBM hat, wie üblich, auch dieses geile BS in den Sand gesetzt. Weil an die Microchannelsysteme gebunden und aufgrund fehlender Anpassung an 386er Prozessoren die Entwicklung verpennt...
Da lob ich mir die AS/400, auf der Kiste hat es RICHTIG Spass gemacht zu arbeiten. Leider habe ich mich damals auf den Maschinenbau konzentriert und bis heute nur noch "nebenbei" programmiert.
Das Software-Konzept der AS/400, hardwareunabhängigen Code zu compilieren, wird bis heute noch praktiziert. So laufen auf der absolut allerneuesten Hardware aktuelle Programme und Tasks neben Programmen die unverändert 15 Jahre alt sind.
Naja, hat alles vor und Nachteile....
Heute geht man zu Aldi, kauft für 400 Euro einen Laptop, startet das Ding und kann sofort loslegen. Ich würde definitiv nicht mehr mit "Gebastel" anfangen.
-
Diese haben meistens eine Implementation eines Akzentes von BASIC. Mein alter Schultaschenrechner (TI-84+) unterstützt Goto und Labels.
Unser damaliger Schultaschenrechner war ein TI30 von 1978 oder 79, der hat den Rechenschieber abgelöst...
Auf dem TG hatte ich dann einen "richtigen" Computer als "Taschenrechner", meinen heute noch auf dem Schreibtisch stehenden und immer noch benutzten PC1401. Der hat satte 3534 Bytes (ja, BYTES) Ram und ist BASIC-programmierbar. Dazu noch Maschinensprachetauglich (KEIN Assembler, reine Binärkodierung mit Bytes)) mit einer Schnittstelle, über die ich 1986 in der Lehre eine NC-Fräsmaschine (IBM Baujahr 1969) zu einer CNC "umgebaut" hatte. Komplette 3-Achsen Steuerung, Controlling und rudimentäres G-Code in 3534 Bytes....
Falls sich jemand fragt, wo meine Besessenheit bei Assembler herkommt, Bytes zu zählen

Btw. GOSUB/RETURN war eh Standard, Zeilennummern genauso. Allerdings konnte man auch Einbuchstabige "Label" hinter die Zeilennummer schreiben also bspw. 10 "H" For %i=1 to 25 blablub und dann mit einem Tastendruck diese "Programme" direkt anspringen.
Gespeichert wurde mit einem selbstgelöteten Interface über die Schnittstelle und den Mikrofoneingang auf Musikkassette :o) , Kassettenrecorder vorrausgesetzt....
Alternativ Code abschreiben, abheften und dann irgendwann nach einem Reset wieder alles neu eintippern.
Ich erinnere mich sogar daran, dass wir über die Punktmatrixanzeige "Grafiken" und Spiele programmiert hatten. Basketball mit einem 1 "Pixel" großen Ball und 5x7 Pixel großen, animierten(!) Spielfiguren....alles natürlich in schwarzweiß^^
-
Die Probleme von Goto treten im Kompilat nicht mehr auf, da die Konstrukte der Ausgangssprache, welche im Maschinencode per Goto übersetzt werden, gar nicht die problematischen Konstrukte erzeugen können wie sie stattdessen mit Goto möglich wären.
Muhaaaaaa!

DER Satz hätte von mir sein können.


Wird "schön" gesetzt und ausgedruckt. Ist definitiv einer der Top10-Anwärter in der ewigen Bestenliste....
Dafür hast du dir bei unserem hoffentlich bald stattfindenden nächsten Treffen eine Runde lecker Biers verdient!
Sicherlich ist da etwas (ja, aber nur "etwas") Wahres dran. Warum nur etwas? Weil wer zum Teufel nimmt sich die bodenlose Frechheit heraus, einem gestandenen "Programmierer" vorzuschreiben, welche Sprung- bzw. Verzweigungskonstrukte er benutzen DARF und welche nicht?! Umgekehrt wird genau daraus ein Schuh! Die "Hochsprache" DARF kein GOTO benutzen, weil sie eben nicht (!!!) hauptsächlich von professionellen, will sagen erfahrenen und fach(!)kundigen Experten verwendet wird, sondern ÜBERWIEGEND (sonst macht es keinen Sinn) von unprofessionellen, unerfahrenen und nicht fachkundigen Code-zusammen-c&p-tern. Aha. Und genau für diese Zielgruppe wird dann also die bzw. eine Hochsprache "entwickelt". Jetzt wird mir so einiges klar....

Wir lassen "einfache" Konstrukte weg, damit die Deppen sich elitär gegenüber den "Kac*noob-Basic-Usern" fühlen können.
Die Verwendung bzw. Nichtverwendung von GOTO differenziert den (vermeintlichen) Könner von den "unqualifizierten" Anfängern (weil GOTO-Verwendern).
Dabei wird gerne vergessen, dass sämtliche Basic-Nachfolgesprachen ein GOTO implementiert hatten. Pascal, ja sogar das "elitäre" Turbo-Pascal hatte ein GOTO. Verdammte Axt. Nachdem das irgendwann rauskam, ging Borland mitsamt seinen anderen "Turbo"-Sprachen die Bachgasse runter. Bankrott wegen GOTO.....so kann´s geh´n.
Also besser erst gar kein GOTO in die Sprache implementieren, da sind schon ganze Dynastien von Systemhäusern dran kaputt gegangen ;o)
Btt:
Ja, ich KANN ein GOTO benutzen, muss es aber nicht. Aber das sollte in meiner Verantwortung liegen. Btw. habe ich auch in den gängigen (Makro-) Assemblern while/wend und if/then/else und Funktionen und viele überaus sinnvolle Konstrukte, welche auch in Hochsprachen verwendet werden. Aber auch ein GOTO (heisst dort Jump). Und sogar noch viel mehr, denn geschätzt 50 (!) dieser Jumps, welche abhängig von bestimmten Registern/Flags reagieren (sog conditional jumps). Um das in einer Hochsprache nachzubilden, ist einiges an Code erforderlich. Und ein "schlauer" Compiler, welcher aus dem hingetipperten Hochsprachen-Code einen mehr oder weniger schnellen/kurzen Maschinencode erstellt.
"Brauchen" tu ich das GOTO in AutoIt auch nicht
.Naja, fast nicht. Ein aus dem 40 Jahre alten GW-Basic (damals noch Interpreter *träum*) entliehenes "ON ERROR GOTO" würde AutoIt vortrefflich stehen....Da ich "nebenbei" mittlerweile viel mehr in VBA (hauptsächlich Excel) programmiere als in AutoIt, habe ich wenigstens dort mein "on error goto". Da in dieser Programmiersprache mit Hirn integriert (ansonsten ist VBA gegenüber AutoIt Lichtjahre "hintendran"), gibt es bei dessen Verwendung weder "fragwürdige Sprunganweisungen", noch Spaghetticode, und auch, selbst wenn in Funktionen verwendet, keine Speicherleaks oder gar Pufferüberläufe.
Mein Fazit zu GOTO:
Wenn ich es dann benutzen könnte, wenn ich es bräuchte, wäre ich zufrieden!
-
Hi, Oscar!
Klasse Idee! Ich finde da bestimmt noch einiges, aber zunächst:
Mein absoluter Favorit, das Umbenennen der Feldnamen der $TagBitmapInfo-Struct-KONSTANTEN

vorher:
$TagBitmapInfo="struct;dword Size;long Width;long Height;word Planes;word BitCount;dword Compression;dword SizeImage;long XPelsPerMeter;long YPelsPerMeter;dword ClrUsed;dword ClrImportant;endstruct;dword RGBQuad[1]"
nachher:
$TagBitmapInfo="struct;dword biSize;long biWidth;long biHeight;word biPlanes;word biBitCount;dword biCompression;dword biSizeImage;long biXPelsPerMeter;long biYPelsPerMeter;dword biClrUsed;dword biClrImportant;endstruct;dword biRGBQuad[1]"
Was letztendlich bei mir dazu geführt hat, verstärkt die Werte, also gewissermaßen die "evil Numbers" zu verwenden. (DAS war bestimmt nicht im Sinne des Erfinders....)
Statt
$tBMI = DllStructCreate($tagBITMAPINFO)
DllStructSetData($tBMI,"biWidth", $iwidth)
also
DllStructSetData($tBMI, 2, $iwidth) ;hier ist es völlig egal, welche Autoit-Version verwendet wird
oder auch statt
_WinAPI_BitBlt($DC_gui, 0, 0, 256, 256, $DC_bitmap, 0, 0, $srccopy)
nun
_WinAPI_BitBlt($DC_gui, 0, 0, 256, 256, $DC_bitmap, 0, 0, 0xCC0020) ;nur wegen der einen Konstanten $srccopy eine komplette UDF laden.....neeeeee^^
Denn diese Konstanten (sic) kommen nicht aus der Autoit-Welt und/oder sitzen in irgendwelchen UDF´s, sondern werden seit Anbeginn aller Zeiten als Parameter in den M$-Funktionen verwendet.
-
Die Last die auf den Kernen verteilt wird wird ganz allein von Windows entschieden.
Eben, und imho sollte (muss) das ein modernes BS auch so machen!
Wieso sollte ein Chiphersteller seine Technik für Benchmarks optimieren, wenn diese (oder sogar das Betriebssystem) nicht die volle Kapazität der CPU testen können.
Das wurde "früher" gerne gemacht, kam aber raus und sorgte für schlechte Publicity^^.
Man sollte aber im Hinterkopf behalten, dass es SO GUT WIE KEINE Software auf dem Markt gibt, welche das von mir im Script gezeigte Szenario, also volle Last über eine (in Prozessorzeit) unendlich lange Zeit, vollführt!
Über ein Bild, völlig egal in welcher Auflösung, jagd man einen völlig egal wie programmierten Filter. Das dauert auf einem Singlecore wegen mir einige Sekunden, bei einem Multicore ist das dann Faktor x schneller. Punkt. Niemand, aber auch niemand (Otto-Normalo-PC-User) braucht heutzutage die brachiale Leistung eines Core i5/i7/Ryzen. Gebraucht wird von diesen Usern ein brachial hoher Takt für Single-Core-Leistung, und genau DAS ist ein RIESEN Unterschied!
Während ich diesen Text schreibe, liegt mein Prozessor zwischen jedem Tastenanschlag 99,999% aller Takte im C6, also TIEFSCHLAF! Da juckt es Windows überhaupt nicht, zwischen den aktuell 185 Prozessen und ca. 2000 Threads hin- und herzuschalten. Aber wehe EINER dieser Prozesse verlangt nach (voller) Leistung, dann müssen die anderen "warten". Jeder PC-User, egal mit welchem High-tech-Prozessor kennt die Trägheit des BS, wenn bsw. "fette" Windows-Updates im Hintergrund installiert werden.
und statt eines Threadrippers
mich nach einem im Singlecorebetrieb möglichst flotten 4 Kerner umsehen(falls man sowas Altes noch kiregt) oder den Publikumsliebling Ryzen 5 1600 nehmen.
Tja, imho ist der Threadripper der ideale Prozessor für eine Workstation mit entsprechender Software. Und da übersteigt der Preis der Software die Hardware idR um ein Vielfaches!
Meine Anforderungen sind nicht die höchsten, zum Zocken brauche ich es nicht unbedingt, aber Filme encoden(HD-Material)
braucht doch einiges an Leistung oder auch Spectral-Wave-Editing ist auch sehr Leistungshungrig.
Wenn du die Möglichkeit hast, schau mal ob du für die Software auf dem jeweiligen Prozessor entsprechend Benchmarks bekommst. Fürs "reine" Zocken ist das so oder so völlig unerheblich^^
Filme encoden(HD-Material) oder auch Spectral-Wave-Editing könnten je nach Programmierung von (je mehr desto besser) "vielen" Cores profitieren.
Versuch macht kluch

Btw., der Ryzen 5 1600X hat beides, gute Singlecore- als auch sehr gute Multicore-Performance. Out of the Box. Wenn du übertaktest, dann ist der 1600 ca. 10%billiger und letztendlich genau so schnell wie der 1600X.
Also wie immer....
die Glaskugel wirds schon richten
-
Nach diesem Ergebnis würde mich und vermutlich auch andere brennend interessieren ob es unter den diversen
Linuxen gleich beschissen aussieht.
Weil mir das Thema keine Ruhe gelassen hat, habe ich mehr oder weniger intensiv recherchiert.
So wie es aussieht, ist das ein Windows- und weniger ein Linux-Problem! Allerdings gibt es seit November schon einen Fix, welcher bei einigen Multicore-Spielen die FPS um bis zu 15% gesteigert hat.
Weiterhin gibt es Programme zum rumspielen mit den Windows-Einstellungen, bspw. Mercury oder Lasso.
Damit kann man u.a. SMT (Simultaneous Multithreading) ausschalten, hat also nur "echte" Cores und kein (Intel-) Hyperthreading.
Für den Otto-Normalo Computerklimperer ist das sowieso alles nur theoretisch, der freut sich wie ein Schneekönig über seine "fette" CPU und Grafikkarte und benutzt dann die Programme der Softwarehersteller, welche natürlich um der Problematik wissen und somit Softwaretechnisch ALLES dafür tun, dass die Programme "geschmeidig" laufen. Die wären ja ehrlich gesagt auch bescheuert, wenn sie einen Haufen Arbeit in die Entwicklung von Multithreading-Software investieren würden und dann irgendein Spinner auf die Idee käme, das Programm in gleicher Geschwindigkeit auf einem Singlecore auszuführen!
DAS wird unterbunden, indem den verfügbaren Threads nur "kurze" (wie im ursprünglichen AutoIt-Script gezeigt) Zeitscheiben zur Verfügung gestellt werden. Man achtet also seitens Software(ersteller) peinlich genau darauf, Multithreading nur dann einzusetzen, wenn es einen messbaren Vorteil bringt, also bei einfachen und "kurzen" bzw. gut parallelisierbaren Algorithmen.....
Aber genau DIE wären ja per OpenCL bzw. CUDA wesentlich schneller auf einer GPU umzusetzen
Abgesehen von Algorithmen, welche besser auf einer CPU skalieren, aber das sind imho die großen Ausnahmen.Will sagen, einem "Otto"-Normalo reicht ein hochge(über)takteter billigst-Dual/Quadcore für seine "Standard"-Programme.
Abgesehen von Anwendungen, die auf die Verwendung möglichst vieler Kerne ausgelegt sind, macht ein Mehrkernprozessor heutzutage keinen Sinn!
Weiterhin hatte ich Kontakt mit einigen Leuten, welche intensiv sog. "Number-Crunching" betreiben. Solange der Algorithmus die Verwendung von OpenCL oder CUDA auf Grafikkarten einschränkt (denn da können die besten CPU´s keinen Blumenpott gewinnen) und somit auf CPU´s "gecruncht" wird, überlässt keiner der Programmierer dem BS (egal welchem) das Kommando über die Threads! Will heißen, der Programmierer ermittelt zuerst die Anzahl der verfügbaren Cores, erstellt dann die entsprechende Anzahl Threads und ordnet diese dann explizit (wie schon oben angesprochen per SetProcessAffinityMask() ) den einzelnen Kernen zu. Wenn man das exzessiv betreibt und bspw. einem Quadcore die 4 Kerne VOLL auslastet....dann....genau, bleibt dem BS keine "Zeit" bzw. Rechenpower. So etwas nennt man dann "einfrieren", da zuckt dann nicht mal mehr der Mauszeiger (der sowieso bei dieser Art Rechnerei niemals sichtbar ist, Console ftw
). Ergo startet man die Berechnung und muss halt warten, bis das Ergebnis erreicht wird!Jedenfalls hat mich das auf die Idee gebracht, die einzelnen Threads im AutoIt-Script an die (n-1, ein Kern soll für Windows bleiben) verwendbaren Kerne explizit zu binden, also das Core-hopping einzuschränken. Dann werden bei einem Dualcore somit nur ein Kern, bei einem Quadcore nur drei Kerne usw. benutzt, und zwar exclusiv. Damit müsste dann, WENN es das BS überhaupt zulässt(!), die zu erwartende Laufzeitverbesserung eintreten.
Das erklärt aber auch warum Intel CPU's bei vielen Benchmarks so stark sind, weil eben alles Single-Threaded
optimiert ist.(CPUs und Betriebs-System)
hehe, genau DAS ist das Problem. Die Software könnte seit Jahrzehnten wesentlich schneller sein, wenn die Programmierer bzw. die Compilerhersteller die Funktionen der CPU´s auch nur annähernd ausnutzen würden. Aber ich denke, da hackt die eine Krähe der anderen kein Auge aus. Hardware wird sowieso für die Anwendungen produziert, die Geld in die Kassen spülen, also Militär und Überwachung. Und die Software für genau diese Anwendungen wird von Spezialisten erstellt, welche jedes kleine Quentchen Performance aus der Hardware rausholen (können). Und ich glaube nicht, dass bei diesen Anwendungen ein "Standard"-Windows(Server) oder Linux verwendet wird.
Ich werde wohl ab dem nächsten Rechner auf Linux wechseln müssen, denn Windows 10 ist einfach ein nicht
entschuldbarer schlechter Witz von Microsoft und dort eben gerne mit einem AMD Ryzen ThreadRipper.
Dann fehlt nur noch eine Autoit-TRE Version und sonst eben GoLang und das als Google-Hasser.
Alternativ schau dich mal im Lager der Anbieter von Rechenleistung um. Wo ist denn das Problem, für 500€ einen PC zu kaufen, dort Software zu schreiben und diese dann bspw. auf Amazon- oder Google- oder wasweissich-Rechenzentren mit x-tausenden von Kernen/Threads laufen zu lassen. Selbst wenn diese Dienstleistung ein paar Euros im Monat/Jahr kosten sollte, kommst du da WESENTLICH billiger weg wie mit einem aktuellen Multicore-Prozessor. Wobei die Threadripper schon vergleichsweise günstig sind. Aber kannst du diese vielen Kerne überhaupt "sinnvoll" ausnutzen?!
Aber Recht hast du, um Windows beim exzessiven Core-hopping zuzuschauen, ist das Geld zu schade....

-
Hi zusammen,
habe soeben etwas herausgefunden, was mich an der Konzeption von Multithreading "etwas" (ziemlich) zweifeln lässt. Kann natürlich am "neuen" Ryzen liegen...oder an Windows, Diskussion dazu bzw. tiefergehende Infos (falls jemand welche hat) sind ausdrücklich erwünscht^^
Ich habe, um den Ryzen auszuloten, das Programm HWiNFO64 runtergeladen und mir dort die Anzeige der "Sensors" auf den Desktop gelegt. Beim Ryzen 5 1600 werden demnach 12 Threads (6 Cores a 2 Threads) angezeigt. Bei "Standardprogrammen", welche definitiv nur einen bis maximal 2 Threads beanspruchen, verteilt Windows die Last quer über alle Threads, da der Ryzen bei "kalten" Cores diese bis zu 500Mhz übertakten kann. Im Taskmanager dümpelt die Last bei voll rödelndem Excel oder diversen Spielen oder Prime95 mit einem Thread bspw. bei 8-10%. Soweit normal. Bei HWiNFO sieht man sehr schön, wie Windows das Core-hopping betreibt, also fleissig die Last von einem Core auf den nächsten schiebt, die anderen haben dann halt weniger bis nichts zu tun.
Jetzt wollte ich aber mal alle Kerne glühen sehen und habe mich auf mein Script in diesem Thema hier besonnen.
Script ausgeführt, alles paletti, Zeiten s.o.
Jetzt wollte ich die Laufzeit erhöhen um bei HWiNFO zu sehen was denn auf den Cores so passiert und wurde "etwas" (ziemlich) überrascht!
Nach sukzessiver Erhöhung von $n (Anzahl Durchläufe in Zeile 91 des Scripts) stellte ich fest, dass bei Ausführung von einem bzw. zwei Threads die Zeiten nur ca. 1/4 bis 1/3 vom 3., 4., 5., ...24. Thread waren! Wie kann das sein? Bisher waren doch bei höherer Anzahl benutzter Kerne die Zeiten immer niedriger geworden?!
Nach einigen Tests, wobei ich im Taskmanager und auch auf HWiNFO die Cores zu 100% ausgelastet sah, habe ich $n auf die größte mögliche 32Bit-Zahl, also 0xFFFFFFFF gesetzt. Mit diesem Ergebnis:
Spoiler anzeigen
@@ Debug(91) : $n = -1
Threads: 1 Time: 5739.9ms PI: 3.141592653468
Threads: 2 Time: 5758.2ms PI: 3.141592653533
Threads: 3 Time: 5834.6ms PI: 3.141592653558
Threads: 4 Time: 5957.7ms PI: 3.141592653557
Threads: 5 Time: 6324.2ms PI: 3.141592653580
Threads: 6 Time: 7159.6ms PI: 3.141592653570
Threads: 7 Time: 7946.1ms PI: 3.141592653573
Threads: 8 Time: 8774.5ms PI: 3.141592653573
Threads: 9 Time: 9370.6ms PI: 3.141592653571
Threads: 10 Time: 9920.8ms PI: 3.141592653585
Threads: 11 Time: 10863.7ms PI: 3.141592653576
Threads: 12 Time: 11574.2ms PI: 3.141592653582
Statt mit steigender Anzahl Threads schneller zu werden, benötigt das Programm bei Aufteilung auf 12Threads (also je 1/12 Last auf alle der 12 verfügbaren Cores/Threads) doppelt so lange, als wenn man "nur" einen einzigen Thread laufen lässt....
Dafuq. Genau dafür braucht man Multithreading NICHT!
Schuld ist imho Windows(10 home), welches natürlich intensives Core-hopping betreibt, und das mit komplett ausgelasteten Kernen
. Selbst wenn ich jetzt per SetProcessAffinityMask() (oder im Taskmanager) AutoIt nur 3 Cores statt 6 zur Verfügung stelle, verschlimmert sich das Problem nur....der Windows Scheduler wechselt fleissig alle paar Millisekunden den Core, und je mehr er davon hat, desto aufwendiger wird die Verwaltung....bis letztendlich bei der ganzen Verwalterei keine Rechenzeit für das Programm übrig bleibt....
.Irgendetwas läuft gewaltig schief, aber was?

Ideen? Infos?
-
Hi,
wieso machst du das nicht per VBA? Genau dafür gibts das...
-
Hi zusammen,
anbei Vergleich von Laufzeiten für einen AMD Ryzen5 (ohne X!) ohne Übertakten....(Aldi-PC Medion P56000 für runtergesetzt 400€ )
Auch kein Unterschied zwischen AVX und SSE, naja, hätte mich ehrlich gesagt auch gewundert^^
Aber im direkten Vergleich zu den sonst so schnellen Intels (bspw. hier) ist das Faktor 2.5 schneller....
Das Multithreading sieht auch gut aus, 6 Cores mit HT, beim Script von hier mit 1000000000 Durchläufen kommen folgende Ergebnisse raus
Spoiler anzeigen
Threads: 1 Time: 664.4ms PI: 3.141592652586
Threads: 2 Time: 337.1ms PI: 3.141592652591
Threads: 3 Time: 226.2ms PI: 3.141592652598
Threads: 4 Time: 182.8ms PI: 3.141592652593
Threads: 5 Time: 191.3ms PI: 3.141592652591
Threads: 6 Time: 175.0ms PI: 3.141592652588
Threads: 7 Time: 159.2ms PI: 3.141592652589
Threads: 8 Time: 145.4ms PI: 3.141592652586
Threads: 9 Time: 132.4ms PI: 3.141592652587
Threads: 10 Time: 120.8ms PI: 3.141592652590
Threads: 11 Time: 122.5ms PI: 3.141592652589
Threads: 12 Time: 116.7ms PI: 3.141592652588
Threads: 13 Time: 122.2ms PI: 3.141592652590
Threads: 14 Time: 127.4ms PI: 3.141592652590
Threads: 15 Time: 120.6ms PI: 3.141592652591
Threads: 16 Time: 115.2ms PI: 3.141592652590
Threads: 17 Time: 116.9ms PI: 3.141592652589
Threads: 18 Time: 120.1ms PI: 3.141592652589
Threads: 19 Time: 122.5ms PI: 3.141592652590
Threads: 20 Time: 123.8ms PI: 3.141592652589
Threads: 21 Time: 116.5ms PI: 3.141592652590
Threads: 22 Time: 123.7ms PI: 3.141592652590
Threads: 23 Time: 118.5ms PI: 3.141592652590
Threads: 24 Time: 117.9ms PI: 3.141592652589
also mit Multithread fast Faktor 5 schneller als Singlecore. Würde meine Annahme bestätigen, dass sich Windows immer einen Thread reserviert.
Fehlen nur noch die Programme, die diesen Prozessor komplett ausnutzen
-
Sorgen mache ich mir deswegen nicht - ich gucke nur gern ob es sich optimieren lässt.
Das ist auch völlig in Ordnung so....
Liege jetzt bei ~33Mb pro Stunde - für etwas was nur daheim am PC läuft also okay, wenn auch irgendwie ärgerlich wenn man eigentlich nur <1Mb davon braucht.
DA MUSSTE ICH LAUT LACHEN!

Mach mal eine x-beliebige Seite im ach so dollen Internetz auf und guck dir den Code an und dann frag dich mal, wieviel Promille von diesem Müll eigentlich ein Mensch braucht! Und den ganzen unnützen Dreck muss man runterladen um letztendlich nur auf einen Link zu klickern um somit weiteren Müll-Download zu kreieren.

-
Wenn man bedenkt, der Inhalt hat nur 4-5kb, kommt da schon einiges an unnötigem Datenvolumen auf
5 kbytes sind 5kbytes, wenn du die jede Sekunde herunterlädst, dann sind das 18MB in der Stunde. Stunde wohlgemerkt! Und da machst du dir einen Kopf wg. Netzwerkauslastung?
-
Du brauchst also nicht in die Hände spucken und eine schnelle ASM Version coden.
...abwarten^^
Bei mir ist auf 3 Rechnern trotz 80-120FPS bei der AutoItversion immer noch eine unterschiedliche Geschwindigkeit im Endloszoom festzustellen. Im Browser gibt es weder (Mikro-) Ruckler noch dieses "pumpen".
Ich habe jetzt die schleife eingehend ausgestoppt und festgestellt, dass die Schleife
CodeFor $e = 0 To 2 $d = $v - $q / 2 * $c $f = $w - $r / 2 * $c $g = $q * $c $l = $r * $c $hObj = _WinAPI_SelectObject($hMemDC, $a[$e]) _WinAPI_StretchBlt($hDC_backbuffer, $d, $f, $g, $l, $hMemDC, 0, 0, $iW, $iH, $SRCCOPY) $c *= 0.5 Nextmassive Unterschiede bei den einzelnen Stretchblt-Zeiten hat! Massiv heisst, der jeweils erste Stretchblt dauert ca. 5-10x länger als die beiden folgenden?!
Ich untersuche das mal genauer, inwieweit _WinAPI_SelectObject($hMemDC, $a[$e]) da einen Anteil dran hat. Ich vermute stark einen Zusammenhang mit dem darauffolgenden _GDIPlus_GraphicsDrawStringEx bzw. Bitblt.
-
Alphablend hatte ich u.a. gecoded, war SEHR schnell, aber Skalierung? Bestimmt hatte ich aber auch so eine Funktion irgendwo....schaumamal, ansonsten bietet sich SSE wirklich an, 4 (in 64-Bit wären es
Pixel gleichzeitig in einer Handvoll Takte zu berechnen hätte was.Mein Prozessor packt gerade so 30-40 FPS.
Mit Irrlicht würde das bestimmt mit paar 1000 FPS laufen.
OpenCL/OpenGL ftw.
-
Ja, die gibt es...
...und wird als nächstes in Assembleit eingebaut!
Ich würde dann aber das ganze als SciTE-Plugin in Lua schreiben. Die gewünschten Optionen müsstet ihr dann mal zusammen stellen.
wäre sicher eine feine Erweiterung von Scite

-
Ja, daher ein "ASM-Tidy". Vielleicht gibt es ja so etwas schon "fertig", ggf als Programm/Script.
Das Autoit-Tidy zerschiesst ja leider den eingerückten ASM-Code. Ich frage mal an, ob es in Tidy eine Option gibt bestimmte Teile des Scripts von der Tidyfunktion auszunehmen.
-
Das Stretchblt() ist, GDI+-typisch SCH***-langsam

Bei mir ( i7-7500U CPU @ 2.70GHz FullHD) dauert der Stretchblt() sagenhafte 25-35ms. Das BitBlt() gerade mal 1 ms....
Das wäre doch für Oscar ne schöne Übung für SSE-Befehle in ASM

-
Oscar ,
wie gesagt, AlignComment richtet "automatisch" aus, auch die in Regions eingepackten Kommentare.
Über ein "Tidy" sollte man sich aber auch Gedanken machen.
Eigentlich wäre es garnicht mal schlecht, eine wieauchimmer-Ausrichtung der Kommentare in AssembleIt zu integrieren.
Ich haue nach einigen Zeilen Codeänderung sowieso reflexartig auf F4, wäre mal zu überlegen das zu F5 dazuzupacken....
Ich kann hier gerade wie gesagt kein AutoIt testen aber folgende Zeile aus deinem eigenen Skript - behandelt dein Tool diese korrekt?:
Ja.
Schönes Regex übrigens, hab ich mir ausgedruckt (kein Witz) und abgehängt. Damit man, bevor man dran denkt die TODO´s abzuhandeln, beim Ordner aufschlagen direkt sieht, wo der Hammer hängt

alle AutoIt-Comments (und da gehören halt die Blöcke mit dazu) per RegEx sauber zu matchen.
Nicht mehr - aber auch nicht weniger. Ist OT ich weiß. Aus meinem Pattern lassen sich die Blöcke aber ganz fix entfernen wer das möchte.
Klasse!