Geschwindigkeitsfrage Datei einlesen und konvertieren
-
wob schrieb:
manni66 schrieb:
wob schrieb:
Wie schaffst du es sonst, 60 Sekunden für das Einlesen zu brauchen?
Das sollte problemlos möglich sein, wenn man den Optimizer nicht einschaltet.
Mit welchem Compiler?
Also Visual Studio sollte das schaffen, besonders wenn man das Programm aus der IDE startet.
-
manni66 schrieb:
Wann hört die Schleife wohl auf? Was ist mit Fehlern?
Ja, richtig. Also falsch. Habs so hin geschmiert. Na sollte aber keine große Herausforderung sein, das zu ergänzen. Das Prinzip sollte aber klar sein.
-
Hallo Julian,
Versuche mal unten stehenden Code. Damit schaffe ich 80Millionen 4-stellige Integer-Werte (Datei = 40MB groß) in 0,6 Sekunden in einen std::vector zu schaufeln. Das Lesen selbst liegt bei ca. 0,5s und der std:vector kostet 0,1s.
Du könntest alternativ eine std::deque<> verwenden.Julian90 schrieb:
... die Daten muss ich ja erstmal in eine Datenstruktur schieben
Nö - nicht 'erstmal' sondern gleich in das Ziel. Daher blebt die Frage nach der entgüligen Verwendung der Daten. Das ist auch entscheidend für die Art&Weise des Einlesens.
#include <fstream> #include <iostream> #include <chrono> #include <locale> // std::num_get<> #include <vector> class NumGet : public std::num_get< char > { public: using iter_type = std::istreambuf_iterator< char, std::char_traits< char > >; NumGet() : std::num_get< char >() {} protected: iter_type do_get( iter_type in, iter_type end, std::ios_base&, std::ios_base::iostate& err, long& v) const override { // Achtung: liest nur positive Werte long l = 0; for( ; in != end; ++in ) { if( '0' <= *in && *in <= '9' ) (l *= 10) += int(*in - '0'); // Achtung: KEIN Check auf overflow else { v = l; return in; } } err |= std::ios_base::failbit; return in; } }; class Alles { public: using target_type = std::vector< int >; Alles( target_type& target ) : target_( target ) {} friend std::istream& operator>>( std::istream& in, const Alles& all ) { std::istream::sentry ok( in ); using Traits = std::istream::traits_type; if( ok ) { std::ios_base::iostate state = std::ios_base::goodbit; const NumGet num_get; try { const std::ctype< char >& ctype_ = std::use_facet< std::ctype< char > >( in.getloc() ); std::istreambuf_iterator< char > last; for(;;) { // -- skip leading whitespace Traits::int_type m = in.rdbuf()->sgetc(); for( ;; m = in.rdbuf()->snextc() ) { if( Traits::eq_int_type( m, Traits::eof() ) ) { state |= std::ios_base::eofbit; break; } else if( !ctype_.is( std::ctype_base::space, Traits::to_char_type(m) ) ) break; // kein whitespace } if( state == std::ios_base::eofbit ) break; // Lesen am Dateiende ohne Fehler beenden // -- Integer einlesen long wert = 0; num_get.get( std::istreambuf_iterator< char >( in.rdbuf() ), last, in, state, wert ); if( state != std::ios_base::goodbit ) break; all.target_.push_back( wert ); // <====== was soll mit den Werten geschehen? } } catch(...) { state |= std::ios_base::badbit; if( in.exceptions() & std::ios_base::badbit ) throw; } in.setstate( state ); } return in; } private: target_type& target_; }; int main() { using namespace std; ifstream in("big.txt"); auto start = chrono::steady_clock::now(); std::vector< int > daten; if( !(in >> Alles(daten)) ) cerr << "Fehler beim Lesen" << endl; auto ende = chrono::steady_clock::now(); cout << "Dauer: " << chrono::duration_cast< chrono::milliseconds >(ende-start).count() << "ms" << endl; cout << "Anzahl= " << daten.size() <<endl; return 0; }
Gruß
Werner