[gelöst] Vector ist wesentlich langsamer als Array?



  • zeusosc schrieb:

    @ComputerCarl:
    Ok,.. also nach der Konstruktion hast Du aber eine fixe anzahl an Schichten und
    Neuronen?

    Genau! Nach dem Konstruktor sind alle Attribute fest in der Anzahl ihrer Dimensionen.



  • Wenn Dir M[i] Deine Schicht indiziert und M[i][j] Dein Neuron
    brauchst Du also "nur" ein zur Initialisierungszeit dynamisches array...

    Dein Neuron hat welche Parameter?

    typedef struct _neuron
    {
    double* weight; // gewichte der eingänge
    
    LPVOID _ue_func; //zeiger auf eine Gewichtungsfunktion (übertragungsfunktion)
    LPVOID _outbarrier_func;// Ausgangsschwellenfunktion, also aktivierungsfunktion
    }
    

    oder sind die Gewichte bei Dir schon mit M[i][j][w] gegeben?

    grüße
    ------
    edit:
    ahh ok,.. ich sehe es gerade,..
    ich bastele mal was



  • Wenn Dir M[i] Deine Schicht indiziert und M[i][j] Dein Neuron
    brauchst Du also "nur" ein zur Initialisierungszeit dynamisches array...

    -> Das sehe ich noch nicht, aber das muss nichts heißen.
    Also kurz ich weiß nicht, wie ich die eine Dimension reduzieren kann.
    Ich mein, ich könnte mir die Anzahl der Schichten mit der Anzahl der Neuronen
    zwischen-speichern und somit die "Referenzierung" auf ein Index selber zusammen basteln, aber ich weiß nicht ob das gemeint ist.

    Dein Neuron hat welche Parameter?

    typedef struct _neuron
    {
    double* weight; // gewichte der eingänge
    
    LPVOID _ue_func; //zeiger auf eine Gewichtungsfunktion (übertragungsfunktion)
    LPVOID _outbarrier_func;// Ausgangsschwellenfunktion, also aktivierungsfunktion
    }
    

    oder sind die Gewichte bei Dir schon mit M[i][j][w] gegeben?

    Na ja nicht ganz... ein Neuron hat soviele Gewichte wie Neuronen in der vorhergehenden Schicht. Also jede Verbindung von Neuron j aus Schicht i
    führt zu Neuron k in Schicht i+1. Die Gewichte sind in w[i][j][k] gespeichert.
    wTx in activate liefert mir somit die Aktivierung durch die Vorgänger-Neuronen und der tanh(beta * (wTx - bias)) bestimmt somit die Weiterleitung in die Nächste Schicht. Diese wird in M[i+1][k] gespeichert.

    Welche Funktionen LPVOID ... übernehmen sollen kann ich erahnen, sehe aber nicht die Notwendigkeit.



  • Ich werde jetzt bis morgen früh erst mal das Feld räumen.
    Sollten noch Fragen an mich kommen also nicht warten. Ich
    werde heut nicht mehr antworten.
    Um aber vielleicht ein besseres Bild von solch einem Netz
    zu schaffen wollte ich nur ebenmal eine graphische Darstellung
    posten. Auf dieser Seite wäre solch ein Netz, was eigentlich
    in meinem Code implementiert wurde. Text der Seite hab ich nicht
    mehr gelesen nur die Darstellung ist denke ich hilfreich.

    http://www.google.de/imgres?imgurl=http://193.25.32.158/fb2/prof/skrueger/images/stories/neuronetze/rendite.gif&imgrefurl=http://www.kolleg.wi.hs-anhalt.de/fb2/prof/skrueger/index.php%3Foption%3Dcom_content%26view%3Darticle%26id%3D72%26Itemid%3D85&usg=__Wf5XkEsDvPGlCUYNBuxG8SVVb9k=&h=226&w=462&sz=26&hl=de&start=0&zoom=1&tbnid=Y-uU2AeUVBalsM:&tbnh=88&tbnw=179&ei=fwcjT67FA86Rswbkt5yTDw&prev=/search%3Fq%3Dk%C3%BCnstliches%2Bneuronales%2Bnetz%26um%3D1%26hl%3Dde%26sa%3DN%26biw%3D1920%26bih%3D917%26tbm%3Disch&um=1&itbs=1&iact=rc&dur=176&sig=107543848169332014707&page=1&ndsp=45&ved=1t:429,r:14,s:0&tx=74&ty=42

    Hier das Bild isoliert:
    http://193.25.32.158/fb2/prof/skrueger/images/stories/neuronetze/rendite.gif



  • Ach schade,.. bin gerade fertig geworden,...

    Naja vlt können die anderen das ja mal auseinander nehmen:

    //#######################################################################################################
    // Base Array class deklaration
    //#######################################################################################################
    
    template<typename T>
    class _base_array
    {
    private:
    	T *_ptr;
    	unsigned int size;
    
    	bool _malloc(unsigned int Size);
    	void _free(void);
    	void _clear_all(void);
    public:
    	_base_array();
    	_base_array(unsigned int Size);
    	~_base_array();
    	void reserve(unsigned int Size); // just call it ONCE
    	unsigned int _nr_of_elements(void);	// returns the absolute number of accessable elements
    	unsigned int _size(void);	//returns the size of array in Bytes
    	T & operator[](int Index);
    };
    
    //#######################################################################################################
    // Base Array class definitions
    //#######################################################################################################
    template<typename T>
    bool _base_array<T>::_malloc(unsigned int Size)
    {
    	bool bRet=false;
    	if(	this->_ptr ) return bRet;
    
    	this->_ptr=reinterpret_cast<T*>(malloc(sizeof(T)*Size));
    	if(	!this->_ptr ) 
    	{
    		this->size=0;
    		return bRet;
    	};
    
    	this->size=Size;
    
    	for(int i=0; i<Size; i++)
    		(*(this->_ptr+i))=T();
    
    return !bRet;
    };
    
    template<typename T>
    void _base_array<T>::_free()
    {
    if(!this->_ptr)
    {
    	this->size=0;
    	return;
    };
    
    free(reinterpret_cast<void*>(this->_ptr));
    
    this->_ptr=reinterpret_cast<T*>(0);
    this->size=0;
    };
    template<typename T>
    void _base_array<T>::reserve(unsigned int Size)
    {
    	this->_malloc(Size);
    };
    
    template<typename T>
    void _base_array<T>::_clear_all()
    {
    	this->size=0;
    	this->_ptr=reinterpret_cast<T*>(0);
    };
    
    template<typename T>
    _base_array<T>::~_base_array()
    {
    	this->_free();
    	this->_clear_all();
    };
    
    template<typename T>
    _base_array<T>::_base_array()
    {
    	this->_clear_all();
    };
    
    template<typename T>
    _base_array<T>::_base_array(unsigned int Size)
    {
    	this->_clear_all();
    
    	this->_malloc(Size);
    };
    
    template<typename T>
    unsigned int _base_array<T>::_nr_of_elements()
    {
    	return this->size;
    };
    
    template<typename T>
    unsigned int _base_array<T>::_size()
    {
    	return this->size*sizeof(T);
    };
    
    template<typename T>
    T & _base_array<T>::operator [](int Index)
    {
    	if((Index <0 )|| (static_cast<unsigned int>(Index) > this->size-1)) 
    		return *(new T());
    
    	return *(this->_ptr +Index);
    };
    //#######################################################################################################
    
    typedef _base_array<int> _bai;
    typedef _base_array<_bai> _cai;
    typedef _base_array<_cai> _dai;
    
    //#######################################################################################################
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	_bai b(12);
    	_cai c(12);
    	_dai d;
    	d.reserve(12);
    
    	for(int i=0; i<12; i++)
    	{
    		b[i]=i;
    		c[i].reserve(12);
    		d[i].reserve(12);
    	};
    
    	for(int x=0; x<12; x++)
    	{
    		for(int y=0; y<12; y++)
    		{
    			d[x][y].reserve(12);
    
    		}
    	};
    
    	for(int x=0; x<12; x++)
    	{
    		for(int y=0; y<12; y++)
    		{
    			for(int z=0; z<12; z++)
    			{
    				d[x][y][z]=x+y*12+z*12*12; //weiß nicht ob die rechnung richtig ist,...
    			}
    		}
    	};
    
    	__debugbreak();
    
    	return 0;
    }
    

    grüße



  • Warum benennst du deine Klassen so grausam mit dem _ als Präfix?



  • Ja,..
    Warum machen andere das nicht?
    _Weil _man _die _Freiheit _hat das zu tun und zu lassen was man will,..
    ... und ausserdem ließt und schreibt sich das für mich leichter,...
    Ansonste fällt mir nicht mehr ein..



  • zeusosc schrieb:

    Warum machen andere das nicht?

    Weil alle Bezeichner vom Standard reserviert sind, die mit einem Unterstrich starten auf welchen ein Großbuchstabe folgt. Ok, deine Bezeichner sind zwar nicht nicht standardkonform, aber doch mehr als unüblich. Vor allem für Klassen und Funktionen. Da sind insgesamt noch so einige Hauer drin, aber da will ich jetzt nicht drauf eingehen, irgendjemand nimmt sich bestimmt die Zeit. 😉



  • Ok,..

    soweit ich weiss folgt bei mir auf den Unterstrich aber ein
    kleiner Buchstabe bzw. eine Zahl.
    Daher unterscheidet sich das von dem reservierten,..

    Hauerdrinn?

    jetzt bin ich neugierig,... auslernen will ich ja auch nicht,...



  • wow... Danke!
    Ich muss mich da erstmal reinlesen. Diesen "erfahrenen"
    Programmierstil bin ich noch nicht gewöhnt. Aber ich
    glaube zu sehen was gemeint ist. Werde einfach meinen
    Code überarbeiten (angelehnt an das gepostete).

    Vielen Dank an alle die Tipps gegeben haben. Ich
    werde jetzt einfach mal das Thema als gelöst markieren.



  • zeusosc schrieb:

    Hauerdrinn?

    jetzt bin ich neugierig,... auslernen will ich ja auch nicht,...

    Keine Sorge, "Auslernen" wirst du so schnell sicher nicht. 😉

    - Die sehr hässlichen _ am Anfang wurden ja schon erwähnt.
    - Ein komisches selbst gebasteltes malloc statt new[]? 😮
    - Cast nach void*?
    - Cast von 0 nach T*?
    - Das ständige this-> irritiert total.
    - Nicht richtig eingerückt.
    - Komische und unnötige ; hinter if() und hinter Funktionen, die den Lesefluss total behindern.
    - Index von operator [] nicht unsigned.

    Und wo bitte ist bei dir überhaupt der Vorteil zu std::vector? Im Speicher liegt doch immer noch alles kreuz und quer, oder habe ich in dem WirrWarr jetzt den Super-Trick übersehen?



  • @ComputerCarl

    Was du noch machen kannst, wenn die Dimensionen zwar fest aber erst zur Laufzeit bekannt sind, ist, dir eine Klasse zu bauen, die Größenangaben zu den Dimensionen im Konstruktor nimmt, und dann Zugriff über operator () mit drei Indexvariablen auf einmal gibt. (Intern nutzt du einfach einen std::vector und reservierst sx * sy * sz Elemente am Stück).

    int main()
    {
      unsigned sx, sy, sz; // Werte einlesen
      DeineKlasse<float> mat(sx, sy, sz);
      mat(5, 7, 3) = 77; // Zugriff
    }
    

    Ob das viel schneller ist weiß ich nicht, da du den Index halt auch zur Laufzeit ausrechnen musst. (Das sind halt Multiplikationen, wie man die Dimensionen runterrechnet weißt du?)
    Aber ich denke mal einen Versuch ist es wert.


  • Mod

    cooky451 schrieb:

    Ob das viel schneller ist weiß ich nicht, da du den Index halt auch zur Laufzeit ausrechnen musst. (Das sind halt Multiplikationen, wie man die Dimensionen runterrechnet weißt du?)
    Aber ich denke mal einen Versuch ist es wert.

    Glaub mir, das ist VIEL ⚠ ⚠ ⚠ schneller.

    Was ist denn Arraydereferenzierung? Additionen und Multiplikationen. Es ist daher so schnell wie ein zusammenhängendes Array mit dem Komfort eines Containers.



  • SeppJ schrieb:

    Was ist denn Arraydereferenzierung? Additionen und Multiplikationen. Es ist daher so schnell wie ein zusammenhängendes Array mit dem Komfort eines Containers.

    Äh ja, stimmt, der Index muss ja auch bei statischen Arrays errechnet werden, irgendwie hatte ich da einen Denkfehler. Super, dann dürfte das ja die Lösung sein.



  • zeusosc schrieb:

    soweit ich weiss folgt bei mir auf den Unterstrich aber ein
    kleiner Buchstabe bzw. eine Zahl.

    17.6.4.3.2: Global names, zweiter Punkt:

    Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.

    Deine Klasse liegt im global namespace, deshalb ist ALLES was mit einem einzigen Unterstrich beginnt, ebenso der Implementierung vorbehalten und sollte vom User nicht verwendet werden.



  • cooky451 schrieb:

    zeusosc schrieb:

    Hauerdrinn?

    jetzt bin ich neugierig,... auslernen will ich ja auch nicht,...

    Keine Sorge, "Auslernen" wirst du so schnell sicher nicht. 😉

    - Die sehr hässlichen _ am Anfang wurden ja schon erwähnt.
    - Ein komisches selbst gebasteltes malloc statt new[]? 😮
    - Cast nach void*?
    - Cast von 0 nach T*?
    - Das ständige this-> irritiert total.
    - Nicht richtig eingerückt.
    - Komische und unnötige ; hinter if() und hinter Funktionen, die den Lesefluss total behindern.
    - Index von operator [] nicht unsigned.

    Und wo bitte ist bei dir überhaupt der Vorteil zu std::vector? Im Speicher liegt doch immer noch alles kreuz und quer, oder habe ich in dem WirrWarr jetzt den Super-Trick übersehen?

    Also, trick ist da keiner.
    Die Anforderung war (so wie ich das sah):
    Schreibe ein zur initialisierungszeit dynamisches Array auf
    das man mit [][][] zugreifen kann, und recht fix ist.

    STL vectoren springen häufig durch verschiedene Unterfunktionen,
    die die Länge prüfen, ob der Zeiger richtig ist und und und,..
    hier wird alloziiert und über maximal zwei ptrs beim zugriff
    dereferenziert (und auf das dritte dan referenziert)...
    sollte also relativ flink laufen,..

    Jetzt mal vom underscore abgesehen:

    * Zum new: ich vermeide es wo ich kann! (hier nutze ich es exakt 1x)
    Wird der new operator nicht über den source definiert, so findet
    eine (Compiler spezifische) Ersetzung statt, die ich erst zur Laufzeit
    sehe. Das will ich nicht!

    * Cast von 0 nach T* : 0 ist kein Typ.
    Sind verschiedene konvertierungsvorschrifften vorhanden,
    wird die erste passende vom Compiler genommen. (Meistens basistypen).
    Ich will das der Compiler "explizit" 0 als T* behandelt.

    * Cast nach void*: sehe ich jetzt nicht,.. wo?

    * Index operator [] nicht unsigned: Ja,.. kann man so und so sehen,
    "ist übergebene uint > size dann gib referenz" wäre hier wohl
    bessere wahl gewesen, da hast du recht...

    * this-> bleibt definitiv !!! es ist ein unterschied ob ich eine
    Methode der Instanz aufrufe oder eine gleichnamige Funktion aus
    dem gleichen Namensraum, geschweige denn Member.
    Da der Compiler das so oder so die addy's der Member aus der
    Referenzierung des this holt (in asm schön sichtbar), dann
    kann ich es auch gleich richtig machen. Ausserdem ist dann
    IMMER klar, WANN ich eine Methode oder Member innerhalb einer
    Methode aufrufe,...
    (Macht sich besonders bemerkbar wenn intellisense spinnt)

    * Einrückung: hä? wie was? wo?
    Es gibt ja mal wohl mehrere Varianten von einrückungen...

    * ";" ?? Meines wissens hat nach jeder abgeschlossenen Anweisung ein ";"
    zu folgen. Auch wenn manchen Compilern das wurscht ist....

    Also bis auf die underscores und dem uint (danke, ja da haste ja recht)
    sehe ich jetzt nicht viele hauerdrinn,...

    @Cookie457:
    Ja, hatte ich auch zuerst überlegt,... dann dachte ich, bevor er sich
    mit "suchen und ersetzen" menüpunkt anlegt um die [i][j][k] durch
    (i,j,k) zu ersetzen, gleich n template mit variabler dim anzahl
    basteln. Er nutzt ja mehrere 1d 2d und 3d arrays.,...

    grüße


  • Mod

    zeusosc schrieb:

    STL vectoren springen häufig durch verschiedene Unterfunktionen,
    die die Länge prüfen, ob der Zeiger richtig ist und und und,..

    Wenn du mit "häufig" meinst "im Debugmodus", dann kann man das so stehen lassen.



  • zeusosc schrieb:

    STL vectoren springen häufig durch verschiedene Unterfunktionen,
    die die Länge prüfen, ob der Zeiger richtig ist und und und,..
    hier wird alloziiert und über maximal zwei ptrs beim zugriff
    dereferenziert (und auf das dritte dan referenziert)...
    sollte also relativ flink laufen,..

    Ein std::vector macht genau das gleiche. (Im Releasemodus). Nein, warte, er ist viel schneller als deine Version, weil er den Index nicht testet.

    zeusosc schrieb:

    * Zum new: ich vermeide es wo ich kann! (hier nutze ich es exakt 1x)
    Wird der new operator nicht über den source definiert, so findet
    eine (Compiler spezifische) Ersetzung statt, die ich erst zur Laufzeit
    sehe. Das will ich nicht!

    Bitte was?

    zeusosc schrieb:

    * Cast von 0 nach T* : 0 ist kein Typ.
    Sind verschiedene konvertierungsvorschrifften vorhanden,
    wird die erste passende vom Compiler genommen. (Meistens basistypen).
    Ich will das der Compiler "explizit" 0 als T* behandelt.

    Ja.. dann nimm nullptr. 😉

    zeusosc schrieb:

    * Cast nach void*: sehe ich jetzt nicht,.. wo?

    In Zeile 58.

    zeusosc schrieb:

    * Index operator [] nicht unsigned: Ja,.. kann man so und so sehen,
    "ist übergebene uint > size dann gib referenz" wäre hier wohl
    bessere wahl gewesen, da hast du recht...

    Nein, die bessere Wahl wäre gewesen, den Test einfach nicht zu machen.

    zeusosc schrieb:

    * this-> bleibt definitiv !!! es ist ein unterschied ob ich eine
    Methode der Instanz aufrufe oder eine gleichnamige Funktion aus
    dem gleichen Namensraum, geschweige denn Member.
    Da der Compiler das so oder so die addy's der Member aus der
    Referenzierung des this holt (in asm schön sichtbar), dann
    kann ich es auch gleich richtig machen.

    Was heißt hier "richtig", es macht halt keinen Unterschied, aber das this wegzulassen ist übersichtlicher.

    zeusosc schrieb:

    Ausserdem ist dann
    IMMER klar, WANN ich eine Methode oder Member innerhalb einer
    Methode aufrufe,...
    (Macht sich besonders bemerkbar wenn intellisense spinnt)

    Das ist auch so klar. Mehr noch, this-> impliziert, dass diese explizite Schreibweise nötig ist, weil sonst etwas Anderes gemeint wäre. Daher sollte man es meiden, wenn dem nicht so ist.

    zeusosc schrieb:

    * Einrückung: hä? wie was? wo?
    Es gibt ja mal wohl mehrere Varianten von einrückungen...

    Das hat nichts mehr mit Stil zu tun, das ist einfach falsch bzw. teilweise gar nicht eingerückt.

    zeusosc schrieb:

    * ";" ?? Meines wissens hat nach jeder abgeschlossenen Anweisung ein ";"
    zu folgen. Auch wenn manchen Compilern das wurscht ist....

    Nein, keinem Compiler ist das egal. Aber leere ; sind jedem Compiler egal, deswegen kompiliert der Code überhaupt. Auf einen Scope muss kein ; folgen. (Und sollte dadurch auch nicht.)

    zeusosc schrieb:

    nicht viele hauerdrinn,...

    Doch, das malloc Gefrickel ist eines der übelsten Sachen die ich seit Langem gesehen habe. Und wenn der Index nicht mehr gültig ist gibt man einfach einen *new T() zurück der nie mehr freigegeben wird? 😮

    zeusosc schrieb:

    gleich n template mit variabler dim anzahl
    basteln. Er nutzt ja mehrere 1d 2d und 3d arrays.,...

    Das funktioniert nicht. Die Dimensionen sind erst zur Laufzeit bekannt, wären sie zur Compilezeit bekannt, könnte man auch einen std::vector<std::array<...>> nehmen. Daher fällt jegliches Templategezauber weg.



  • Ich hoffe, du schaust nochmal in den Thread rein, auch wenn du das als (warum auch immer) gelöst markiert hast.

    Ich habe mal ein wenig Code aus meinem aktuellen Projekt extrahiert und soweit vereinfacht, dass du es mit deinem Kenntnisstand verstehen müsstest. Das ist natürlich so minimal wie möglich, aber es sollte dir schon mal einen deutlichen Speedup geben. Aber du musst noch eine Menge Code hinzufügen, damit das für dein neuronales Netz passt.

    Syntaxfehler könnten drin sein, und eventuell hab ich beim Umbauen auch igendwelche variablen vertauscht. Aber diese Fehler dienen dann nur dazu, dass du versuchst, den Code zu verstehen 😉 (jaja, ich bin gerade zu faul zum testen)

    //stores a matrix in row major format.
    //as minimal as possible, so it offers only element access via op():
    //matrix(i,j)= 10;
    //and a constructor which takes the dimensionality and a method which returns
    //the internal block of memory
    class Matrix{
    private:
        std::vector<float> data;
        std::size_t rows;
        std::size_t columns;
    public:
        Matrix(std::size_t nRows,std::size_t nColumns)
       :data(rows*columns),rows(nRows),columns(nColumns){}
    
       float& operator()(std::size_t row, std::size_t col){
           return data[row*columns+col];
       }
       float operator()(std::size_t row, std::size_t col)const{
           return data[row*columns+col];
       }
       std::size_t numRows()const{
           return rows;
       }
       std::size_t numColumns()const{
           return columns;
       }
       float const* storage()const{
           return &data[0];
       }
    };
    
    //prod(A,b,c) computes c+=A*b
    //where b,c are vectors and A is a matrix 
    void prod(
        Matrix const & matA,
        std::vector<float> const& vecB,
        std::vector<float& vecC,
    ){
    
        std::size_t n = matA.numRows();
        std::size_t k = matA.numColumns();
    
        //calculate 4 rows at the same time until the remaining number of columns is lower than 4. This saves memory accesses by a factor of 4.
        std::size_t maxRow=(n/4)*4;
        std::size_t row=0;
        while(row!= maxRow){
            float* A0 = matA.storage()+row*k;
            float* A1 = A0+k;
            float* A2 = A1+k;
            float* A3 = A2+k;
            float c0=0;
            float c1=0;
            float c2=0;
            float c3=0;
            for(std::size_t i = 0; i != k; ++i){
                c0+=A0[i]*vecB[i];
                c1+=A1[i]*vecB[i];
                c2+=A2[i]*vecB[i];
                c3+=A3[i]*vecB[i];
            }
            vecC[row]+=c0;
            vecC[row+1]+=c1;
            vecC[row+2]+=c2;
            vecC[row+3]+=c3;
            row+=4;
        }
        //calculate the remaining rows of the result
        for(;row!=n; ++row){
            float* A = matA.storage()+row*k;
            float c0=0;
            for(std::size_t i = 0; i != k; ++i){
                c0+=A[i]*vecB[i];
            }
            vecC[row]+=c0;
        }
    }
    
    //benutzung:
    
    Matrix m(20,10);
    std::vector<float> argument(10);
    std::vector<float> result(20);
    //some initialization skipped here
    prod(m,argument,result);
    

    hat bei mir im Test mit 512er quadratischen Matrizen ATLAS geschlagen. Aber ich gebe zu, dass ein Datenpunkt alleine da nicht wirklich ausschlaggebend ist 😉



  • @Otze:
    Für Matrixprodukt gibt es doch auch ne SSE2 Variante!??

    @cooky451:
    Hi, danke erst einmal das du Dich, auch wenn es etwas Threadfremd ist,
    damit beschäftigts... sieh bitte meine antworten nicht als lernunwillig,
    sondern als debattenbeitrag...

    cooky451 schrieb:

    zeusosc schrieb:

    STL vectoren springen häufig durch verschiedene Unterfunktionen,
    die die Länge prüfen, ob der Zeiger richtig ist und und und,..
    hier wird alloziiert und über maximal zwei ptrs beim zugriff
    dereferenziert (und auf das dritte dan referenziert)...
    sollte also relativ flink laufen,..

    Ein std::vector macht genau das gleiche. (Im Releasemodus). Nein, warte, er ist viel schneller als deine Version, weil er den Index nicht testet.

    echt? is natürlich doof (für mich). Ich werde das nachher mal testen...

    cooky451 schrieb:

    zeusosc schrieb:

    * Zum new: ich vermeide es wo ich kann! (hier nutze ich es exakt 1x)
    Wird der new operator nicht über den source definiert, so findet
    eine (Compiler spezifische) Ersetzung statt, die ich erst zur Laufzeit
    sehe. Das will ich nicht!

    Bitte was?

    Ja, new ist ein operator den man gerne überladen kann. Wird im Fall x
    kein new operator gefunden, z.b. bei einem Basistyp, nimmt der Compiler
    "seine" variante. Das sieht man im trivialsten Fall auch bei
    Zuweisungsoperatoren. Die definition solcher sind im sinne eigentlich
    überladungen....

    cooky451 schrieb:

    zeusosc schrieb:

    * Cast von 0 nach T* : 0 ist kein Typ.
    Sind verschiedene konvertierungsvorschrifften vorhanden,
    wird die erste passende vom Compiler genommen. (Meistens basistypen).
    Ich will das der Compiler "explizit" 0 als T* behandelt.

    Ja.. dann nimm nullptr. 😉

    hmm ja 🙂

    cooky451 schrieb:

    zeusosc schrieb:

    * Cast nach void*: sehe ich jetzt nicht,.. wo?

    In Zeile 58.

    //siehe
    void free ( void * ptr );
    

    cooky451 schrieb:

    zeusosc schrieb:

    * Index operator [] nicht unsigned: Ja,.. kann man so und so sehen,
    "ist übergebene uint > size dann gib referenz" wäre hier wohl
    bessere wahl gewesen, da hast du recht...

    Nein, die bessere Wahl wäre gewesen, den Test einfach nicht zu machen.

    gut,.. wenn es dem aufrufer obligt diesen test zu machen um eine access
    exception zu umgehen...

    cooky451 schrieb:

    zeusosc schrieb:

    * this-> bleibt definitiv !!! es ist ein unterschied ob ich eine
    Methode der Instanz aufrufe oder eine gleichnamige Funktion aus
    dem gleichen Namensraum, geschweige denn Member.
    Da der Compiler das so oder so die addy's der Member aus der
    Referenzierung des this holt (in asm schön sichtbar), dann
    kann ich es auch gleich richtig machen.

    Was heißt hier "richtig", es macht halt keinen Unterschied, aber das this wegzulassen ist übersichtlicher.

    zeusosc schrieb:

    Ausserdem ist dann
    IMMER klar, WANN ich eine Methode oder Member innerhalb einer
    Methode aufrufe,...
    (Macht sich besonders bemerkbar wenn intellisense spinnt)

    Das ist auch so klar. Mehr noch, this-> impliziert, dass diese explizite Schreibweise nötig ist, weil sonst etwas Anderes gemeint wäre. Daher sollte man es meiden, wenn dem nicht so ist.

    Also letzendlich wäre das also nur eine Stilfrage? Du sagst: Nutze wenn muss,
    lasse wenn kann wegen leserlichkeit...

    cooky451 schrieb:

    zeusosc schrieb:

    * Einrückung: hä? wie was? wo?
    Es gibt ja mal wohl mehrere Varianten von einrückungen...

    Das hat nichts mehr mit Stil zu tun, das ist einfach falsch bzw. teilweise gar nicht eingerückt.

    sry, aber pro tiefe ein tab,.. für mich ist das eine entsprechende einrückung..

    cooky451 schrieb:

    zeusosc schrieb:

    * ";" ?? Meines wissens hat nach jeder abgeschlossenen Anweisung ein ";"
    zu folgen. Auch wenn manchen Compilern das wurscht ist....

    Nein, keinem Compiler ist das egal. Aber leere ; sind jedem Compiler egal, deswegen kompiliert der Code überhaupt. Auf einen Scope muss kein ; folgen. (Und sollte dadurch auch nicht.)

    Da kann ich Dir gerade nicht folgen... Hast Du einen entsprechenden Link?

    cooky451 schrieb:

    zeusosc schrieb:

    nicht viele hauerdrinn,...

    Doch, das malloc Gefrickel ist eines der übelsten Sachen die ich seit Langem gesehen habe. Und wenn der Index nicht mehr gültig ist gibt man einfach einen *new T() zurück der nie mehr freigegeben wird? 😮

    Da muss ich Dir wiedersprechen:

    {
    T& foo(void)
    {
       return *(new T());
    };
    
    void blub(void)
    {
        T t;
        t=foo();
    }
    

    Was passiert denn am ende der fkt blub? Det Dtor wird aufgerufen und das Objekt
    zerstört,...
    Das malloc "gefrickel" ist, wie oben erwähnt, die folge das ich kaum ein new benutze,..

    cooky451 schrieb:

    zeusosc schrieb:

    gleich n template mit variabler dim anzahl
    basteln. Er nutzt ja mehrere 1d 2d und 3d arrays.,...

    Das funktioniert nicht. Die Dimensionen sind erst zur Laufzeit bekannt, wären sie zur Compilezeit bekannt, könnte man auch einen std::vector<std::array<...>> nehmen. Daher fällt jegliches Templategezauber weg.

    [/quote]
    Die Dimensionen sind maximal 3-> Schicht, Neuron, gewichte,.. Dynamisch sind
    die Anzahl der Schichten, Neuronen und entsprechend Gewichte,...

    Fazit: ich werde mal n geschwindigkeitsvergleich machen, Vector vs meine Implementation..

    grüße


Anmelden zum Antworten