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


Anmelden zum Antworten