Einlesen von Daten beschleuningen



  • Hi,

    ich habe nen kleines Problem. Ich muss für ein Programm relativ viele Daten einlesen. Es handelt sich dabei um Vertex Informationen, liegen also als float vor.
    Da es sich zb. bei einem Model um 39k Vertexe handelt und das ganze mal 3(jede dimension) multipliziert ergibt 117k vertex infos. Meine frage ist, wie ich das ganze beschleunigen kann.

    bisher arbeitet mein Progg so:

    GLFLOATVEC vertices;
    float f1, f2, f3;
    //hole menge der vertex infos
    ....
    ....
    		while( i < vertices->size() ){  
    
                            file >> f1 >> f2 >> f3;
    			vertices->at( i ) = f1;
    			vertices->at( ++i ) = f2;
    			vertices->at( ++i ) = f3;
    			i++;
    		}
    

    ich weiß das ist kein schöer code...
    deswegen frage ich ja hier. gäbe es zb. ne möglichkeit erst alles in den speicher zu kopieren und dann damit zu arbeiten?

    ich bin für alle vorschhläge die speed bringen zu haben.

    danke und gruß



  • Ich gehe mal davon aus, daß file vom Typ std::ifstream ist. Die Klasse std::ifstream ist gepuffer. Das einlesen in den Speicher und dann damit zu arbeiten wird wahrscheinlich nichts bringen.

    Der Code ist bereits optimal im Sinne der performance soweit der Ausschnit das zeigt und da die Datenmengen sicher in den Cache passen, hilft nur ein schnellere CPU (im weitesten Sinne, also fangt mir jetzt nicht an mit Speicheranbindung und co.).

    Tommi



  • Also optimal ist das noch lange nicht:

    Wenn "vertices" ein std::vector ist, dann solltest du vorher "reserve" aufrufen (da du die ungefähre Größe ja zu kennen scheinst).
    Außerdem wäre ein ungepuffertes Lesen trotzdem schneller (entgegen von dem was tntnet schreibt, da Puffern immer Kopieren bedeutet).

    Ich weiß nicht, ob beim fstream auch setbuf(NULL, 0) funktioniert, jedenfalls bei einem FILE geht setbuf(fp, NULL), um in den ungepufferten Modus zu schalten.



  • also ich hab den vector bereits mit .resize auf die entsprechende größe wachsen lassen oder gibt es einen unterschied zu .reserve?

    und ja file ist std::fstream
    ich verstehe aber nicht warum das ungepufferte einlesen schneller gehen soll als das gepufferte...warum puffert man dann überhaupt?

    kann ja irgendwie nicht sein, dass man das nicht schneller machen kann...


  • Mod

    sind das binär oder textdaten? in letzterem falle wird die laufzeit wahrscheinlich primär von der umwandlung dieses textes bestimmt und es gibt im grunde nichts, was man tun könnte, um das signifikant zu beschleunigen. sind es binär-daten sieht die sache anders aus (allerdings kann ich dann kaum glauben, das obige lösung bei gerade 100k daten tatsächlich zu langsam ist - es sei denn, du machst das 100mal innerhalb kurzer zeit 😉
    falls du mit textdaten zu tun hast, könnte es sinnvoll sein, das ergebnis in eine binäre cachedatei zu speichern, so das der nächste durchlauf schneller geht, es sei denn, das original wurde verändert. die frage nach gepuffert/ungepuffert dürfte hier relativ uninteressant sein - das betriebssystem puffert ja auch, und bei rein sequentiellem zugriff genügt das oft.



  • handelt sich um textdateien..

    und die werden nur einmal beim programmstart geladen. hätte das aber trotzdem gerne schneller..



  • dann verwende die c-io-funktionen



  • und warum soll das so viel schneller sein? kann mir das wer erklären? will ja shcon wissen was ich warum tue...

    nen link mit ner info reicht mir auch



  • icdh glaub nich dass die schneller sind... lass doch mal ein profiler drüber laufen, was länger dauert: umwandeln oder aus datei lesen 🙂



  • Geh einfach mal mit nem Debugger im Single Step durch und du siehst den Unterschied.



  • Außerdem wäre ein ungepuffertes Lesen trotzdem schneller (entgegen von dem was tntnet schreibt, da Puffern immer Kopieren bedeutet).

    kopieren ist aber 1000000 mal schneller, als die festplatte für jedes byte zu bemühen.



  • Th schrieb:

    Also optimal ist das noch lange nicht:

    Wenn "vertices" ein std::vector ist, dann solltest du vorher "reserve" aufrufen (da du die ungefähre Größe ja zu kennen scheinst).
    Außerdem wäre ein ungepuffertes Lesen trotzdem schneller (entgegen von dem was tntnet schreibt, da Puffern immer Kopieren bedeutet).

    Ich weiß nicht, ob beim fstream auch setbuf(NULL, 0) funktioniert, jedenfalls bei einem FILE geht setbuf(fp, NULL), um in den ungepufferten Modus zu schalten.

    "vertices->at( i ) = f1;" würde gar nicht funktionieren, wenn der Vektor nicht vorher auf eine ausreichende Grösse gebracht wurde. Reserve ist da höchstens kontraproduktiv.

    Ungepuffertes Lesen ist der Performancekiller! Eines der teuersten Dinge, die man in einem Programm macht, sind Systemaufrufe. Wenn ich ungepuffert lese, also jedes Byte einzeln, dann bedeutet das ein Systemaufruf pro Byte. Deswegen richtet man einen geeignet grossen Lesepuffer ein, den man mit einem Systemaufruf füllen kann.

    Tntnet



  • Du könntest auch ne std::list<> benutzen, falls du nacher nicht irgendwie zufällig auf die Daten zugreifen möchtest.

    Ne list arbeitet viel schneller als ein vector. Wenn du sie natürlich nur von vorne nach hinten durchläufst und nicht zufällig mal mittendrin einen Wert abfragen willst.

    Test it out 😉



  • Freak_Coder schrieb:

    Du könntest auch ne std::list<> benutzen, falls du nacher nicht irgendwie zufällig auf die Daten zugreifen möchtest.

    Ne list arbeitet viel schneller als ein vector. Wenn du sie natürlich nur von vorne nach hinten durchläufst und nicht zufällig mal mittendrin einen Wert abfragen willst.

    Test it out 😉

    Wie kommst Du darauf, daß eine list schneller (auch noch viel schneller) als ein vector arbeitet? Das ist mitnichten der Fall. In eine Liste kann ich schneller Elemente einfügen. Und das sogar an eine beliebige Stelle in konstanter Zeit. Schneller ist es aber, einen vector mit resize gleich auf die richtige Grösse zu bringen und dann die Elemente zu verwenden, so wie im vorliegenden Beispiel. Das ist dann wirklich viel schneller, als eine list.

    Selbst der Zugriff auf ein Element (über einen iterator) in einem list ist eher langsamer als in einem vector. Ein Iterator auf eine list ist eine Klasse, die auf den Knoten der verketteten Liste zeigt. Greife ich auf das Element zu, liefert der Iterator das Element, auf das der Knoten verweist. Ein Iterator auf ein vector ist in der Regel ein einfacher Zeiger. Und eine Zeigerdereferenzierung ist sicher einfacher, als das, was der Listeniterator machen muß.


Anmelden zum Antworten