Große Arrays



  • Du musst den Header <array> oder, falls das nicht klappt, <tr1/array> einbinden. Außerdem musst du gegebenenfalls mit C++11-Unterstützung kompilieren (bei g++ mit --std=c++0x).



  • Ich glaube mein Compiler unterstützt kein C++11. Gibt es eine elegante Lösung, die ohne array auskommt? Das wäre mir am Liebsten, da es noch 2 andere Rechner gibt, auf denen mein Programm laufen soll. Könnte gut sein, dass die auch Probleme mit haben.



  • Ramanujan schrieb:

    Ich glaube mein Compiler unterstützt kein C++11.

    Wie wäre es, wenn du noch dazu schreibst welchen Compiler du nutzt?

    Im Übrigen hat die (nicht) Unterstützung von std::array nichts mit der Lauffähigkeit des Programms zu tun. Das Kompilat weiß nichts mehr von std::array.



  • Ramanujan schrieb:

    ..\src\matrix.cpp:332: error: `array' is not a member of `std'
    ..\src\matrix.cpp:332: error: expected primary-expression before "double"
    ..\src\matrix.cpp:332: error: expected `;' before "double"
    
    ..\src\matrix.cpp:333: error: `array' is not a member of `std'
    ..\src\matrix.cpp:333: error: `array' is not a member of `std'
    ..\src\matrix.cpp:333: error: `Matrix<T>::dim2_' cannot appear in a constant-expression
    ..\src\matrix.cpp:333: error: `Matrix<T>::dim1_' cannot appear in a constant-expression
    ..\src\matrix.cpp:333: error: a function call cannot appear in a constant-expression
    ..\src\matrix.cpp:366: error: template argument 1 is invalid
    ..\src\matrix.cpp:366: error: template argument 2 is invalid
    ..\src\matrix.cpp:366: error: expected unqualified-id before '}' token
    

    Die Fehlermeldungen sehen mir nach dem GCC aus. Die aktuellen Versionen dieses Compiler unterstützten auch std::array. Dazu ist der entsprechende Header einzubinden. Aber std::array ist hier nicht das, was Du haben willst, sondern std::vector!

    Ramanujan schrieb:

    Muss ich dim1_ bzw. dim2_ zu const casten oder wie löse ich das Problem?

    Die Werte von dim1_ und dim2_ sind bei Dir zur Compile-Zeit unbekannt. Aber das ist eine notwendige Bedingung für eine "constant expression". Da hilft auch kein cast.

    Siehe hier.

    kk



  • @krümelkacker Hast du den Anfang des Threads gelesen?



  • cooky451 schrieb:

    @krümelkacker Hast du den Anfang des Threads gelesen?

    Ja. Ich habe Deinem ersten Kommentar auch voll zugestimmt. Den Verweis auf die Matrix-Klasse habe ich gesetzt, weil ich matrix.cpp und auch so Dinger wie Matrix<T>::dim2_ und Matrix<T>::dim1_ in den Fehlermeldungen gesehen habe. 😃

    Das sieht mir hier nämlich wie ein Fall von "ich sag euch nicht, was ich machen will, sondern nur wie und wo ich dabei Probleme hatte" aus.



  • Ich benutze hier MinGW 5.1.4
    Im Uni-Poolrechner müsste das die gleiche Version sein.
    Auf dem Ubuntu-Server läuft gcc 4.4.3

    Auf letztere hab ich keinen Einfluss. Kann ich per Parameter testen, ob c++11 unterstützt wird?

    Wenn ich (wie ipsec sagte) "--std=c++0x" als Parameter angebe, kommt folgende Ausgabe:

    g++ -O0 -g3 -Wall -c -fmessage-length=0 --std=c++0x -o src\Useful.o ..\src\Useful.cpp
    cc1plus.exe: error: unrecognized command line option "-std=c++0x"
    Build error occurred, build is stopped
    

    Edit:
    Auf dem Server macht der Parameter "--std=c++0x" keine Probleme.



  • GCC 4.4 unterstützt C++0x, das ist ab 4.3 in Teilen dabei.

    Hast du überhaupt "#include <array>" drin? Dann lass das --std=c++0x weg und poste die Fehlermeldung.



  • g++ -O0 -g3 -Wall -c -fmessage-length=0 -o src\matrix.o ..\src\matrix.cpp
    ..\src\matrix.cpp:20:17: array: No such file or directory

    bzw. wenn ich "#include <tr1/array>" schreibe:

    g++ -O0 -g3 -Wall -c -fmessage-length=0 -o src\matrix.o ..\src\matrix.cpp
    ..\src\matrix.cpp:20:21: tr1/array: No such file or directory



  • Gib mal in die MinGW Konsole ein:
    mingw-get install g++



  • C:\MinGW\bin>mingw-get install g++
    install: gcc-c++-4.6.1-2-mingw32-bin.tar.lzma
    installing gcc-c++-4.6.1-2-mingw32-bin.tar.lzma
    mingw-get: *** ERROR *** package gcc-c++-4.6.1-2-mingw32-bin.tar.lzma is already
    installed

    Edit:
    Eine Frage noch zu array:
    muss die Größe von array (also der 2. template-parameter) bereits zur Compilezeit feststehen oder kann das auch eine beliebige Variable sein. Wenn es nämlich ersteres ist, ist array für mich ungeeignet.

    Edit^2:
    ich poste hier mal ein kurzes konkretes Stück Code. Vllt könnte mir das jemand mal mit vector (etc.) formulieren:

    Matrix<T> Matrix<T>::multiplyNaiveUnchecked(const Matrix<T>* matrix) const {
    	// [...]
    
    	T** datA = new T*[dim1_];
    	for (int i = 0; i < dim1_; i++) {
    		datA[i] = new T[dim2_];
    		for (int j = 0; j < dim2_; j++)
    			datA[i][j] = getEntry(i,j);
    	}
    
    	// [...]
    
    	for (int i = 0; i < dim1_; i++) delete[] datA[i];
    	delete[] datA;
    
    	// [...]
    }
    


  • Ramanujan schrieb:

    C:\MinGW\bin>mingw-get install g++
    install: gcc-c++-4.6.1-2-mingw32-bin.tar.lzma
    installing gcc-c++-4.6.1-2-mingw32-bin.tar.lzma
    mingw-get: *** ERROR *** package gcc-c++-4.6.1-2-mingw32-bin.tar.lzma is already
    installed

    Eine Frage noch zu array:
    muss die Größe von array (also der 2. template-parameter) bereits zur Compilezeit feststehen oder kann das auch eine beliebige Variable sein. Wenn es nämlich ersteres ist, ist array für mich ungeeignet.

    Ja, dann musst du std::vector nehmen.
    std::array ist nämlich der Ersatz für ruhe Arrays.

    Trotzdem finde ich es merkwürdig dass es bei dir nicht klappt, aber keine Ahnung was nicht stimmt.



  • @Ramanujan Mit GCC 4.6.1 sollte -std=c++0x kein Problem sein. Ja, bei std::array muss die Größe eine Compiletime-Konstante sein. (Wie auch bei normalen Arrays, die du ja am Anfang präsentiert hast..)
    Für eine Matrixklasse mit dynamischer Größe siehe den Link von krümelkacker.



  • cooky451 schrieb:

    @Ramanujan Mit GCC 4.6.1 sollte -std=c++0x kein Problem sein. Ja, bei std::array muss die Größe eine Compiletime-Konstante sein. (Wie auch bei normalen Arrays, die du ja am Anfang präsentiert hast..)

    Also ich konnte normale Arrays auch mit variabler Größe erstellen. Am Anfang dieses Threads hab ich was mit konstanten werten präsentiert, da jene Kombination (100000*4) Probleme gemacht hatte.



  • Das sind VLAs, und C++ kennt keine VLAs. Die gibt's nur in C. (std >= C99)



  • hm, jedenfalls hat mein Compiler nicht gemeckert.

    Das kam vllt unter, weil der Edit nach dem nächsten Post kam:

    Edit^2:
    ich poste hier mal ein kurzes konkretes Stück Code. Vllt könnte mir das jemand mal mit vector (etc.) formulieren:

    Matrix<T> Matrix<T>::multiplyNaiveUnchecked(const Matrix<T>* matrix) const {
    	// [...]
    
    	T** datA = new T*[dim1_];
    	for (int i = 0; i < dim1_; i++) {
    		datA[i] = new T[dim2_];
    		for (int j = 0; j < dim2_; j++)
    			datA[i][j] = getEntry(i,j);
    	}
    
    	// [...]
    
    	for (int i = 0; i < dim1_; i++) delete[] datA[i];
    	delete[] datA;
    
    	// [...]
    }
    


  • Nein, das ging nicht unter. Aber das hier ignorierst du offenbar konsequent:

    cooky451 schrieb:

    Für eine Matrixklasse mit dynamischer Größe siehe den Link von krümelkacker.

    Und dein Compiler meckert vermutlich nicht, weil du nicht std=c++0x nutzt. 🤡



  • Ramanujan schrieb:

    muss die Größe von array (also der 2. template-parameter) bereits zur Compilezeit feststehen oder kann das auch eine beliebige Variable sein. Wenn es nämlich ersteres ist, ist array für mich ungeeignet.

    Sagte ich doch.

    Ramanujan schrieb:

    Edit^2:
    ich poste hier mal ein kurzes konkretes Stück Code. Vllt könnte mir das jemand mal mit vector (etc.) formulieren:

    Matrix<T> Matrix<T>::multiplyNaiveUnchecked(const Matrix<T>* matrix) const {
    	// [...]
    
    	T** datA = new T*[dim1_];
    	for (int i = 0; i < dim1_; i++) {
    		datA[i] = new T[dim2_];
    		for (int j = 0; j < dim2_; j++)
    			datA[i][j] = getEntry(i,j);
    	}
    
    	// [...]
    
    	for (int i = 0; i < dim1_; i++) delete[] datA[i];
    	delete[] datA;
    
    	// [...]
    }
    

    siehe Link von mir ... und dann so ungefähr

    matrix operator*(matrix const& a, matrix const& b)
    {
       const int z = a.zeilen();
       const int s = b.spalten();
       const int k = std::min(a.spalten(),b.zeilen()); // oder Ungleichheit abfangen
    
       matrix c (z,s);
       for (int i=0; i<z; ++i) {
         for (int j=0; j<s; ++j) {
           double summe = 0;
           for (int t=0; t<k; ++t) {
             summe += a(i,t)*b(t,j);
           }
           c(i,j) = summe;
         }
       }
       return c;
    }
    

    (ungetestet)



  • Ja, den Link hab ich mir angeguckt, dort ging es um eine Matrix-Klasse, dessen Datenfeld als eindimensionaler vector realisiert wurde. Ich könnte nun auch in meinem Code das temporäre Datenfeld als 1D-vector implementieren, wobei ich die Index-Rumrechnerei jetzt nicht so schön finde. Ich muss zugeben das Datenfeld meiner Matrix-Klasse als T**-Array realisiert zu haben. Ich möchte das jetzt allerdings nicht mehr ändern, da ich sonst sehr viel Code umschreiben müsste. Problematisch ist vor allem, dass sich zwei Matrizen ein Array teilen können, um Zeit bei manchen Operationen zu sparen. Dazu hab ich ein Attribut angelegt, das angibt, wem das Array nun "gehört". Dass sowas fehleranfällig ist, gebe ich zu. Sicherlich kann man das auch mit vector realisieren, nur das würde mir zu viel Arbeit bedeuten. Und direkt nach dem Umstellen hätte ich 100%-ig deutlich mehr Fehler als vorher. In der konkreten Methode werden zwei Matrizen (auf die naive Art und Weise) multipliziert. Da Matrizen implizit (!) transponiert sein können, schreibe ich die Daten in ein temporäres Array, um nicht immer wieder getEntry() aufrufen zu müssen. getEntry() überprüft, ob der bool-Wert transponiert_ gesetzt ist und gibt dann entweder entries_[i][j] oder entries_[j][i] zurück. Nun möchte ich in der innersten Schleife möglichst wenig Code haben, von daher schreibe ich mir die Daten so in ein Array/vector, dass sie hintereinander im Speicher liegen (d.h. wenn ich A*B berechne, so brauche ich die Daten von A nicht-transponiert und die Daten von B transponiert). Ok, das ist natürlich auch wunderbar mit einem temporären 1D-vector möglich. Bei kleinem k (also wenn A = (i x k) und B = (k x j)) ist das natürlich ein ziemlicher Overhead, aber das ist eine andere Geschichte.

    Ich wollte jetzt eigentlich nur kurz schreiben, was meine Matrizen können bzw. machen und was hinter dem temporären Array steckt.


Anmelden zum Antworten