den Code vom Chefe optimieren ^^



  • finix schrieb:

    T const& get_at( std::size_t x, std::size_t y ) const
    {
      std::size_t const index = x * m_n + y;
      if (index > last_index_) {
        throw std::range_error("out of bounds");
      }
      return m_values[index];
    }
    

    Achja? Aber wenns nach dir geht darf man in einem 1000x1 Feld auf das Element [0][999] und [999][0] und sogar [1000][0] und [0][1000] zugreifen.



  • finix schrieb:

    T const& get_at( std::size_t x, std::size_t y ) const
    {
      std::size_t const index = x * m_n + y;
      if (index > last_index_) {
        throw std::range_error("out of bounds");
      }
      return m_values[index];
    }
    

    eigentlich falsch. überläufe nicht bedacht.
    aber der unsigned-trick ist fein.



  • nunununu schrieb:

    T get_at( unsigned x, unsigned y ) const 
            { 
                if( ( x < m_m ) && ( y < m_n ) && y & x) 
                { 
                    return m_values[ x * m_n + y ]; 
                } 
                throw std::range_error( "out of bounds" ); 
            }
    

    Das & x&y muss natuerlich weg, weis net was ich dabei gedacht hab. Wollte irgendwie die 0 weg haben.



  • nunununu schrieb:

    T get_at( unsigned x, unsigned y ) const 
            { 
                if( ( x < m_m ) && ( y < m_n ) && y & x) 
                { 
                    return m_values[ x * m_n + y ]; 
                } 
                throw std::range_error( "out of bounds" ); 
            }
    

    Ich hab es buchstabentechnisc optimiert, auf das seid ihr doch immer so geil!
    Ist aber wahrscheinlich so eher langsamer / gleich schnell.

    warum das "&& y & x" ?
    ohne dem isses richtiger und schneller.



  • volkard schrieb:

    eigentlich falsch. überläufe nicht bedacht.
    aber der unsigned-trick ist fein.

    Verrat mir den Trick, bitte 🙂



  • Opti schrieb:

    volkard schrieb:

    eigentlich falsch. überläufe nicht bedacht.
    aber der unsigned-trick ist fein.

    Verrat mir den Trick, bitte 🙂

    unsigned Werte sind nie negativ 😉

    ps: volkhard du bist einfach zu langsam! 😃



  • nunununu schrieb:

    T get_at( unsigned x, unsigned y ) const 
            { 
                if( ( x < m_m ) && ( y < m_n ) && y & x) 
                { 
                    return m_values[ x * m_n + y ]; 
                } 
                throw std::range_error( "out of bounds" ); 
            }
    

    Ich hab es buchstabentechnisc optimiert, auf das seid ihr doch immer so geil!
    Ist aber wahrscheinlich so eher langsamer / gleich schnell.

    Wenn jemand hier für x und y 0 eingibt kommt bei x & y auch 0 raus, wodurch dann die exception getriggert wird.

    Edit: zu langsam getipped 😉



  • Finde es amüsant, dass die vorgeschlagenen Optimierungen keine sind 😃

    Ich würd es zu folgendem ändern:

    const T& get_at( size_t x, size_t y ) const
            {
                if( ( x >= m_m ) || y >= m_n )
                  throw std::range_error( "out of bounds" );
    
                return m_values[ x * m_n + y ];
            }
    

    Nen signed Typ für die Indizes zu nehmen ist ein Fehler, wenn negative Werte keine gültigen Werte sind. Eine const-Referenz zurückzugeben ist sicher auch nicht verkehrt, aber bei kleinen Typen wäre es ja egal.



  • lolz schrieb:

    Nen signed Typ für die Indizes zu nehmen ist ein Fehler, wenn negative Werte keine gültigen Werte sind. Eine const-Referenz zurückzugeben ist sicher auch nicht verkehrt, aber bei kleinen Typen wäre es ja egal.

    Was heisst klein? Es sind Zeiger:

    private:
    		T* m_values;
    		unsigned m_m;
    		unsigned m_n;
    


  • Und was wäre hier zu machen?

    bool operator==( const Creature& lhs, const Creature& rhs )
    {
    	return typeid( lhs ) == typeid( rhs ) ? true : false;
    }
    

    Zwei Kreaturen sollen auf gleiche Art verglichen werden.
    Arten sind Subklassen von Creature,



  • double dispatch!



  • Opti schrieb:

    Und was wäre hier zu machen?

    bool operator==( const Creature& lhs, const Creature& rhs )
    {
    	return typeid( lhs ) == typeid( rhs ) ? true : false;
    }
    

    Zwei Kreaturen sollen auf gleiche Art verglichen werden.
    Arten sind Subklassen von Creature,

    Wenn die "optimierte" Version 100% dasselbe verhalten haben soll kann man hier garnix machen, ausser den sinnlosen "?" Operator wegmachen (was bei einem guten Compiler aber genau 0 Auswirkungen auf die Laufzeit haben wird).

    Double dispatch (wurde erwähnt) wäre eine Möglichkeit wenn man in alle Subklassen eingreifen kann und möchte.



  • Nee, also double dispatch funktioniert hier nicht.
    Ich beschreib mal das Problem:
    Es wird eine Liste (std::list) erstellt mit verschiedenen Creatures
    Aus dieser Liste sollen alle entfernt werden, die nicht einer bestimmten Art entsprechen.
    Es gibt einen Funktor (remove_if_not) und der op() vergleicht die beiden Creatures. Der oben gezeigte op= dient dazu als predicate.

    Wäre es ev. schneller, den Creature Subtypen eine static ID mitzugeben, die dann verglichen wird?



  • Opti schrieb:

    Wäre es ev. schneller, den Creature Subtypen eine static ID mitzugeben, die dann verglichen wird?

    Mit dem MSVC wäre das garantiert um einiges (!) schneller.
    (Andere compiler weiss ich nicht, müsstest du ausprobieren)



  • Das ist mit dem gcc sogar langsamer 😞


Anmelden zum Antworten