CPU effektiver bei Script Ausführung einsetzten

    • Offizieller Beitrag

    Statt einfach nur ins Leere zu shiften, kann man die 32Bitzahl auch gleich als 4 Zufallszahlen (à 8 Bit) betrachten. Das würde dann so aussehen:

    AutoIt
    $iRandom = Random(0, 2^31-1, 1)
    ConsoleWrite('Zufall = ' & Hex($iRandom) & @CR)
    For $i = 0 To 3
    	ConsoleWrite($i+1 & '. = 0x' & Hex(BitAND($iRandom, 0xff), 2) & @CR)
    	$iRandom = BitShift($iRandom, 8)
    	ConsoleWrite('nach Shift = ' & Hex($iRandom) & @CR)
    Next

    Das ist in AutoIt aber langsamer (getestet), weil die Anzahl der Befehle innerhalb der Schleife zunimmt.
    Testcode:

    Ergebnis:

    Code
    Variante 1 = 10.108 sek. (10.000.000 Zeichen)
    Variante 2 = 7.741 sek. (10.000.000 Zeichen)
    Variante 3 = 14.178 sek. (10.000.000 Zeichen)
  • Wenn du den ganzen ANSI-Satz zulässt könnte man dann nicht auch so machen?:

    AutoIt
    For $i = 1 To $iCount Step 4
       $sText &= BinaryToString(Random(0, 2^31-1, 1), 1)
    Next


    Hat bloß den Makel, dass Random() nicht bis 2^32-1 geht und somit jede 4te Zahl nicht über 127 hinauskommt (wie bei deiner Variante 3).

    @Andy

    Zzt. suche ich noch eine (schnelle!) Lösung, um von dem zufälligen 32-Bit-Wert auf den gesuchten Wertebereich 0-94 (33 bis 127) zu kommen.

    Gibt es in Assembler einen Integer-Modulo?
    Falls ja wäre das ein Ansatz:

    AutoIt
    $x = Mod(Random(0, 2^31-1, 1), 95) + 33

    Einmal editiert, zuletzt von AspirinJunkie (1. März 2016 um 12:36)

    • Offizieller Beitrag

    Stimmt, die Variante mit BinaryToString wäre dann die Schnellste (in AutoIt): 4.202 sek. (10.000.000 Zeichen)
    Ich hatte die BitShift-Variante jetzt mehr als Beispiel für eine Assembler-Variante gesehen. Dort hatte Andy ja einen 32-Bit-Randomwert und Bitshift dürfte in Assembler ja sehr schnell sein.
    Unabhängig vom ursprünglichen Threadthema (ist ja gelöst) würde mich eine Assembler-Variante mit gesamten ASCII-Zeichensatz (0...255) interessieren.

  • Das ganze ist jetzt von knapp 2min auf max 15sek. gefallen, die CPu tümpelt aber immer noch bei 25%

    ggf. solltest du dir das Thread/Task-Management von Windows anschauen.

    Die CPu steht nie bei 100% sie tümpelt max. bei 25% rum und zwatr auf einem Kern, nicht 25% verteilt auf allen 8 Kernen.

    Du hast eine Quadcore, daher die 25%. Windows verteilt die 100% Last EINES Threads/Tasks auf 4 Kerne, daher 25%. Du kannst das einfach im Taskmanager beeinflussen, wenn du den Task/Thread EINEM Core zuordnest (Rechtsklick auf den Prozess).


    Ich werde mal was basteln, die 15 Sekunden sollten doch zu schlagen sein^^

  • Bei 10 Mio Zeichen muss man schauen in wiefern sich ein Puffer lohnt.

    Methode1: Kein Puffer
    Methode2: 256 Zeichen Puffer -> Maximal 8Bit/Durchlauf möglich
    Methode3: 256 Zeichen Puffer -> Maximal 8Bit/Durchlauf möglich. Ist langsamer als 2, da Random vergleichsweise Schnell zu BitAnd und BitShift ist.

    Bei 10Mio kann man auch einen 65536 Zeichen Puffer nutzen. Damit wären dann 16Bit/Durchlauf drin. Ein Größerer Puffer macht erstmal keinen Sinn, außer man will 100Mio Zufallszahlen berechnen. Das Gilt natürlich nur AutoIt spezifisch, da man hier davon ausgeht, dass die Randomfunktion für 8Bit die gleiche Laufzeit besitzt wie für 16Bit usw. (In anderen Programmiersprachen hat jeder Befehl eine andere Laufzeit und daher liegt der Knackpunkt in ASM z.B. vermutlich woanderst).

    lg
    M

  • ggf. solltest du dir das Thread/Task-Management von Windows anschauen.

    Du hast eine Quadcore, daher die 25%. Windows verteilt die 100% Last EINES Threads/Tasks auf 4 Kerne, daher 25%. Du kannst das einfach im Taskmanager beeinflussen, wenn du den Task/Thread EINEM Core zuordnest (Rechtsklick auf den Prozess).

    Ich werde mal was basteln, die 15 Sekunden sollten doch zu schlagen sein^^

    Nein Andy, es sind nur 25% auf einer CPU ;), die anderen CPus laufen gar nicht erst mit an.
    Bevor die Frage kommt, die CPU ist 100% in Ordnung, aus eirgendeinem Grund wird das script aber sofort nur auf einer cpu ausgeführt

    • Offizieller Beitrag

    Mars: Deine Puffer-Methode (auf 10.000.000 geändert) schlägt sich ganz gut (4.485 sek.), wird aber von der BinaryToString-Methode (4.202 sek.) geschlagen.
    Ich denke, rein mit AutoIt sind wir am Optimum angekommen. Da wird wohl nicht mehr viel gehen.
    Etwas optimieren kann man die BinaryToString-Methode noch, indem man mehrere BinaryToString in eine Zeile packt:

    AutoIt
    For $iLoop = 1 To $iCount Step 64
    	$sText &= BinaryToString(Random(0, 2^31-1, 1), 1) & BinaryToString(Random(0, 2^31-1, 1), 1) & BinaryToString(Random(0, 2^31-1, 1), 1) & BinaryToString(Random(0, 2^31-1, 1), 1) & BinaryToString(Random(0, 2^31-1, 1), 1) & BinaryToString(Random(0, 2^31-1, 1), 1) & BinaryToString(Random(0, 2^31-1, 1), 1) & BinaryToString(Random(0, 2^31-1, 1), 1) & BinaryToString(Random(0, 2^31-1, 1), 1) & BinaryToString(Random(0, 2^31-1, 1), 1) & BinaryToString(Random(0, 2^31-1, 1), 1) & BinaryToString(Random(0, 2^31-1, 1), 1) & BinaryToString(Random(0, 2^31-1, 1), 1) & BinaryToString(Random(0, 2^31-1, 1), 1) & BinaryToString(Random(0, 2^31-1, 1), 1) & BinaryToString(Random(0, 2^31-1, 1), 1)
    Next

    So läßt sich das auf 3.961 sek. reduzieren. Der Code wird aber zunehmend unleserlicher. ^^

  • Nein Andy, es sind nur 25% auf einer CPU ;), die anderen CPus laufen gar nicht erst mit an.

    Die Prozentzahl im Taskmanager gibt die Gesamtauslastung des Systems an.
    Wenn du 4 Kerne hast, kannst du bei einem SingleThread-Prozess also nur maximal 25% Auslastung erreichen.
    Der Kern ist also zu 100% ausgelastet und die gesamte CPU (also alle Kerne) nur zu 25%.

    Wäre, wie du sagst, nur der einzelne Kern zu 25% ausgelastet würde der Taskmanager für diesen Prozess 6,25% Auslastung anzeigen.
    Ist das der Fall?

  • Die Prozentzahl im Taskmanager gibt die Gesamtauslastung des Systems an.Wenn du 4 Kerne hast, kannst du bei einem SingleThread-Prozess also nur maximal 25% Auslastung erreichen.
    Der Kern ist also zu 100% ausgelastet und die gesamte CPU (also alle Kerne) nur zu 25%.

    Wäre, wie du sagst, nur der einzelne Kern zu 25% ausgelastet würde der Taskmanager für diesen Prozess 6,25% Auslastung anzeigen.
    Ist das der Fall?

    Nein es wird nur 1.Kern zu 25% ausgelastet.

    Wenn man seine CPu überwacht sollte man dies über den Ressourcenmonitor machen und nicht bloß über den Taskmanager. Dort sieht man alle CPUs und deren einzelnen Auslastungen und bei mir wird nun mal nur eine zu 25% ausgelastet die anderen dümpeln bei 0%-1%, also Leerlauf.

  • es wird nur 1.Kern zu 25% ausgelastet.

    Dort sieht man alle CPUs und deren einzelnen Auslastungen und bei mir wird nun mal nur eine zu 25% ausgelastet

    Was denn nun? - Kerne oder CPUs?
    Wieviele Kerne hast du denn?
    Und wieviele CPUs?

    Geht die Auslastung auch mal über 25%?
    Es wäre sehr verwunderlich wenn die Auslastung eines Kerns eine bestimmte Auslastungsgrenze hat.
    Das bekommt man auch nicht wirklich hinprogrammiert, dass eine Programm einen einzelnen Kern auf einem stabilen Level auslastet.
    Zumal die 25% sehr stark nach einem Teiler durch 4 (=4 Cores?) riechen.

    Mach mal einen Screenshot davon um zu sehen was du wo genau abliest.

    Einmal editiert, zuletzt von AspirinJunkie (1. März 2016 um 15:43)

    • Offizieller Beitrag

    Dann starte mal dieses Testscript,

    AutoIt
    HotKeySet('{ESC}', '_Exit')
    Global $a = 0
    While True
    	$a += 1
    WEnd
    
    
    Func _Exit()
    	Exit
    EndFunc

    weise dem Prozess "AutoIt3.exe *32" nur eine CPU zu ("Zugehörigkeit festlegen..." im TaskManager) und schaue Dir die Auslastung an.
    Dann siehst Du, dass die eine CPU zu 100% ausgelastet ist, die Gesamtauslastung aber nur 25% (bei 4 CPUs) beträgt.
    Wenn die Zugehörigkeit nicht festgelegt ist, dann verteilt Windows das auf alle CPUs.

  • Ich hab jetzt nicht alle Antworten gelesen, aber für den Wertebereich 0x00 - 0xFF gibts die Funktion _Crypt_GenRandom (wie Andy ja schon geschrieben hat...)

  • Gibt es in Assembler einen Integer-Modulo?

    Ja, als "Abfall" der Division erhält man den "Rest" . Allerdings ist DIV schon sehr "teuer" (jaja, bissl bekloppt darf man sein ^^ ). Weiterhin gehe ich einfach mal davon aus (korrigiere mich bitte wenn nötig! ), daß bei gleichverteilten RtlRandomEx-32-Bit-Ergebnissen, auch die darin enthaltenen einzelnen Bytes gleichverteilt sind.
    Somit bekomme ich 4 zufällige Bytes! Und brauche also auch nur 1/4 der Berechnungen!
    Über den dicken Daumen bin ich mit dem Assemblerscript bissl schneller als _Crypt_GenRandom(). Jedenfalls bei durch 4 teilbaren Byte/Char-Mengen :D

    Noch schön verpacken....

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (1. März 2016 um 23:59)

  • Somit bekomme ich 4 zufällige Bytes! Und brauche also auch nur 1/4 der Berechnungen!

    Ja das hatte Oscar ja auch schon so in AutoIt ausgenutzt.
    Ich weiß nur halt nicht wie du das hinbekommst den Wertebereich jedes Bytes auf 33-127 einzudampfen.
    Alle 4 durch Verschieben und Einzelbehandlung anpassen?
    Wären das "vernünftige" Zahlengrenzen könnte man ja einfach ne Bitmaske drüber legen und gleich alle 4 Bytes mit einer Operation abhandeln - aber die sind hier ja leider etwas krumm geraten mit 33-127.

  • Ich weiß nur halt nicht wie du das hinbekommst den Wertebereich jedes Bytes auf 33-127 einzudampfen.
    Alle 4 durch Verschieben und Einzelbehandlung anpassen?

    Etwas anderes wird nicht funktionieren... :(

    Hier der Assemblercode, ca. doppelt so schnell wie _Crypt_GenRandom(). Mal schauen, was deine Idee mit dem MOD (DIV) bringt, das muss aber für jedes Byte gemacht werden!