Mehrere Vektoren in neuem Vektor zusammenfügen



  • Was sagt denn Dein Profiler, wo die Zeit "vertrödelt" wird? Den würde ich ja als erstes anschmeißen, um zu gucken, was man vielleicht umbauen sollte. Beispielsweise kann ich mir vorstellen, dass Dein Ansatz gar nicht viel helfen wird, weil Du am Ende immer noch einen Vektor hast, der nur Zeiger speichert und die Objekte, auf die gezeigt werden irgendwie in beliebiger Reihenfolge im Speicher stehen können. Damit produzierst Du so oder so relativ viele "cache misses".

    Werner_logoff schrieb:

    Verbesserungsvorschlag für den operator+:

    template <class T>
    std::vector<T> operator +( const std::vector<T>& Vektor1, const std::vector<T>& Vektor2)
    {
        std::vector<T> SammelVektor( Vektor1 ); // <-- teuer
        SammelVektor.insert(SammelVektor.end(),Vektor2.begin(), Vektor2.end());
        return SammelVektor;
    }
    

    ... sollte etwas performanter sein.

    Verbesserungsvorschlag für den Verbesserungsvorschlag:

    template <class T>
    std::vector<T> operator +( std::vector<T> Vektor1, const std::vector<T>& Vektor2)
    { // Kopie kann ggf wegoptimiert werden ^^^^^^^^^
        std::vector<T> SammelVektor; // <-- billig
        SammelVektor.swap(Vektor1);  // <-- billig
        SammelVektor.insert(SammelVektor.end(),Vektor2.begin(), Vektor2.end());
        return SammelVektor;
    }
    

    Wenn Du durch Einsatz von pass-by-value eine manuelle Kopie sparen kannst, bevorzuge pass-by-value und lass den Compiler etwas kopieren, wenn es nötig ist. Diese Implementierung ist in keinem Fall schlechter als Deine, nutzt aber die "copy elision"-Optimierung bei modernen Compilern aus.



  • Warum dann noch den Umweg über SammelVektor?

    template<typename T>
    std::vector<T> operator +( std::vector<T> v1, const std::vector<T>& v2 )
    {
       v1.insert( v1.end(), v2.begin(), v2.end() );
       return v1;
    }
    


  • DocShoe schrieb:

    Warum dann noch den Umweg über SammelVektor?

    Er hat ja gesagt, v1 und v2 müssen dann noch unanbhängig voneinander auf unterschiedliche Weise bearbeitet werden.



  • medic123123 schrieb:

    @all:
    Fehlermeldung: Intellisense: Kein "=" Operator stimmt mit diesen Operanden überein.
    Kompilieren: Binärer Operator '=': Es konnte kein Operator gefunden werden, der einen linksseitigen Operanden vom Typ 'const std::vector<_Ty>' akzeptiert (oder keine geeignete Konvertierung möglich)
    1> with
    1> [
    1> _Ty=BattPackage::MyClass *
    1> ] ...

    Dein Compiler sagt, dass der Vektor, dem Du das Ergebnis Deiner Berechnung zuweisen willst, const ist. Hat mit dem operator+ nichts zu tun.



  • krümelkacker schrieb:

    Verbesserungsvorschlag für den Verbesserungsvorschlag:

    template <class T>
    std::vector<T> operator +( std::vector<T> Vektor1, const std::vector<T>& Vektor2)
    { // Kopie kann ggf wegoptimiert werden ^^^^^^^^^
        std::vector<T> SammelVektor; // <-- billig
        SammelVektor.swap(Vektor1);  // <-- billig
        SammelVektor.insert(SammelVektor.end(),Vektor2.begin(), Vektor2.end());
        return SammelVektor;
    }
    

    Wenn Du durch Einsatz von pass-by-value eine manuelle Kopie sparen kannst, bevorzuge pass-by-value und lass den Compiler etwas kopieren, wenn es nötig ist. Diese Implementierung ist in keinem Fall schlechter als Deine, nutzt aber die "copy elision"-Optimierung bei modernen Compilern aus.

    Ok - man lernt ja nie aus. Und was ist der Unterschied obiger Variante zu

    template <class T>
    std::vector<T> operator +( std::vector<T> SammelVektor, const std::vector<T>& Vektor2)
    {
        SammelVektor.insert(SammelVektor.end(),Vektor2.begin(), Vektor2.end());
        return SammelVektor;
    }
    

    ? - da war doch was, dass dann RVO nicht mehr gehen soll. Habe ich mal gehört/gelesen.



  • 1.@all:Code:

    using namespace std;
    #include "Cells.h"
    
    void BattPackage::Cells::vCreateNetwork() const {
    ...
    this->vecAllGNodes = this->vecCellArea[0]->ptRGrid->vecGNode
    ...
    }
    

    Fehlermeldung: Intellisense: Kein "=" Operator stimmt mit diesen Operanden überein.
    Kompilieren: Binärer Operator '=': Es konnte kein Operator gefunden werden, der einen linksseitigen Operanden vom Typ 'const std::vector<_Ty>' akzeptiert (oder keine geeignete Konvertierung möglich)
    1> with
    1> [
    1> _Ty=BattPackage::MyClass *
    1> ] ...

    2. Mein Profiler sagt gar nichts, da ich keinen habe. Ich werd mich darüber mal schlau machen...

    3.Ja der "+" Operator scheint zu funktionieren. Aber ohne den "=" Operator für meine Vektoren anwenden zu können bringt mir das nicht viel. Aus welchem (wahrscheinlich ziemlich trivialen Grund) will der denn nicht so wie er soll?
    Beide Operanden sind nicht explizit als const deklariert...



  • medic123123 schrieb:

    1.@all:Code:

    using namespace std;
    #include "Cells.h"
    
    void BattPackage::Cells::vCreateNetwork() [b]const[/b] { // <=================
    ...
    this->vecAllGNodes = this->vecCellArea[0]->ptRGrid->vecGNode
    ...
    }
    


  • Argh...gar nicht mehr drauf geachtet...
    Jetzt tuts wie es soll.
    Vielen vielen dank soweit. Ich werde mal versuchen den ganzen input, den ich hier gekriegt habe zu verarbeiten.

    Gruß, Michael



  • Werner_logoff schrieb:

    krümelkacker schrieb:

    Verbesserungsvorschlag für den Verbesserungsvorschlag:
    [...]
    Wenn Du durch Einsatz von pass-by-value eine manuelle Kopie sparen kannst, bevorzuge pass-by-value und lass den Compiler etwas kopieren, wenn es nötig ist. Diese Implementierung ist in keinem Fall schlechter als Deine, nutzt aber die "copy elision"-Optimierung bei modernen Compilern aus.

    Ok - man lernt ja nie aus. Und was ist der Unterschied obiger Variante zu

    template <class T>
    std::vector<T> operator +( std::vector<T> SammelVektor, const std::vector<T>& Vektor2)
    {
        SammelVektor.insert(SammelVektor.end(),Vektor2.begin(), Vektor2.end());
        return SammelVektor;
    }
    

    ? - da war doch was, dass dann RVO nicht mehr gehen soll. Habe ich mal gehört/gelesen.

    Ja, so kann NRVO nicht mehr funktionieren. Aber in C++11 wäre das so okay. Da wird dann im Notfall eben move-konstruiert. Es kommt in C++11 also auf fast das gleiche raus.


  • Mod

    Werner_logoff schrieb:

    Und was ist der Unterschied obiger Variante zu

    template <class T>
    std::vector<T> operator +( std::vector<T> SammelVektor, const std::vector<T>& Vektor2)
    {
        SammelVektor.insert(SammelVektor.end(),Vektor2.begin(), Vektor2.end());
        return SammelVektor;
    }
    

    ? - da war doch was, dass dann RVO nicht mehr gehen soll. Habe ich mal gehört/gelesen.

    Das hat einen technischen Hintergrund (der Standard erlaubt NRVO auch in diesen Fällen). Für die Speicherresevierung von Funktionsparametern und dem Rückgabewert ist normalerweise der Aufrufer zuständig (weil diese ja über die Dauer des Funktionsaufrufes hinaus leben - die Parameter vor Aufruf, der Rückgabewert noch danach). Um nun NRVO auch für Funktionsparameter zu ermöglichen, müsste also der Aufrufer bereits vor dem Aufruf wissen, dass der jeweilige Parameter auch das Rückgabeobjekt sein wird. Das ist im Prinzip nur dann möglich, wenn diesem der Code der aufgerufenen Funktion bekannt ist. Erfahrungsgemäß führen Compiler aber selbst dann diese Optimierung nicht durch, wenn die Funktion geinlined wird (sollte die Kopie in Einzelfällen dann doch vermieden werden, dürfte das eher eine echte as-if-Optimierung sein).


Anmelden zum Antworten