8Bit Array möglichst schnell mit konstante füllen füllen



  • okay klappt nun auch hab einfach nen 4-char-Array auf int gecastet
    natürlich bin ich für schnellere Möglichkeiten immernoh zu haben

    Sorry das ich hier mit mir selbst red, aber das hat mich selber überrascht das ich das mit dem casten selbst hinbekommen hab

    jetzt wird mir auch klar warum mein Programm so langsam ist
    ich verschwend die ganze Geschwindigkeit mit sinnlos langsamen Kopiervorgängen



  • mal was anderes.. wenn man schreibt:
    int i=4;
    wird das doch zur compilezeit schon initialisiert, wie auch bei
    int i[]={4,4,4,4}
    oder lieg ich da falsch? musst du dir halt n precompiler schreiben, der das entsprechend oft kodiert 🙂



  • Klar ginge das, aber ein Array mit fast 800000 Elementen dürfte etwas zu groß für den Stack sein 😉



  • er legt es doch statisch an. obs vorinitialisiert wird oder nich macht doch keinen unterschied



  • aber die Zahl wird auch erst kurz nach Programmstat bekannt
    das sieht dann ungefähr so aus:

    int i[4]={x,x,x,x};

    und das wird bestimmt nicht zur compilerzeit initalisiert



  • komisch, ich hab jetzt

    memset(array, 192, 786432);

    ausprobiert und das ist noch schneller als mit den Referenzen
    das passt jetzt irgendwie nicht in mein Weltbild

    kann man sich den Code von den C-Libs vielleicht irgendwo runterladen?



  • Ich habe da mal ein wenig geforscht...

    Wie gesagt, memset dürfte um einiges schneller sein.
    Ich habe gelesen, dass das die Assembler-Befehle zum Initialisieren und Kopieren von Speicher mit Assembler ein Takt pro Durchlauf (also Ideal 4 Byte pro Takt, 8 Byte mit SIMD) benötigen, was bei 2GHz theoretisch bis zu 8GB/s wären.
    Quelle: http://www.activevb.de/tutorials/tut_asm/asm2.html (nach STOSx suchen)

    Ich habe mir mal die memset.asm von Visual C++ 2005 angesehen und war überrascht wie lang die ist. Dort wird ebenfalls in 2- bzw. 4-Byte-Blöcken initialisiert falls möglich. Des weiteren wird SSE2 verwendet, falls vorhanden. Alles in allem also gut optimiert.



  • aber warum ist die Referenz Methode dann langsamer?
    die benutzt ja genauso 4 Byte Blöcke



  • Verstehe nicht ganz was du mit Referenzen meinst - was haben die mit deinem Problem zu tun?



  • ich hab das ganze jetzt doch mit Referenzen gelöst (bzw. rackwitz)
    und ich frag mich wie das langsamer sein kann als memset
    aber da werden die wahrscheinlich irgendwas dran gedreht haben...



  • Aber wie hast du das mit Referenzen gelöst?
    Oder meinst du das Füllen per Schleife?



  • Argh... b*llsh*t! Ich sollte vorher nachdenken... 😡



  • so hab ich das ganze jetzt gemacht:

    char array[786432]; // muss vielfaches von 4 sein (sizeof unsigned int), sonst wird ueber die grenzen geschrieben (kann man aber behandeln)
    unsigned int konstante = 0;
    for(int i = 0; i < 786432; i += 4)
    {
      *(unsigned int*)(array+i) = konstante;
    }
    

    das war rackwitz Idee

    oh, stimmt das hat gar nichts mit Referenzen zu tun
    mein Fehler...



  • Ist aber unnötig langsam - nimm memset...



  • unsigned int konstante = 123, i;
    for (i = 1; i < sizeof(konstante); ++i)
        konstante |= (konstante & ((1 << CHAR_BIT)-1)) << (CHAR_BIT*i);
    

    fuellt "konstante" mit entsprechend genug "123" auf *ungetestet*



  • aber das isses ja grade
    warum ist das unnötig langsam?
    und warum ist memset schneller?



  • SIMD, prozessorspezifische instruktionen?



  • Nick H. schrieb:

    aber das isses ja grade
    warum ist das unnötig langsam?
    und warum ist memset schneller?

    In deinem Fall mit der Schleife werden eben der Inhalt der Schleife, die Abbruchbedingung und die Übergangsfunktion bei jedem Schleifendurchgang ausgeführt.
    memset ist in Assembler programmiert und höchst optimiert, so dass ein Assemblerbefehl genutzt wird, der einen Speicherraum bestimmter Länge mit nur wenigen Befehlen füllt (schau dir mal den Assemblercode an, da dürftest du keine Schleife finden).

    @c.rackwitz: http://de.wikipedia.org/wiki/SIMD 🙄



  • ja stimmt, das ergibt Sinn
    allerdings müsste man dann in Assembler ja dann auch ne Schleife machen (loop)
    und die müsste auch immer die Abbruch Bedingung überprüfen (cx)
    aber x zu überprüfen geht wahrscheinlich auch viel schneller als nen Wert im Speicher
    am besten wärs wohl Assembler an der Stelle einzubauen und selber den Speicherbereich kopieren
    dann bräuchte man nich mal nen Loop
    aber das is dann irgendwie auch verschwendung
    das mach ich wenns dann wirklich mal um jedes bisschen Speed geht



  • Ich habe gesagt bei memset gibt es keine Schleife!
    Der Assemblerbefehl 'rep' wird benutzt, d.h. die ganze Initialisierung findet in einem einzigen Taktzyklus der CPU statt.
    ... und wenn du memset benutzt IST die Funktion bereits in Assembler, selbst coden wäre somit kompletter Blödsinn.


Anmelden zum Antworten