1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Andy

Beiträge von Andy

  • Assemblercode - Noch optimierbar?

    • Andy
    • 2. Dezember 2016 um 19:16

    Bin gerade auf einem Tablet mit Atom Z3735F@1300Mhz unterwegs und habe mal die beiden Versionen FPU und SSE verglichen. Ernüchterung sondergleichen, beide annähernd gleich schnell!
    Kurz mal bei Agner Fog geblättert, nun ist auch klar warum!
    Der SSE Befehl DIVPD, welcher gleichzeitig zwei 64-Bit-Double dividieren kann, wird im Kapitel für den Atom folgendermaßen erwähnt:

    Zitat von http://www.agner.org/optimize/microarchitecture.pdf

    Division is slow and not pipelined. A single precision scalar floating point division takes 30clock cycles. Double precision takes 60 clock cycles. A 64-bit integer division takes 207clock cycles.

    60 Takte für eine Division....ohne Worte...die "richtigen" Prozessoren machen das in 15-20 Takten (//EDIT wenn pipelined genaugenommen dann in 6-7 Takten) , also mindestens 3-4x schneller! Weiterhin sind auch die ADDPD nicht pipelined, das fällt aber garnicht ins Gewicht!

    Wenn man optimiert, sollte man also auch die Plattform im Auge behalten, ansonsten kann man sich die Arbeit sparen :rtfm:
    Allerdings kann es aber auch sein, dass man auf einem bestimmten Prozessor ohne großartigen Gewinn optimiert, und dieser Code aber auf einer anderen Maschine eine immense Beschleunigung erlebt!
    Knowhow ist durch nichts zu ersetzen, außer durch mehr Knowhow :D

  • Assemblercode - Noch optimierbar?

    • Andy
    • 1. Dezember 2016 um 20:42
    Zitat von chesstiger

    Die Zeitmessung per Linux' time haben wir deswegen gewählt, damit nicht in jeder zu testenden Sprache noch die Zeitmessung selbst implementiert werden muss. Dass da auch einiges an Overhead gemessen wird, ist klar. Das war aber in diesem Moment die praktikabelste Lösung.

    Aus dem Bauch raus würde ich vermuten, dass der Overhead Programm laden/starten/beenden im Bereich von 2-4 Millisekunden liegt...und da du bei jedem zu testenden Programm diesen Overhead hast, ist sogar mal egal, wenn der Wert um eine Handvoll Millisekunden driftet. Also alles im grünen Bereich!


    Zitat von chesstiger

    Ich habe meinen Code nach euren Vorschlägen ein wenig optimiert.

    Hut ab! :klatschen:
    Nachdem ich deinen ursprünglichen Code nach FASM portiert hatte um direkt zu vergleichen, hatte ich festgestellt, dass dein ursprünglicher Code schon sehr schnell war!
    Wenn man die Laufzeiten analysiert (ich benutze dazu keine Zeitmessung, sondern zähle per RDTSC Takte) dann stellt man fest, dass sich die vermeintlichen "teueren" Speicherlese/schreibebefehle gar nicht so arg auswirken. Das hat einfach damit zu tun, dass bspw. die Schleifenzählvariablen in einer extra Pipeline parallel zu den FPU-Befehlen abgewickelt werden. Dazu liegen die Variablen entweder im Level1-Cache oder auf dem Stack, welcher idR. auch immer gecached ist! Ausführungszeit ca. 1-2 Takte pro DWORD laden!
    Im Vergleich zu den ca. 30-40 Takten für einen einzigen FDIV/FIDIV fällt das nicht sonderlich ins Gewicht.
    Daher hatte ich auch keinerlei Ambitionen, dort in eine Optimierung zu investieren, mein FPU-Code sollte nur zeigen, wie man den FPU-Stack nutzen kann.

    Zitat von chesstiger

    Allerdings zeigen sich bei mir ein paar interessante Phänomene.

    Gratuliere! :thumbup:
    Du hast begriffen, um was es geht! :thumbup:
    Ich bin davon überzeugt, dass dir die vergangenen Stunden für die Analyse und das rumprobieren an deinem ASM-Code für dein gesamtes weiteres Programmiererleben (vor allem mit HLL´s) viele Vorteile bringen werden.
    Wenn schon allein für diese "Pillepalle"-Anwendung mit der sehr kleinen Schleife so immense Unterschiede in der Laufzeit (vgl. UEZ´s erste Compilerversionen) feststellbar sind, was bringen dann erst Optimierungen für lange rechenintensive Schleifen!? 8)

    Im Grunde ist natürlich völlig egal, ob das Programm einige Millisekunden mehr oder weniger benötigt. Aber eine Beschleunigung um Faktor 3 für gewisse Anwendungen (bspw. Grafikfilter/analyse) ist ein definitives Kaufkriterium! Und damit wird dann Geld verdient...bestenfalls dein eigenes oder das deines Arbeitgebers ;)

  • Assemblercode - Noch optimierbar?

    • Andy
    • 26. November 2016 um 12:59

    Kurze Frage an alle, hat schon jemand die "neuen" (jaja, die gibts auch schon einige Jahre) AVX und/ oder FMA-Befehle ausprobiert?
    Leider unterstützt mein Laptopprozessor diese Features nicht.
    Imho sollte sich mit diesen Befehlen erstens alleine durch die Verdopplung der Registerbreite bei AVX (256Bit statt 128 wie bei SSE) die Berechnung durch 4 statt 2 gleichzeitiger Berechnungen verdoppeln! Der RCP (reziprok)-Befehl ist dort auch voerhanden....
    Ob dann nochmal durch die Verwendung von FMA (a=b+c*d in einem Takt) eine Beschleunigung erreicht werden könnte, ist die Frage?!

    Die innere Schleife zur Berechnung von Pi/4 erfolgt ja zzt in 4 Prozessorbefehlen

    Code
    1.0 ins Register laden
    1.0/positive und 1.0/negative berechnen
    positive+4 und negative-4 berechnen
    PIpositive+=positive und PInegative+=negative

    Diese Schleife kann man bei AVX genau so beibehalten, da man nun aber 4 statt 2 Double in einem Register unterbringen kann, halbiert sich die Anzahl der Schleifendurchläufe =>doppelte Geschwindigkeit! DOPPELT!

    Die Frage ist, ob FMA zu benutzen ist, also a=b+c*d in einem Takt und das noch serialisierbar hat ja was!

  • Raupis Geburtstag

    • Andy
    • 26. November 2016 um 10:57

    Glücklichen Herzwunsch und alles Gute wünsch ich dir!
    Auf das du noch lange deinen Hammer schwingen kannst!
    [Blockierte Grafik: http://www.smiliesuche.de/smileys/hammer/hammer-smilies-0003.gif]

    //EDIT
    Die passende Musik dazu
    https://www.youtube.com/watch?v=sqYzI8vMG_0

  • Assemblercode - Noch optimierbar?

    • Andy
    • 24. November 2016 um 00:03

    Oki, hier die EXE meines Assemblercodes als FPU-Lösung aus Post #6 als Consolenanwendung in 1536 Bytes....Der identische Assemblercode, also auch knapp 1kByte in eine AutoIt-EXE kompiliert, ist knapp 1,15MB groß, also ca. 1000 (tausend! ) mal größer :whistling:
    Die in der CMD angegebene Zeit ist natürlich die reine Laufzeit des Codes (ohne das Laden der Exe zu berücksichtigen, das ist imho auch nonsens)
    Pi_calc_Andy.zip

    Bei mir hat Avira angefangen, irgendwelche Trojaner zu entdecken, als ich in den ASM-Code die Zeile
    NUMBER dq 0.0
    eingefügt hatte...damit wird nichts weiter gemacht, als 8 Bytes mit Nullen zu füllen ||
    Wer will, kann die Datei einfach in FASMW laden und F9 drücken...

    Zitat von chesstiger

    Ich probiere morgen mal das ein oder andere hiervon aus und schaue mal, ob das noch was bringt.


    Ich werde bei der SSE/SIMD-Version Loop-Unrolling testen, und dann auch nicht die Zeit messen, sondern die benötigten Prozessortakte per RDTSC. Da lässt sich dann wesentlich besser optimieren, wenn man bspw. aus 10 Durchläufen den schnellsten nimmt.
    //EDIT Loop unrolling und umsortieren bzw. "parallelisieren" (reorder/pairing) in der Instruction-Pipeline bringt zumindest bei meinem Prozessor nichts...
    Ich habe aktuell 5.22 Prozessortakte pro Schleifendurchlauf. Da der sub ecx,1 und das anschließende jnz _loop zusammen 0,77 Takte benötigen, bleiben für die 4 SSE-Befehle 4.5 Prozessortakte.
    Jetzt wird es interessant, denn das DIVPD benötigt allein 6.2 Takte!!! Durch die verschiedenen parallel arbeitenden Pipelines werden die Prozessorbefehle nicht "nacheinander" sondern wenn möglich gleichzeitig abgearbeitet. Man kann mehrere Zeilen völlig unnötiger Befehle in die Schleife einfügen, an der Laufzeit ändert sich...nichts!!!
    Daher ist es sinnvoll beim Optimieren, wenn man sich die die sog. Serialisierung vornimmt und ausrechnet, welcher Befehl am besten wo in der Reihenfolge steht...um die "teueren" Abhängigkeiten (dependencies) aufzulösen!
    http://www.agner.org/optimize/optimizing_cpp.pdf
    http://www.agner.org/optimize/optimizing_assembly.pdf
    http://www.agner.org/optimize/microarchitecture.pdf <-- DAS ist richtig klasse! Ich gehe davon aus, dass Compilerbauer dieses Dokument unter dem Kopfkissen liegen haben :thumbup:


    @Mars, natürlich habe ich deine EXE laufen lassen und auch versucht zu disassemblieren, daher auch die Info, dass die Datei eine 64-Bit-Code-EXE ist und auch SSE-Befehle nutzt!


    @Alle interessierten, und vor allem die, welche meinen, ein Compiler würde "automatisch" den besten Code erzeugen, ein (ihr kennt mich ja) ernst gemeinter Hinweis bzw. auch mal ein Grund, "nachzudenken".
    Mal angenommen, ein "cleverer" Compiler merkt bei der Analyse des Codes, dass sich eine bestimmte Variable immer weiter an PI annähert.
    Mit dem FPU-Befehl FLDPI, der aus 2 Bytes besteht und eine "Laufzeit" von 2-3 Prozessortakten hat, wäre PI auf 80bit genau bestimmt, und man könnte sich den Algorithmus sparen...
    Mal weiter angenommen, im Code wäre dieses PI "zu genau" für weitere Berechnungen, dürfte dann der Compiler die ungenaue "Berechnung" von PI mit einem "besseren" PI ersetzen um im Endeffekt ein wesentlich schnelleres und genaueres Ergebnis auszugeben?
    Was aber, wenn ich genau diese "ungenauen" Ergebnisse aber benötige, sollte ich als Programmierer dann die Wahl haben, "meinen" und genau diesen MEINEN Code generiert zu bekommen, oder doch den "optimierten" Code des Compilers?

  • Assemblercode - Noch optimierbar?

    • Andy
    • 23. November 2016 um 19:40

    Ich werfe mal SSE/SIMD in die Runde...
    Auf meinem AMD-Laptop 37ms bei 1.4Ghz, die Intels müssten da weit davonziehen, da das DIV dort massiv optimiert wurde

    AutoIt
    ;aligncomment=40
    ;~ #include <assembleit2_64.au3>
    
    
    #AutoIt3Wrapper_UseX64=n
    
    
    
    
    #cs Pi_Leibnitz
        Use32                                ;32Bit!
    
    
        mov ecx,[esp+4]                      ;n
        shr ecx,1                            ;n/2 es werden pro schleifendurchgang das positive und negative aufsummiert
    
    
        xorpd xmm4,xmm4                      ;0.0 _ 0.0 die summe dieser beiden wird PI/4
    
    
        mov eax,1
        movd xmm0,eax
        pshufd xmm0, xmm0, 0xE0              ;1   _ 1
        CVTDQ2PD xmm0, xmm0                  ;1.0 _ 1.0
    
    
        mov eax,-4
        movd xmm1,eax
        CVTDQ2PD xmm1, xmm1                  ;0.0 _ -4.0
    
    
        neg eax                              ;4
        movd xmm2,eax
        CVTDQ2PD xmm2, xmm2                  ;0.0 _ -4.0
        PSLLDQ xmm2, 8                       ;4.0 _ 0.0
        paddq xmm1,xmm2                      ;4.0 _ -4.0
    
    
        mov eax,-3
        movd xmm3,eax
        CVTDQ2PD xmm3, xmm3                  ;0.0 _ -3.0
        movdqa xmm2,xmm0
        PSLLDQ xmm2, 8                       ;1.0 _ 0
        paddq xmm2,xmm3                      ;1.0 _ -3.0
    
    
        _loop:                               ;so lange, bis ecx=0
        movdqa xmm3,xmm0                     ;1.0 _ 1.0
        divpd xmm3,xmm2                      ;1/1 _ 1/-3
        addpd xmm4,xmm3                      ;links positive rechts negative, die summe ist PI/4
        addpd xmm2,xmm1                      ;positive um 4 erhöhen, negative 4 subtrahieren
        sub ecx,1                            ;n=n-1
        jnz _loop                            ;wenn ecx<>0 dann _loop
    
    
        pshufd xmm5, xmm4, 0x4E
        addpd xmm4,xmm5                      ;PI/4 _ -PI/4
        mulpd xmm4,xmm1                      ;PI _ -PI
    
    
        movhpd qword[esp+8],xmm4             ;PI
    
    
        fld qword[esp+8]                     ;st0=PI
        ;~     _asmdbg_()
    
    
        ret
    
    
    #ce
    
    
    
    
    $n = 10000000
    
    
    
    
    ;Entweder der Einzeiler:
    ;~ $ret = _AssembleIt2("double", "Pi_Leibnitz", "uint", $n, "double", $pi)
    
    
    
    
    ;oder für das dllcalladdress
    ;~ $binarycode = _AssembleIt2("retbinary", "Pi_Leibnitz") ;gibt nur den assemblierten code zurück
    ;nur für dllcalladdress() benötigt, den binarycode braucht man nur ein mal erstellen
    
    
    
    
    $binarycode = "0x8B4C2404D1E9660F57E4B801000000660F6EC0660F70C0E0F30FE6C0B8FCFFFFFF660F6EC8F30FE6C9F7D8660F6ED0F30FE6D2660F73FA08660FD4CAB8FDFFFFFF660F6ED8F30FE6DB660F6FD0660F73FA08660FD4D3660F6FD8660F5EDA660F58E3660F58D183E90175EB660F70EC4E660F58E5660F59E1660F17642408DD442408C3"
    $tCodeBuffer = DllStructCreate("byte[" & StringLen($binarycode) / 2 - 1 & "]") ;reserve Memory for opcodes
    DllStructSetData($tCodeBuffer, 1, $binarycode)
    
    
    $pi = 0.0
    $t = TimerInit()
    $ret = DllCallAddress("double:cdecl", DllStructGetPtr($tCodeBuffer), "uint", $n, "double", $pi)
    $m = TimerDiff($t)
    
    
    ConsoleWrite(@CRLF & ": $pi Leibnitz = " & $ret[0] & @CRLF & ": Time [ms] = " & $m & @CRLF & @CRLF)
    Alles anzeigen

    Die 128Bit breiten XMM-Register werden in 2x64Bit (je ein double) aufgeteilt.
    In den linken 64Bit werden die positiven Teiler summiert, im rechten Registerteil die negativen Teiler.
    Die gesamte Schleife besteht AUS NUR 4 ASM-Befehlen!
    Nach der Schleife die beiden Registerhälften addieren zu PI/4 und mit 4 multiplizieren ergibt PI.

    Da die FPU intern mit 80 Bit Genauigkeit rechnet, aber bei SSE/SIMD nur 64 Bit zur Verfügung stehen, ergeben sich die "Unterschiede" in den letzten 3 Nachkommastellen.
    Geht da noch mehr? :theke:

  • Assemblercode - Noch optimierbar?

    • Andy
    • 22. November 2016 um 22:48
    Zitat von Mars

    Die ASM Version von Andy läuft bei mir in ca. 160ms. Damit ist sie knapp schneller als die Go variante.

    Hmmm, die GO-Variante ist 64-Bit und nutzt schon fleißig SSE-Befehle :D
    Kannst du 32-Bit-Code erzwingen und den dann mal bereitstellen? Ich gehe davon aus, dass der compilierte 32-Bit-Code kein Stück langsamer ist!

    Zitat von Mars

    Hab hier einen Intel Q6600 Prozessor mit 2,4ghz

    ggf sollten wir mal eine Suite zusammenstellen mit den einzelnen Programmen, dann könnte man auch vergleichen, welche Befehle auf dem einen oder anderen Prozessor schneller oder langsamer ausgeführt werden! So wie ich die "alten" Prozessoren kenne, hat AMD da klare Vorteile bei der FPU gegenüber INTEL gehabt. Aber ich denke die "neueren" INTEL´s werden da noch einiges schneller laufen!

  • Assemblercode - Noch optimierbar?

    • Andy
    • 22. November 2016 um 22:10

    Hier mal meine unoptimierte FPU-Version.
    Unoptimiert deswegen, weil allein das FDIV schon (je nach Prozessor) 40 (!!!) Takte benötigt....aber egal, eine schöne Fleißübung :D
    Allerdings habe ich es mir nicht nehmen lassen, KEINE einzige Speicherzelle zu verwenden :party: Selbst die Rückgabe an AutoIt erfolgt über das ST0-Register, wenn als Rückgabetyp "double" verwendet wird.
    Ca. 100ms auf meinem Laptop AMD A6-3400M APU, da sollte bei euren INTEL noch einiges gehen!

    Spoiler anzeigen
    AutoIt
    ;aligncomment=40
    ;#include <assembleit2_64.au3>
    
    
    #AutoIt3Wrapper_UseX64=n
    
    
    
    
    #cs Pi_Leibnitz
        Use32                                ;32Bit!
    
    
        finit                                ;FPU initialisieren
    
    
        mov ecx,[esp+4]                      ;n
        shr ecx,1                            ;n/2 es werden pro schleifendurchgang das positive und negative aufsummiert
    
    
        ;FPU-stack aufbauen
        fld1                                 ;st0=1
        fld1                                 ;st0=1 st1=1
        fadd st0,st1                         ;st0=2 st1=1
        fmul st0,st0                         ;st0=4 st1=1
        fld1                                 ;st0=1 st1=4 ;st2=1
        fld st1                              ;st0=4 st1=1 st2=4 st3=1
        fsub st0,st1                         ;st0=3 st1=1 st2=4 st3=1
        fchs                                 ;st0=-3 st1=1 st2=4 st3=1
        fldz                                 ;st0=0 st1=-3 st2=1 st3=4 st4=1
    
    
        _loop:                               ;so lange, bis ecx=0
    
    
        ;der stack muss am Anfang des loop so aussehen st0=PI/4 st1=negative st2=positive st3=4 st4=1
        ;in st0 wird PI gespeichert, st1 wird immer um 4 erniedrigt, st2 um 4 erhöht,
        ;st3 ist die schrittweite von 4 und st4 wird fürs reziprok 1/x benutzt
    
    
        fld st4                              ;st0=1 st1=0 st2=-3 st3=1 st4=4 st5=1
        fld st2                              ;st0=-3 st1=1 st2=0 st3=-3 st4=1 st5=4 st6=1
        fdivp st1,st0                        ;st0=1/-3 st1=0 st2=-3 st3=1 st4=4 st5=1
        ;pi speichern
        faddp st1,st0                        ;st0=-1/3=PI/4 st1=-3 st2=1 st3=4 st4=1
        fld st4                              ;st0=1 st1=PI/4 st2=-3 st3=1 st4=4 st5=1
        fld st3                              ;st0=1 st1=1 st2=PI/4 st3=-3 st4=1 st5=4 st6=1
        fdivp st1,st0                        ;st0=1/1 st1=PI/4 st2=-3 st3=1 st4=4 st5=1
        ;pi speichern
        faddp st1,st0                        ;st0=PI/4 st1=-3 st2=1 st3=4 st4=1
        ;4 zu st2 addieren und von st1 subtrahieren
        fld st3                              ;st0=4 st1=PI/4 st2=-3 st3=1 st4=4 st5=1
        fadd st3,st0                         ;st0=4 st1=PI/4 st2=-3 st3=5 st4=4 st5=1
        fsubp st2,st0                        ;st0=PI/4 st1=-3 st2=5 st3=4 st4=1
    
    
        sub ecx,1                            ;n=n-1
        jnz _loop                            ;wenn ecx<>0 dann _loop
    
    
        fld st3                              ;st0=4 st1=PI/4 st2=-3 st3=5 st4=4 st5=1
        fmul st0,st1                         ;st0=PI
    
    
        ;_asmdbg_()
    
    
        ;rückgabe bei double ist ST0
        ret
    
    
    #ce
    
    
    
    
    $n = 10000000
    
    
    
    
    ;Entweder der Einzeiler:
    ;$pi = _AssembleIt2("double", "Pi_Leibnitz", "uint", $n)
    
    
    
    
    ;oder für das dllcalladdress
    ;~ $binarycode = _AssembleIt2("retbinary", "Pi_Leibnitz")     ;gibt nur den assemblierten code zurück
    ;nur für dllcalladdress() benötigt, den binarycode braucht man nur ein mal erstellen
    
    
    
    
    $binarycode = "0x9BDBE38B4C2404D1E9D9E8D9E8D8C1D8C8D9E8D9C1D8E1D9E0D9EED9C4D9C2DEF9DEC1D9C4D9C3DEF9DEC1D9C3DCC3DEEA83E90175E5D9C3D8C9C3"
    $tCodeBuffer = DllStructCreate("byte[" & StringLen($binarycode) / 2 - 1 & "]") ;reserve Memory for opcodes
    DllStructSetData($tCodeBuffer, 1, $binarycode)
    
    
    
    
    $t = TimerInit()
    $pi = DllCallAddress("double:cdecl", DllStructGetPtr($tCodeBuffer), "uint", $n)
    $m = TimerDiff($t)
    ConsoleWrite(@CRLF & ": $pi Leibnitz = " & $pi[0] & @CRLF & ": Time [ms] = " & $m & @CRLF & @CRLF)
    Alles anzeigen

    Damit mal richtig Spass aufkommt, werde ich auch die SSE/SIMD-Variante in Angriff nehmen, ich vermute Zeiten um die 20-30ms, also Faktor 3-4 zum FPU-Code!
    Da werde ich auch "optimieren", d.h. nach Möglichkeit die Pipelines versuchen parallel zu füttern und auch "natürlich" keinerlei Speicherzugriffe :rofl: . Auf einen C(++)-Code mit einem "schnellen" Ergebnis bin ich schon mal gespannt, es soll ja Leute geben, die meinen, ein Compiler macht das automatisch...

    Und um dann komplett hardcoremäßig abzurocken könnte man mal versuchen, ob sich der Algorithmus so weit parallelisieren lässt, um per OpenCL auf einer Grafikkarte zu laufen.
    Aber da wird schon "Double" das Problem sein ;( , das ist ca. 20x langsamer als "Float".
    Für OpenCL würde ich auf einer 50€-Grafikkarte bzw auf meiner integrierten APU realistisch 3-4 Millisekunden anpeilen. Und dabei gehen noch 80% der Zeit für den Daten-Transfer von und zur Grafikkarte flöten X/

  • Assemblercode - Noch optimierbar?

    • Andy
    • 22. November 2016 um 13:27

    Hi,

    Zitat von chesstiger

    Ich glaube nicht, dass das noch jemand schlägt. Aber ich bin mir fast sicher, dass es da noch Optimierungsmöglichkeiten gibt. Da sich hier auch einige Leute schon ausführlich mit Assembler auseinandergesetzt haben, dachte ich, ich frage mal, ob jemandem noch etwas einfällt.

    Ich glaube schon, dass das noch jemand schlägt :D
    Optimierungsmöglichkeiten: Neben den von Mars angesprochenen Möglichkeiten fällt mir sofort auf, dass du den Stack der FPU nicht nutzt! Dies sind 8 "Speicherstellen" in Registerform! Mal davon abgesehen, dass die FPU-Befehle schon "schnarchlangsam" sind (dazu später mehr 8o ), speicherst du bspw. per fstp qword [pi], nur um es im Schleifenkopf kurz darauf wieder zu laden...mit [store]übrigens genauso...
    Clever wird der FPU-Stack eingesetzt, indem "Konstanten", bspw. [four], permanent im Stack liegen und die weiteren Berechnungen ausschliesslich mit den registern durchgeführt werden, ohne permanent in den Speicher zu schreiben bzw. zu laden.
    Das  fld qword [pi] gehört vor den Loop (zusammen mit den anderen benutzten Variablen), und das fstp qword [pi] hinter den Loop. Du ersparst dir damit alleine 2*10E6 Speicherzugriffe/Takte!

    Zitat von Mars

    (3.) Andy wird bestimmt noch irgendwas zum SSE sagen, was hier fehlt

    Und wie er das wird! 8o
    Die SEE-Befehle ADD/SUB/DIV werden in einem Takt abgewatscht, die schreien geradezu nach Benutzung! Und werden von jedem Prozessor, der in diesem Jahrtausend gefertigt wurde, unterstützt.
    Auch ggf. erforderliche Vergleichsbefehle gibt es in SSE.
    Ich werde dazu später mal ein Beispiel machen...
    Inwieweit man SIMD (Single instruction, multiple data) einsetzt, ist zu testen, da Algorithmusabhängig. Wenn man 2 Berechnungsschritte gleichzeitig in einem Register abwickelt, braucht man nur noch die Hälfte der Schleifendurchläufe/Berechnungen!

  • SciTE - Umlaute

    • Andy
    • 14. November 2016 um 07:00
    Zitat von Bitnugger

    Festzustellen, mit welcher Codepage eine Datei gespeichert wurde, ist ein Ratespiel. Mit absoluter Gewissheit lässt sich dass nicht ermitteln.

    genau das hatte ich weiter oben bereits geschrieben, Scite "versucht" die passende Kodierung zu bestimmen und passt den dargestellten Text entsprechend an! Imho sind die in Scite "voreingestellten" Kodierungen lediglich ein Hinweis....wer weiß?

  • Dienst - Suche - Programm, Verbesserungsvorschläge.

    • Andy
    • 13. November 2016 um 09:33

    Hi,

    Zitat von bazii

    Jeder der die Möglichkeit in einer Software für einen Datenexport mit datenschutzrelevanten Inhalten inne hat, könnte diese Daten missbrauchen.

    Man sollte sich diese Aussage, mit Hintergrund das der Ersteller in einem "Konzern" arbeitet mal PRAKTISCH vor Augen führen.
    Die Mitarbeiter in diesem "Konzern" dürfen weder (personenbezogene) Daten aus E-mails auslesen und bspw. in einer Textverarbeitung weiterverwenden. Speichern dieser E-Mails und Textdokumente ist aus Datenschutzrechtlichen Gründen also auch verboten. Ausdrucke auf Papier sind auch verboten, außer man deponiert diese Ausdrucke im konzerneigenen Tresor mit Zutrittkontrolle NUR GENAU FÜR DEN MITARBEITER, DER DIESES DOKUMENT ERSTELLT HAT!
    Fehldrucke werden sofort geshreddert.
    Weiterleitung von Mails erfolgt erst nach freigegebener Prüfung durch einen Datenschutzbeauftragten, um unbeabsichtigte Datenweitergabe zu erkennen/unterbinden...
    //EDIT da jeder Arbeitsplatz kameraüberwacht ist, soll ausgeschlossen werden, dass Mitarbeiter eine handschriftliche Abschrift des Bildschirminhalts erstellen können
    :whistling:

    Das ist nur ein kleiner Teil von Vorgängen, die BugFix nicht ohne Grund als "hanebüchen" beschrieben hat...
    Es geht um "unberechtigte Dritte". Wenn ich als Mitarbeiter eines Unternehmens eine Software X benutze und mit einem AutoIt-Programm auf die Daten(bank) des Programms X zugreife, um Arbeitsabläufe zu automatisieren, dann ist das keine "Weitergabe von Daten an unberechtigte Dritte!"

    [OT]Man sollte ehrlich sein...wieso wird einigen/vielen dabei unbehaglich, wenn jemand Zugriff auf große bzw. umfassende Datenmengen hat?!
    Weil von vornherein unterstellt wird, dass beabsichtigt oder unbeabsichtigt "Unsinn" mit diesen Daten angestellt wird oder zumindest werden kann!
    Mir wird ehrlich gesagt schlecht dabei, wenn es um Zusammenführung/Migration von Datenbanken geht. Und NOCH schlechter, wenn sog. "Spezialisten" versprechen, dass alles glatt läuft...[/OT]


    Zitat von autoBert

    Bin der Meinung, daß BW- oder Bundesweit jeden Tag gegen diese Richtlinien verstoßen wird, bin aber nicht bereit mich daran zu beteiligen, sprich zusätzliche Zeit/Geld für eine Zertifizierung zu investieren. Mein Programm hat natürlich eine Im- Exportfunktion im CSV-Format, ob diese sinnvoll und besrimmungssgemäß benutzt wird ist mir egal.

    Genau so sieht es leider in der PRAXIS aus...

    Ich hatte neulich Mitarbeiter in einem deutschlandweit bekannten Unternehmen geschult, welches auch noch an einen sog. Weltkonzern angeschlossen ist...
    Es ging eigentlich um eine Produktschulung, aufgrund weiteren Interesses habe ich die Schulung ausgeweitet.
    Essenz für mich nach einigen Stunden Diskussion: die Mitarbeiter dort haben KEINE Möglichkeit, sich Hilfsmittel in Form von Formularen/Protokollen/Tabellen selbst zu erstellen, da die Heeresleitung/EDV-Abteilung dies unterbindet/ablehnt. Externe Unternehmen damit zu beauftragen kommt auch nicht in Frage.
    Ende vom Lied "...wir können doch so nicht arbeiten..."
    Dass nur SEHR motivierte und gegen ihre Vorgesetzten gestählte Mitarbeiter sich Zuhause mit OpenOffice hinsetzen und die erforderlichen Hilfsmittel erstellen, kommt wohl garnicht oder nur selten vor. Daher hatte ich mich entschlossen, zu "helfen" und mal zu zeigen wie einfach es ist, sich solche Hilfsmittel zu erstellen. Auf meinem privaten Laptop wurde in Zusammenarbeit mit den dortigen Mitarbeitern ein auf die Bedürfnisse abgestimmtes Formular/Protokoll in OO erstellt. Per Beamer an die Wand geworfen, waren alle happy, aber das legte sich sehr schnell, als es darum ging, dieses Formular in Papierform baustellengerecht aufzuarbeiten.
    Mein privater Laptop durfte nicht ans Firmennetz, USB-Stick natürlich genausowenig. Formular im odt, xls oder PDF-format per Mail an einen Verantwortlichen schicken geht, aber der sitzt mehrere hundert Kilometer entfernt und die Dateien müssen erst "geprüft" werden... :Face:
    Ich wundere mich überhaupt nicht, wieso Deutschland keine Zuckerbergs, Gates, Otellinis uswusf. hervorbringt, denen wird schon in der Schule/Ausbildung ausgetrieben, PRODUKTIV zu arbeiten! Und im Berufsleben erst recht!

    Zitat von bazii

    Selbst bei Berufsgenossenschafts-Software zur Hinterlegung von Gefährdungsbeurteilungen nur mit Daten einer öffentllichen Einrichtung, ist beim Daten-Export ein Benutzernamen und ein vordefiniertes Passwort anzugeben, damit die dort erfassten Daten nicht jeder Sachbearbeiter selbst mit den hinterlegten Daten auf einen Stick ziehen kann. Das Thema wird bei uns sehr ernst genommen.

    Berechtigterweise!

    Zitat von bazii

    Ob jetzt allerdings beim Threadsteller im Dienstplan zukünftig datenschutzrelevante Eintragungen stattfinden ....

    ...ist zumindest fraglich / diskussionswürdig. Wenn ich als Vorgesetzter allerdings einen motivierten Mitarbeiter aus "fadenscheinigen" Gründen ausbremse, muss ich mich um fehlende Produktivität nicht weiter wundern....


    Für die "Datenschützer/beauftragten" hier noch einmal KLAR UND DEUTLICH die Aussage des TE im Startpost:
    Stoani schrieb:

    Zitat von Stoani

    Bisher war ein Zettel mit Telefonnummern dafür ausreichend,

    ein Zettel! Ein ZETTEL! OMFG, wirr haben völlig vergessen, dass die Mitarbeiter sich personenbezogene Daten AUFSCHREIBEN können, das muss aus datenschutzrechtlichen Gründen natürlich umgehend unterbunden werden...viel Spass dabei! :ironie:

  • Fenster erkennen

    • Andy
    • 13. November 2016 um 08:27

    Hi,
    es hilft extrem, wenn man sog. Debug-Meldungen (schreibt in die Konsole oder ruft eine Messagebox auf) in seinem Code verteilt, damit man sieht, was eigentlich passiert!
    Cursor auf die zu überprüfende Variable/Befehl, und dann ALT+D für eine Consoleninfo oder CTRL+SHIFT+D für eine Messagebox.
    In Scite gibt es ein Menü "Extras" dort befinden sich weiter Debug/Trace Funktionen, auch um alle auf einen Schlag wieder loszuwerden!
    JEDER Befehl in AutoIt gibt eine Rückmeldung, auf die man reagieren bzw. die man auswerten kann!
    Man schreibt also bspw. nicht "If WinExists(blablub) then" sondern

    AutoIt
    $IstFensterda = WinExists(blablub)  ;1 wenn Fenster da, 0, wenn nicht
    	ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $IstFensterda = ' & $IstFensterda & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    	if $IstFensterda = 1 then  'wenn Fenster erscheint, Messagebox
    		MsgBox(262144, 'Debug line ~' & @ScriptLineNumber, 'Selection:' & @CRLF & '$IstFensterda' & @CRLF & @CRLF & 'Return:' & @CRLF & $IstFensterda) ;### Debug MSGBOX

    Das Consolewrite erscheint bei jeder Fensterabfrage in der Console, die Messagebox erscheint, sobald Winexists() ein entsprechendes Fenster gefunden hat. Das "kostet" dich beim Programmieren genau 2 Tastendrücke, erspart dir und uns aber auch Zeit um Beiträge wie diesen zu erstellen/zu bearbeiten....

    Übrigens stehen in der (auch deutschen) Hilfe nützliche Hinweise, dort solltest du unter "Bemerkungen" bei WinExists() mal nachschauen.


    Weiterhin würde ich dir empfehlen, hinter JEDEM Befehl einen kurzen Kommentar einzufügen, damit DU nachvollziehen kannst, was der Befehl dort macht. Das weißt du nämlich nicht!

    Dein Programm macht genau das, was du beschrieben hast! In einer Endlosschleife wird, wenn ein bestimmtes Fenster erscheint, ein Programm XX geschlossen und danach wieder geöffnet!

  • WINAPI GetLogicalProcessorInformation

    • Andy
    • 12. November 2016 um 22:00

    @UEZ, in keinem der dort verlinkten Scripte finde ich etwas dazu, außer :

    Zitat von Ascend4ent

    GetLogicalProcessorInformation should report the right information too, but at the moment I don't know how to interpret it ....

    Die sind alle mit anderen Funktionen weitergekommen :D

  • WINAPI GetLogicalProcessorInformation

    • Andy
    • 12. November 2016 um 16:07
    Zitat von powerbass4

    Mit meinem Ansatz war ich voll auf dem Holzweg.....

    Da ich absolut kein C-Fuzzi bin, habe ich mir entsprechenden Code/Dokumentationen angeschaut und trotzdem nicht durchgeblickt ! :rtfm: <--hat auch nichts gebracht....
    Ich habe mir die _SYSTEM_LOGICAL_PROCESSOR_INFORMATION -Struct mit 48 Bytes vorgestellt (anhand des inhaltes des kompletten Speicherbereichs, daher auch die Aufteilung/Visualisierung mittels StringMid() ), allerdings nie begriffen, wie die Einzelteile mit der UNION korrespondieren...nachts um 2 dann ins Bett und geträumt....

    Nach 4h Schlaf besinnt man sich auf seine Fähigkeiten:

    Was IMMER, und zwar in jeder Programmiersprache funktioniert, ist Debugging!
    Also habe ich erst mal versucht, folgenden Code zu compilieren, was aber mit einem Linker-Fehler nicht funktionieren wollte (MinGW):
    https://msdn.microsoft.com/de-de/library/…4(v=vs.85).aspx

    Da nicht compilierbar, habe ich dann folgendes hingefriemelt:

    C
    #include <windows.h>
    #include <malloc.h>
    #include <stdio.h>
    #include <tchar.h>
      typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP {
          RelationProcessorCore,
          RelationNumaNode,
          RelationCache,
          RelationProcessorPackage,
          RelationGroup,
          RelationAll = 0xffff
        } LOGICAL_PROCESSOR_RELATIONSHIP;
      typedef enum _PROCESSOR_CACHE_TYPE {
          CacheUnified,
          CacheInstruction,
          CacheData,
          CacheTrace
        } PROCESSOR_CACHE_TYPE;
      typedef struct _CACHE_DESCRIPTOR {
          BYTE                 Level;
          BYTE                 Associativity;
          WORD                 LineSize;
          DWORD                Size;
          PROCESSOR_CACHE_TYPE Type;
        } CACHE_DESCRIPTOR;
      typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
          ULONG_PTR                      ProcessorMask;
          LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
          union {
              struct {
                BYTE  Flags;
              } ProcessorCore;
              struct {
                DWORD NodeNumber;
              } NumaNode;
              CACHE_DESCRIPTOR Cache;
              ULONGLONG        Reserved[2];
          } ;   /* anonymous union */
        } SYSTEM_LOGICAL_PROCESSOR_INFORMATION;
    int GET_THE_INFO (void)
    {
    ULONG_PTR groesse = 0;
     groesse = groesse +  sizeof (SYSTEM_LOGICAL_PROCESSOR_INFORMATION);       // oder  _SYSTEM_LOGICAL_PROCESSOR_INFORMATION oder CACHE_DESCRIPTOR um die Größen rauszufinden
    printf ("\nError %lu\n", GetLastError());
    printf("\nSize = %lu\n", (ULONG_PTR) groesse );
    return (0);
    }
    int main() 
    {
    	GET_THE_INFO();
    	return 0;
    }
    Alles anzeigen

    Nach geschmeidigem Hieb auf F8 (Compile and Execute) hat sich dann herausgestellt, dass die Struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION nur 24Bytes groß war!

    Dann fiel es mir wie Schuppen aus den Haaren und alles bekam Sinn:
    Jeweils 4 Bytes für ProcessorMask(ulong_ptr) und LOGICAL_PROCESSOR_RELATIONSHIP Relationship (eine Aufzählung, Typ ist UINT(-ptr)) sind zusammen 8 Bytes, der Rest musste die UNION sein.
    In der UNION wird der gleiche Speicher mit unterschiedlichen Typen belegt, der größte "zählt", also die beiden ULONGLONG (jeweils 8 = 16 bytes) Reserved[2].
    Der Rest war simpel, es wurde jeweils eine Struct "in" der UNION erstellt, mit entsprechenden Typen.
    "Alte Hasen" kennen mein Beispiel DllStruct Funktionen für Autoit

    Letztendlich sehe ich in diesem Vorgehen keinen großen Sinn, es ist beschissen zu lesen/verstehen und noch beschissener umzusetzen (man sehe sich den C-Code an!)
    Ich gehe mal davon aus dass jemand das so gemacht hat "weil er es kann" bzw. weil die Sprache das kann...naja :/

  • Sparen (erledigt)

    • Andy
    • 12. November 2016 um 14:24
    Zitat von chip

    Hochrisiskoanlagen gibt es weiterhin, der Unterschied ist lediglich, dass die Banken jetzt die Kunden entsprechend aufklären müssen.

    Das mussten die Banken schon immer! Es ändert aber nichts daran, dass die Summe des Geldes konstant ist, d.h. wenn jemand Gewinn macht, muss auf der anderen seite jemand dafür bezahlen! Das Geschäft läuft aber so, dass nur wenige gewinnen, aber viele dafür bezahlen müssen!
    Und dass dieses System so nicht funktionieren kann, dafür ist doch doe aktuelle lage der beste Beweis! WENN, ja WENN mit Hochrisikogeschäften wirklich Geld zu verdienen ist, wieso buttern dann sämtliche Banken/Versicherungen nicht genau dort ihr Geld rein?! Weil sie genau dort schon alle ihre Mittel deponiert haben! (Es kommt aber nix zurück....)

    Mittlerweile wollen die Versicherer eine Gesetzesänderung herbeiführen, damit sie bspw. bei vor 20 Jahren abgeschlossenen Lebensversicherungen die damals garantierte Verzinsung (bei mir waren das "nur" 3,4%) heute nicht mehr bezahlen müssen, da dieses Geld heute nicht mehr zu erwirtschaften ist....
    Mir kommen die Tränen...gerade im Gegenteil, normalerweise müsste der Gesetzgeber genau das Gegenteil machen und die Erfüllung sämtlicher damaliger Klauseln in den Verträgen GARANTIEREN! Und die Vorstände/Aufsichtsräte und sämtliche Entscheidungsträger bis runter zum Abteilungsleiter müssten mit ihrem Privatvermögen haften, DANN käme extrem schnell Bewegung in das System!

  • Sparen (erledigt)

    • Andy
    • 12. November 2016 um 13:05

    Das Problem ist, das Geld ist zzt. "zu billig", so dass es mittlerweile Negativzinsen gibt.
    In DK ist es mittlerweile so, dass man Geld dazugeschenkt bekommt, wenn man Immobilienkredite aufnimmt! Man bezahlt also weniger als man von der Bank als Kredit aufgenommen hat!
    http://www.manager-magazin.de/immobilien/art…-1021761-4.html


    Zitat von Alina

    vorschreibt wieviel ich später maximal pro Monat abheben darf.

    ABHEBEN, Alina, ABHEBEN! Das bezieht sich auf Bargeld!

    Du kannst selbstverständlich Überweisungen und andere Kontobewegungen in jeder beliebigen Höhe vornehmen...


    Eine alte Bauernweisheit sagt, man soll sein Vermögen dritteln, in Bargeld, Immobilien, Sachwerte(Gold/Diamanten).

    Keinesfalls würde ich irgendwelchen Bänkern glauben, die dir mit Hochrisiko-Fonds auch hohe Gewinne versprechen. Genau damit wurde die Bankenkrise herbeigeführt, und wären damals einige zehntausend Bänker infolge dieser vorhersehbaren Geschäftsergebnisse in den Knast gewandert, würden heutzutage diese Praktiken von niemandem mehr angeboten!
    Aber nein, unsere BundesAngie hat einige Milliarden Steuergelder locker gemacht, um die "Banken zu retten", welche sich mit diesem Geld sofort wieder in die Hochrisikomarkt gestürzt haben! :Face:
    Ausbaden tut es der Kunde, so oder so...

    Btw. mit 1000€ im Monat lässt sich doch sicher ein feines (vermietetes) Penthouse in Kopenhagen finanzieren 8o
    http://staycopenhagen.dk/design-apartments/penthouse/
    Dann kannst du als Rentnerin dort einziehen und die Aussicht genießen! :theke:

  • WINAPI GetLogicalProcessorInformation

    • Andy
    • 12. November 2016 um 12:33

    Hi,
    @chesstiger, gut angefangen, dann stark nachgelassen^^
    Du hast die "UNION" nicht in deine Struct verbaut....und auch nicht die Anzahl der Cores aus der Anzahl der gesetzten Bits aus ProcessorMask.
    Die Struct ist mitnichten 40Bytes (s. meinen nächsten Post^^), das Ergebnis deiner "Berechnung" entspricht also nicht der Erwartung. Mein AMD-Quadcore wird mit deinem Script mit 7 Cores ausgegeben....

    Bei 32bit ist eine "Line" der Struct 24 Bytes (4 Bytes ProcessorMask + 4 Bytes Relationship + 16 Bytes, in denen die UNION residiert)
    Bei 64bit ist eine "Line" der Struct 32 Bytes (8 Bytes ProcessorMask + 8 Bytes Relationship + 16 Bytes, in denen die UNION residiert)


    Mach da mal ne schicke auch für 64Bit gültige Version draus, incl. dem OO-Gedöns zum Abfragen der Struct-Items, das sieht nämlich wenigstens gut aus^^ //siehe EDIT unten

    AutoIt
    #include <Array.au3>
    #include <WinAPI.au3>
    
    
    #AutoIt3Wrapper_UseX64=n
    
    
    ;variablen zuordnen
    Enum $RelationProcessorCore, _
            $RelationNumaNode, _
            $RelationCache, _
            $RelationProcessorPackage, _
            $RelationGroup, _
            $RelationAll
    
    
    
    
    Global $processorCoreCount = 0, _
            $logicalProcessorCount = 0, _
            $processorPackageCount = 0, _
            $numaNodeCount = 0, _
            $L1CacheCount = 0, _
            $L2CacheCount = 0, _
            $L3CacheCount = 0, _
            $L1CacheSize = 0, _
            $L2CacheSize = 0, _
            $L3CacheSize = 0
    
    
    
    
    
    
    
    
    $dll = DllOpen("kernel32.dll")
    ConsoleWrite('- Debug(' & @ScriptLineNumber & ') : $dll = ' & $dll & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    ConsoleWrite('- : $dll = ' & $dll & @CRLF)               ;### Debug Console
    
    
    ;adresse holen
    $procaddress = DllCall($dll, "ptr", "GetProcAddress", "ptr", _WinAPI_GetModuleHandle("kernel32.dll"), "str", "GetLogicalProcessorInformation")
    ConsoleWrite('- : $ret = ' & $procaddress[0] & @CRLF)    ;### Debug Console
    
    
    ;Funktion callen, um buffer größe zu erhalten
    $return_length = 0
    $ret = DllCallAddress("uint", $procaddress[0], "dword", 0, "uint*", $return_length)
    ;~ ConsoleWrite('- : $ret = ' & $ret & @CRLF ) ;### Debug Console
    $return_length = $ret[2]
    ;~ ConsoleWrite('- : $return_length = ' & $return_length & @CRLF ) ;### Debug Console
    ;~ _arraydisplay($ret)
    
    
    
    
    $struct_bytes = DllStructCreate("byte [" & $return_length & "]")
    $ptr = DllStructGetPtr($struct_bytes)
    ;~ ConsoleWrite('- : $ptr = ' & $ptr & @CRLF ) ;### Debug Console
    
    
    
    
    ;Funktion callen, um bufferpointer  zu übergeben und buffer zu füllen
    $ret = DllCallAddress("uint", $procaddress[0], "ptr", $ptr, "uint*", $return_length)
    ;~ ConsoleWrite('- : $ret = ' & $ret[0] & @CRLF ) ;### Debug Console
    ;~ _arraydisplay($ret)
    
    
    ;zeig´s mir baby!!!
    $ret = DllStructGetData($struct_bytes, 1)
    ConsoleWrite('- : $ret = ' & ($ret) & @CRLF)             ;### Debug Console
    For $i = 3 To $return_length * 2 Step 48
        $a = StringMid($ret, $i, 48)
        ConsoleWrite("    " & $a & @CRLF)
    Next
    
    
    
    
    ConsoleWrite(@CRLF & @CRLF & "+ Ergebnisse:" & @CRLF & @CRLF)
    
    
    ;zuordnen
    
    
    For $i = 0 To $return_length - 24 Step 24
    
    
        $a = StringMid($ret, 3 + $i * 2, 48)
        ConsoleWrite($a & @CRLF)
    
    
    ;~ ;PLPI = PSYSTEM_LOGICAL_PROCESSOR_INFORMATION
        $struct_PLPI = DllStructCreate("dword ProcessorMask;" & _
                "dword Relationship;" & _
                "byte [16];", $ptr + $i)
    
    
        ;die "union" nachbasteln....alle
        $struct_Processorcore = DllStructCreate("byte Flags", DllStructGetPtr($struct_PLPI) + 8)
    
    
        $struct_NumaNode = DllStructCreate("dword NodeNumber", DllStructGetPtr($struct_PLPI) + 8)
    
    
        $struct_CACHE_DESCRIPTOR = DllStructCreate("byte Level;" & _
                "byte Associativity;" & _
                "word Linesize;" & _
                "dword Size;" & _
                "dword Type", DllStructGetPtr($struct_PLPI) + 8)
    
    
    
    
    
    
    ;~     $structsize = DllStructGetSize($struct_PLPI)
    ;~     ConsoleWrite('- : $structsize = ' & $structsize & @CRLF ) ;### Debug Console
    
    
    
    
    
    
    
    
        ;Daten auslesen
        $ProcessorMask = DllStructGetData($struct_PLPI, "ProcessorMask")
        ConsoleWrite('> $ProcessorMask = ' & $ProcessorMask & @CRLF)
        $Relationship = DllStructGetData($struct_PLPI, "Relationship")
        ConsoleWrite('> $Relationship  = ' & $Relationship)
    
    
    
    
        $Relationship = Int(DllStructGetData($struct_PLPI, "Relationship"))
    
    
        Switch $Relationship
    
    
            Case $RelationProcessorCore                      ;0 es werden Prozessor daten abgefragt
                ConsoleWrite("  ProcessorCore" & @CRLF)
                $ProcessorCore = DllStructGetData($struct_Processorcore, "Flags")
                ConsoleWrite('- : $ProcessorCore = ' & $ProcessorCore & @CRLF) ;### Debug Console
    
    
                $processorCoreCount += 1
    
    
                $logicalProcessorCount += CountSetBits($ProcessorMask)
    
    
            Case $RelationNumaNode
                ConsoleWrite("  NumaNode" & @CRLF)
                $NodeNumber = DllStructGetData($struct_NumaNode, "NodeNumber")
                ConsoleWrite('- : $NodeNumber = ' & $NodeNumber & @CRLF) ;### Debug Console
    
    
                $numaNodeCount += 1
    
    
            Case $RelationCache
                ConsoleWrite("  RelationCache" & @CRLF)
                $Level = DllStructGetData($struct_CACHE_DESCRIPTOR, "Level")
                ConsoleWrite('- : $Level = ' & $Level & @CRLF) ;### Debug Console
                $Associativity = DllStructGetData($struct_CACHE_DESCRIPTOR, "Associativity")
                ConsoleWrite('- : $Associativity = ' & $Associativity & @CRLF) ;### Debug Console
                $Linesize = DllStructGetData($struct_CACHE_DESCRIPTOR, "Linesize")
                ConsoleWrite('- : $Linesize = ' & $Linesize & @CRLF) ;### Debug Console
                $Size = DllStructGetData($struct_CACHE_DESCRIPTOR, "Size")
                ConsoleWrite('- : $Size = ' & $Size & @CRLF) ;### Debug Console
                $Type = DllStructGetData($struct_CACHE_DESCRIPTOR, "Type")
                ConsoleWrite('- : $Type = ' & $Type & @CRLF) ;### Debug Console
    
    
                Switch $Level
                    Case 1
                        $L1CacheCount += 1
                        $L1CacheSize += $Size
                    Case 2
                        $L2CacheCount += 1
                        $L2CacheSize += $Size
                    Case 3
                        $L3CacheCount += 1
                        $L3CacheSize += $Size
                EndSwitch
    
    
    
    
    
    
    
    
            Case $RelationProcessorPackage
                ConsoleWrite("  ProcessorPackage" & @CRLF)
                $processorPackageCount += 1
    
    
            Case $RelationGroup
                ConsoleWrite("  Group" & @CRLF)
    
    
    
    
    
    
        EndSwitch
    
    
    
    
    
    
    
    
    
    
    
    
        ConsoleWrite(@CRLF & @CRLF)
    
    
    Next
    
    
    
    
    
    
    $returnstring = "GetLogicalProcessorInformation:" & @CRLF & @CRLF & _
            StringFormat("Number %-30s = %u", "Processorcores", $processorCoreCount) & @CRLF & _
            StringFormat("Number %-30s = %u", "NumaNodes", $numaNodeCount) & @CRLF & _
            StringFormat("Number %-30s = %u", "logicalProcessorCount", $logicalProcessorCount) & @CRLF & _
            StringFormat("Number %-30s = %u", "processorPackageCount", $processorPackageCount) & @CRLF & _
            StringFormat("Number %-30s = %u/%u/%u", "Level1/2/3-Caches", $L1CacheCount, $L2CacheCount, $L3CacheCount) & @CRLF & _
            StringFormat("Number %-30s = %u/%u/%u", "L1/L2/L3 cache sizes (kB)", $L1CacheSize / 1024, $L2CacheSize / 1024, $L3CacheSize / 1024) & @CRLF & _
            ""
    
    
    ConsoleWrite($returnstring & @CRLF)
    
    
    MsgBox(0, "GetLogicalProcessorInformation", $returnstring)
    
    
    
    
    
    
    Func CountSetBits($uint)                                 ;zählt gesetzte bits
        $anz = 0
        For $i = 0 To 31
            If BitAND(2 ^ $i, $uint) Then $anz += 1
        Next
        Return $anz
    EndFunc                                                  ;==>CountSetBits
    Alles anzeigen


    //EDIT bitte auch für 64Bit testen!

    AutoIt
    #include <Array.au3>
    #include <WinAPI.au3>
    
    
    
    
    #AutoIt3Wrapper_UseX64=y		;für 32/64Bit
    
    
    ;variablen zuordnen
    Enum $RelationProcessorCore, _
            $RelationNumaNode, _
            $RelationCache, _
            $RelationProcessorPackage, _
            $RelationGroup, _
            $RelationAll
    
    
    
    
    Global $processorCoreCount = 0, _
            $logicalProcessorCount = 0, _
            $processorPackageCount = 0, _
            $numaNodeCount = 0, _
            $L1CacheCount = 0, _
            $L2CacheCount = 0, _
            $L3CacheCount = 0, _
            $L1CacheSize = 0, _
            $L2CacheSize = 0, _
            $L3CacheSize = 0
    
    
    
    
    If @AutoItX64 Then
        $32_64 = 32
    	$sSize=16
    Else
        $32_64 = 24
    	$sSize=8
    EndIf
    
    
    
    
    
    
    $dll = DllOpen("kernel32.dll")
    ;~ ConsoleWrite('- Debug(' & @ScriptLineNumber & ') : $dll = ' & $dll & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    ;~ ConsoleWrite('- : $dll = ' & $dll & @CRLF)               ;### Debug Console
    
    
    ;adresse holen
    $procaddress = DllCall($dll, "ptr", "GetProcAddress", "ptr", _WinAPI_GetModuleHandle("kernel32.dll"), "str", "GetLogicalProcessorInformation")
    ;~ ConsoleWrite('- : $ret = ' & $procaddress[0] & @CRLF)    ;### Debug Console
    
    
    ;Funktion callen, um buffer größe zu erhalten
    $return_length = 0
    $ret = DllCallAddress("uint", $procaddress[0], "dword", 0, "uint*", $return_length)
    ;~ ConsoleWrite('- : $ret = ' & $ret & @CRLF ) ;### Debug Console
    $return_length = $ret[2]
    ;~ ConsoleWrite('- : $return_length = ' & $return_length & @CRLF ) ;### Debug Console
    ;~ _ArrayDisplay($ret)
    
    
    
    
    $struct_bytes = DllStructCreate("byte [" & $return_length & "]")
    $ptr = DllStructGetPtr($struct_bytes)
    ;~ ConsoleWrite('- : $ptr = ' & $ptr & @CRLF ) ;### Debug Console
    
    
    
    
    ;Funktion callen, um bufferpointer  zu übergeben und buffer zu füllen
    $ret = DllCallAddress("uint", $procaddress[0], "ptr", $ptr, "uint*", $return_length)
    ;~ ConsoleWrite('- : $ret = ' & $ret[0] & @CRLF ) ;### Debug Console
    ;~ _arraydisplay($ret)
    
    
    ;zeig´s mir baby!!!
    $ret = DllStructGetData($struct_bytes, 1)
    ConsoleWrite('- : $ret = ' & ($ret) & @CRLF)             ;### Debug Console
    For $i = 3 To $return_length * 2 Step $32_64*2
        $a = StringMid($ret, $i, $32_64*2)
        ConsoleWrite("    " & $a & @CRLF)
    Next
    
    
    
    
    ConsoleWrite(@CRLF & @CRLF & "+ Ergebnisse:" & @CRLF & @CRLF)
    
    
    ;zuordnen
    
    
    For $i = 0 To $return_length - $32_64 Step $32_64
    
    
        $a = StringMid($ret, 3 + $i * 2, $32_64*2)
        ConsoleWrite($a & @CRLF)
    
    
    ;~ ;PLPI = PSYSTEM_LOGICAL_PROCESSOR_INFORMATION
        $struct_PLPI = DllStructCreate("uint_ptr ProcessorMask;" & _
                "uint_ptr Relationship;" & _
                "byte [" & $32_64-16 & "]", $ptr + $i)
    
    
        ;die "union" nachbasteln....alle
        $struct_Processorcore = DllStructCreate("byte Flags", DllStructGetPtr($struct_PLPI) + $sSize)
    
    
        $struct_NumaNode = DllStructCreate("dword NodeNumber", DllStructGetPtr($struct_PLPI) + $sSize)
    
    
        $struct_CACHE_DESCRIPTOR = DllStructCreate("byte Level;" & _
                "byte Associativity;" & _
                "word Linesize;" & _
                "dword Size;" & _
                "dword Type", DllStructGetPtr($struct_PLPI) + $sSize)
    
    
    
    
    
    
    ;~     $structsize = DllStructGetSize($struct_PLPI)
    ;~     ConsoleWrite('- : $structsize = ' & $structsize & @CRLF ) ;### Debug Console
    
    
    
    
    
    
    
    
        ;Daten auslesen
        $ProcessorMask = DllStructGetData($struct_PLPI, "ProcessorMask")
        ConsoleWrite('> $ProcessorMask = ' & $ProcessorMask & @CRLF)
        $Relationship = DllStructGetData($struct_PLPI, "Relationship")
        ConsoleWrite('> $Relationship  = ' & $Relationship)
    
    
    
    
        $Relationship = Int(DllStructGetData($struct_PLPI, "Relationship"))
    
    
        Switch $Relationship
    
    
            Case $RelationProcessorCore                      ;0 es werden Prozessor daten abgefragt
                ConsoleWrite("  ProcessorCore" & @CRLF)
                $ProcessorCore = DllStructGetData($struct_Processorcore, "Flags")
                ConsoleWrite('- : $ProcessorCore = ' & $ProcessorCore & @CRLF) ;### Debug Console
    
    
                $processorCoreCount += 1
    
    
                $logicalProcessorCount += CountSetBits($ProcessorMask)
    
    
            Case $RelationNumaNode
                ConsoleWrite("  NumaNode" & @CRLF)
                $NodeNumber = DllStructGetData($struct_NumaNode, "NodeNumber")
                ConsoleWrite('- : $NodeNumber = ' & $NodeNumber & @CRLF) ;### Debug Console
    
    
                $numaNodeCount += 1
    
    
            Case $RelationCache
                ConsoleWrite("  RelationCache" & @CRLF)
                $Level = DllStructGetData($struct_CACHE_DESCRIPTOR, "Level")
                ConsoleWrite('- : $Level = ' & $Level & @CRLF) ;### Debug Console
                $Associativity = DllStructGetData($struct_CACHE_DESCRIPTOR, "Associativity")
                ConsoleWrite('- : $Associativity = ' & $Associativity & @CRLF) ;### Debug Console
                $Linesize = DllStructGetData($struct_CACHE_DESCRIPTOR, "Linesize")
                ConsoleWrite('- : $Linesize = ' & $Linesize & @CRLF) ;### Debug Console
                $Size = DllStructGetData($struct_CACHE_DESCRIPTOR, "Size")
                ConsoleWrite('- : $Size = ' & $Size & @CRLF) ;### Debug Console
                $Type = DllStructGetData($struct_CACHE_DESCRIPTOR, "Type")
                ConsoleWrite('- : $Type = ' & $Type & @CRLF) ;### Debug Console
    
    
                Switch $Level
                    Case 1
                        $L1CacheCount += 1
                        $L1CacheSize += $Size
                    Case 2
                        $L2CacheCount += 1
                        $L2CacheSize += $Size
                    Case 3
                        $L3CacheCount += 1
                        $L3CacheSize += $Size
                EndSwitch
    
    
    
    
    
    
    
    
            Case $RelationProcessorPackage
                ConsoleWrite("  ProcessorPackage" & @CRLF)
                $processorPackageCount += 1
    
    
            Case $RelationGroup
                ConsoleWrite("  Group" & @CRLF)
    
    
    
    
    
    
        EndSwitch
    
    
    
    
    
    
    
    
    
    
    
    
        ConsoleWrite(@CRLF & @CRLF)
    
    
    Next
    
    
    
    
    
    
    $returnstring = "GetLogicalProcessorInformation: "&32*(1+@AutoItX64)&"Bit" & @CRLF & @CRLF & _
            StringFormat("Number %-30s = %u", "Processorcores", $processorCoreCount) & @CRLF & _
            StringFormat("Number %-30s = %u", "NumaNodes", $numaNodeCount) & @CRLF & _
            StringFormat("Number %-30s = %u", "logicalProcessorCount", $logicalProcessorCount) & @CRLF & _
            StringFormat("Number %-30s = %u", "processorPackageCount", $processorPackageCount) & @CRLF & _
            StringFormat("Number %-30s = %u/%u/%u", "Level1/2/3-Caches", $L1CacheCount, $L2CacheCount, $L3CacheCount) & @CRLF & _
            StringFormat("Number %-30s = %u/%u/%u", "L1/L2/L3 cache sizes (kB)", $L1CacheSize / 1024, $L2CacheSize / 1024, $L3CacheSize / 1024) & @CRLF & _
            ""
    
    
    ConsoleWrite($returnstring & @CRLF)
    
    
    MsgBox(0, "GetLogicalProcessorInformation", $returnstring)
    
    
    
    
    
    
    Func CountSetBits($uint)                                 ;zählt gesetzte bits
        $anz = 0
        For $i = 0 To 31
            If BitAND(2 ^ $i, $uint) Then $anz += 1
        Next
        Return $anz
    EndFunc                                                  ;==>CountSetBits
    Alles anzeigen
  • Neulich in der Kneipe..."Compiler sind die besseren Programmierer"?!

    • Andy
    • 7. November 2016 um 20:59
    Zitat von Bitnugger

    Hm, also doch noch zu wenig hier im Forum gelesen, denn das sagt mir jetzt nicht wirklich was.

    ok....du wolltest es so 8o
    Chronologisch:
    Breakpoint 2010 in Bingen am Rhein vom 2.-5. April zusammen mit UEZ ein Hammer Event in Bingen!
    Danach in jedem Jahr zusammen mit UEZ nach Saarbrücken:
    Revision Demoparty 2014 Streams'n'Tools (und allgemeine Demoparty Diskussion)
    Wo ist der Thread mit den Bildern aus 2015? //EDIT Revision 2015 ... na geht doch!
    Revision 2016 - "The return of EvilBot" mit Xorianator, Lottich, UEZ und meiner Wenigkeit! Viel Spass dabei, die Namen den Personen zuzuordnen :D
    Revision 2017 und die Schnitzeljagd Vorbereitung für die nächste Revision

    Website: https://2016.revision-party.net

  • Neulich in der Kneipe..."Compiler sind die besseren Programmierer"?!

    • Andy
    • 7. November 2016 um 19:03
    Zitat von Bitnugger

    Mit beiden Systemen konnte man... nein, kann man auch heute noch fantastische Sachen machen.

    Komm mit im nächsten Jahr zur Revision, und bring das/die Schätzchen mit!!! Dort findest du weitere völlig bekloppte, die selbst heutzutage noch sehenswerte Grafik- und vor allem Audio-Demos abliefern! Vom Hardwaregebastel ganz zu schweigen 8o

    Bzgl. Ironie[modus]...Luis Trenker faltenfrei...der hätte bestimmt gedacht, Peek und Poke wären die tschechischen Geschwister von Ying und Yang :party: ...öööhhmm...nö, das sind doch Lolek und Bolek :rock: //EDIT große Abbitte an die beiden, die sind natürlich nicht tschechisch, sondern polnisch! Pan Tau ist tschechisch. T´pau ist vulkanisch... :Face:

    Zitat von Bitnugger

    Turbo Pascal... ja, damit konnte man auch ganz nett basteln... aber kein Verleich mit Assembler wert. Die Programmierung war unter Turbo Pascal für Windows ähnlich aufwendig wie in C – mit dem zusätzlichen Nachteil, dass Windows selbst in C programmiert ist, weshalb die Schnittstellen zwischen Windows und Pascalprogramm mindestens grundlegende C-Kenntnisse erfordern. Daher gab und gibt es absolut keinen Grund, weshalb ich mir zu irgendeiner Zeit Turbo Pascal hätte antun sollen.

    Als "alter" GW-Basic/Assembler-Programmierer hatte ich genau damit meine Probleme. Der einzige Grund, Turbo-Pascal damals in der Schule zu benutzen war imho der Compiler, also ein EXE-File. C war bei mir nie eine Alternative, denn die "Profis", welche von Basic zu Pascal/C umgestiegen sind, um weniger/keinen "Spaghetticode" zu generieren, waren 1/2 Jahr später nicht mal in der Lage, eine Woche vorher selbstgeschriebenen Code zu analysieren. Bevor da einer den Debugger gestartet hat, wurden halt einige hundert Zeilen Code komplett neu geschrieben :rolleyes: ....und genau dieses Vorgehen wurde übrigens viele Jahre später bei IBM zu einer Kunst ausgebaut. Da gab es dann ganze Abteilungen, die statt "ordentlich" zu debuggen (mach das mal bei hardcore-Spaghetti-C !!) Programme/Funktionen NEU geschrieben haben (incl. extra bezahlten Zeilen Kommentaren!!!). Hehe, das mit den Kommentaren war dermaßen wichtig, dass Programme geschrieben wurden, welche Kommentare in den Sourcecode einfügten. Das ist übrigens absolut KEIN WITZ!

    Ich bin später dann auf TurboBasic umgestiegen. DAS war ein geiler Compiler, und der integrierte Debugger hat auch seinen Job gemacht! :klatschen:

  • SciTE - Umlaute

    • Andy
    • 2. November 2016 um 13:32

    omfg...ich glaube, ich bin raus ;(
    Soeben folgendes probiert: Datei in Scite geöffnet, in die leere Console "Männer" geschrieben und Enter gedrückt, ergab folgendes Ergebnis:

    Code
    >Männer
    Der Befehl "Mx84ner" ist entweder falsch geschrieben oder
    konnte nicht gefunden werden.
    >Exit code: 1    Time: 0.2326

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™