Hallo,
ich will (in C++) eine Matrixklasse programmieren, meine erster Entwurf
funktioniert soweit auch, aber wie könnte man den Code noch
vereinfachen?
Hat keiner Vorschläge? Z.B. in der Konstruktordefinition scheint mir der
Code etwas umständlich, aber ich kann mir nicht vorstellen wie ich ihn
einfacher mache soll. Oder in der Funktion print(), welche Konsequenz
hätte es wenn ich vec1 und vec2 nicht als Referenz definieren würde?
Knechtus schrieb:> SquareMatrix::SquareMatrix(int dim_, double initValue_)> : dim{dim_}, initValue{initValue_}> {> vector< vector<double> > vec(dim, vector<double>(dim, initValue));> v = vec; // Geht das nicht eleganter?
Du könntest dir definieren:
1
typedefvector<vector<double>>vec_type;
2
vec_typev;
Und in der Initialisierungsliste:
1
v(dim,vec_type::value_type(dim,initValue))
Dann hast du deinen Vektor-Typ auch zentral an einer Stelle. Das hilft
auch, wenn du den Typ mal ändern oder gar ein Template aus deiner Klasse
machen willst.
Knechtus schrieb:> Hat keiner Vorschläge?
Du nutzt weder dim, noch initValue und es ist auch recht
unwahrscheinlich, dass diese Werte später noch einmal brauchst. -> weg
damit.
Knechtus schrieb:> ich will (in C++) eine Matrixklasse programmieren, meine erster Entwurf> funktioniert soweit auch, aber wie könnte man den Code noch> vereinfachen?
so:
#include <Eigen/Dense>
class SquareMatrix: public Eigen::MatrixXd{
};
int main()
{
SquareMatrix m(3,3);
std::cout << m << std::endl;
}
Knechtus schrieb:> SquareMatrix mat{3, 0.125};
Was ist das? Kein C, oder???
Es gibt genug Matrixlibraries für C und C++. "Eigen" ist nur eine davon.
Wenn man nicht programmieren kann, sollte man fertige Libraries
benutzen.
Knechtus schrieb:> vector< vector<double> > v; // inner vector represents rows, outer> represents columns
Unnötig umständlich. Die Matrix hat ja keine ungleich langen Spalten. So
hast du eine Menge Verwaltungs-Overhead und schlechtes Cache-Verhalten.
Besser wäre:
Knechtus schrieb:> using namespace std;https://www.geeksforgeeks.org/using-namespace-std-considered-bad-practice/
Verwende "std::size_t" statt "int" für die Größenangabe. "int" ist ggf.
zu klein für die jeweilige Plattform.
Knechtus schrieb:> // Was passiert wenn ich bei auto das & weglasse?
Änderungen an den Variablen vec1, vec2 würden nicht in den Vektor
übernommen, und du würdest viel Rechenzeit damit verschwenden die
Vektoren nach "vec1" zu kopieren.
Carl Friedrich schrieb:> Was ist das? Kein C, oder???
Offensichtlich ist das alles C++, und auch korrekt.
Carl Friedrich schrieb:> Wenn man nicht programmieren kann, sollte man fertige Libraries> benutzen.
So lernt man es aber nie. Eigene Matrix-Klassen o.ä. zu implementieren
ist eine gute Übung.
Carl Friedrich schrieb:> Knechtus schrieb:>> SquareMatrix mat{3, 0.125};>> Was ist das? Kein C, oder???
Es nennt sich C++.
Dr. Sommer schrieb:> Verwende "std::size_t" statt "int" für die Größenangabe. "int" ist ggf.> zu klein für die jeweilige Plattform.
Naja, das absolute Minimum für den Wertebereich von int wären 32k. Eine
einzelne Matrix mit 32k*32k double-Elementen bräuchte mindestens 8 GB
RAM. Mir wäre keine Plattform mit 16-Bit-int bekannt, die so viel RAM
überhaupt zu Handhaben in der Lage wäre, erst recht nicht am Stück in
einem einzelnen Array.
Rolf M. schrieb:> Mir wäre keine Plattform mit 16-Bit-int bekannt, die so viel RAM> überhaupt zu Handhaben in der Lage wäre, erst recht nicht am Stück in> einem einzelnen Array.
Kann sein dass es in diesem Fall mit "int" geht, inkl. Konversions
Warnungen wenn man int an Funktionen von Vektor übergibt, welche size_t
verwenden, sowie den ganzen assert(Index >= 0). Vor der Multiplikation
beim Zugriff muss man auch umwandeln, sonst gibts Overflow. Dann muss
man sich aber für andere Selbst Implementationen von Containern auf
size_t umgewöhnen. Oder es einfach von Anfang an richtig machen. Für
alles und jedes "int" zu verwenden ist eine Java Unsitte.
Allenfalls waere das Ziel noch zu definieren. Von/Fuer Ingenieur, oder
Mathematiker/Physiker. Die haben sehr verschiedene Ideen dazu.
Eine Initialisierung wird nur Null als Wert benoetigen. Die ungleich
Null Zellen muss man dann eben in einem 2.Schritt setzen.
Als Ingenieur ist man meist mit 2er, 3er Matritzen zufrieden und rechnet
gleich los damit.
Waehrend bei Mathematkern und Physikern die Anzahl Zeilen und Spalten
viel groesser sein kann. Die schauen auch auf die Konditionierung der
Matrix, und haben spezielle Vorstellungen was die Eigenschaften sein
sollen. Zum Beispiel hann man mit Multidiagonalmatritzen besser rechnen
wenn man die auch als solche handhabt. Das kann dann gleich einen Faktor
1000 in der Geschwindigkeit ausmachen.
Da war mal Einer, der hat sich fuer Matlab entschieden, weil Matlab eine
Matritzenrechnung um den Faktor 100 schneller wie ein C Compiler gemacht
hat... Tja. So geht das.
Die spinnen die Roemer schrieb:> Da war mal Einer, der hat sich fuer Matlab entschieden, weil Matlab eine> Matritzenrechnung um den Faktor 100 schneller wie ein C Compiler gemacht> hat... Tja. So geht das.
Ein Compiler ist ein Compiler. Wenn man ein schnarchlangsames
Bubble-Sort implementiert wird kein Compiler dies durch ein Quick-Sort
ersetzen.
Das sollte eigentlich jedem klar sein. Bevor man anfängt, selbst
runzuhacken, schaut man sich erst mal das Problem an und welche Umgebung
/ Bibliothek(en) etc. damit adäquat umgehen können.
Knechtus schrieb:> eine Matrixklasse programmieren
Das kann ich nicht zulassen. Neo und Trinity sind bereits informiert und
werden dich vernichten!
Wir haben die Fehler in deiner Matrix bereits indentifizert!
Jetzt mal im Ernst:
Kein normaler Mensch löst Matritzen mit Standardverfahren. Wie andere
Schreiber schon erwähnt haben, sucht man erst einmal nach Identitäten,
Spiegelungen und Nullen, um sich die Rechnung zu vereinfachen.
Die spinnen die Roemer schrieb:> Da war mal Einer, der hat sich fuer Matlab entschieden, weil Matlab eine> Matritzenrechnung um den Faktor 100 schneller wie ein C Compiler gemacht> hat... Tja. So geht das.
Hmm. Um ehrlich zu sein: das ist sehr sehr schwer vorstellbar :-)
Muss dann wohl in Assembler programmiert sein. Aber auch dann dürften
nicht soviele Welten dazwischen liegen. Also, irgendwas passt da nicht
:-)
Jiri D. schrieb:> Wieso das Rad neu erfinden?
Um zu verstehen, was abläuft?
Und um der zu erwartenden Folgefrage vorzubeugen:
Es hilft bei der Fehlersuche ungemein, wenn man
nicht ziellos herumraten muss, sondern eine
gewisse Idee davon hat, was passiert.
Mutluit M. schrieb:> Hmm. Um ehrlich zu sein: das ist sehr sehr schwer vorstellbar :-)> Muss dann wohl in Assembler programmiert sein.
Ich glaube er meint, daß der Compiler so lange gebraucht hat, es zu
übersetzen und MATLAB schneller war. Das kann gut sein.
Aber im generellen ist MATLAB eine lahme Kiste.
Schlüsselmacher schrieb:> Wie andere Schreiber schon erwähnt haben, sucht man erst einmal> nach Identitäten, Spiegelungen und Nullen
Das müsste MATLAB aber schon machen, glaube ich.
Egon D. schrieb:> Jiri D. schrieb:>>> Wieso das Rad neu erfinden?>> Um zu verstehen, was abläuft?
Das kann man auch (besser), indem man sich den Code von anderen
anschaut. Das kann man (ich zumindest) gemeinhin bei Freier/Open Source
Software machen. Von MATLAB kann man in der Hinsicht ja nichts lernen.
Dann kann man z.B. herausfinden, dass es column major und row major
Implementierungen gibt, und man das bei BLAS sogar umschalten kann.
Physiker & Mathematiker denken an schmale Matritzen mit nur 6
Diagonalelementen wie sie zB bei finiten elementen vorkommen, waehrend
Ingenieure Matrizen mit 'for x=, for y=' anpacken. Und dann hat man eben
schon einen Faktor 1000 oder so verloren.
Mutluit M. schrieb:> Die spinnen die Roemer schrieb:>> Da war mal Einer, der hat sich fuer Matlab entschieden, weil Matlab eine>> Matritzenrechnung um den Faktor 100 schneller wie ein C Compiler gemacht>> hat... Tja. So geht das.>> Hmm. Um ehrlich zu sein: das ist sehr sehr schwer vorstellbar :-)
Das habe ich auch mal gedacht, als ich Werbung für Matlab mit 'Schneller
als C' gesehen habe. Aber bei Matrizenrechnung, wofür Matlab gemacht
ist, kann ich mir schon vorstellen, dass es schneller ist, als ein
durchschnittlicher Programmierer das hinkriegen würde. Ich gehe davon
aus, dass in Matlab hohes mathematisches Wissen in der Optimierung der
Matrizenrechnung steckt und daher der Vorteil im Vergleich zu
durchschnittlichem C kommt.
Megatroll schrieb:> Der Vorteil liegt in den Algorithmen, nicht im Compiler.
Ja, denn höchstwahrscheinlich sind gerade die bei Matlab auch in C
implementiert. Damit kann es nicht "schneller als C" sein, sondern wie
"Dussel" schreibt:
Dussel schrieb:> dass es schneller ist, als ein durchschnittlicher Programmierer das> hinkriegen würde.
Rolf M. schrieb:> Megatroll schrieb:>> Der Vorteil liegt in den Algorithmen, nicht im Compiler.>> Ja, denn höchstwahrscheinlich sind gerade die bei Matlab auch in C> implementiert. Damit kann es nicht "schneller als C" sein, sondern wie> "Dussel" schreibt:>> Dussel schrieb:>> dass es schneller ist, als ein durchschnittlicher Programmierer das>> hinkriegen würde.
Jein. BLAS ist oft in Fortran geschrieben. Auch GNU Octave hat Teile in
Fortran implementiert.
https://hg.savannah.gnu.org/hgweb/octave/file/0beeb6817376/liboctave/external/blas-xtra/ddot3.f
Eine Implementierung für eine Matrix-Vektor-Multiplikation wird
irgendwann an einem Optimum angekommen sein. Eine allgemeine
(nicht-sparse) Matrix-Vektor-Mul muss eine Mindestmenge
Operationen/Speicherzugriffe ausführen. Nachdem alle bekannteren
Programme das eine oder andere BLAS verwenden, werden sich die da nicht
groß unterscheiden.
Der limitierende Faktor wird halt einfach der verwendete Prozessor sein:
ALU, Caches, Speicherbandbreite. Auch SIMD hilft hier nur begrenzt.
Zaubern kann weder ein Algorithmus, noch ein Compiler.
Und auch Matlab wird bei den üblichen Matrizen nicht erst nachprüfen,
welcher der 5 Algorithmen am effizientesten wäre, denn dafür müsste man
die Matrix erst lesen, analysieren usw. In der Zeit hätte man das
Ergebnis mit einem generischen Standardalgorithmus schon längst.
Wer also was komplexeres mit Matrizen und dergleichen machen will,
sollte sich m.M.n. einfach BLAS bzw. Libraries, die es verwenden,
antun/-sehen.
Wer nur eine 3x3 Matrix multiplizieren muss, schreibt sich das schnell
selber und man wird keinen messbaren Unterschied zu optimierten Libs
feststellen können.
Schlüsselmacher schrieb:> Knechtus schrieb:>> eine Matrixklasse programmieren> Das kann ich nicht zulassen. Neo und Trinity sind bereits informiert und> werden dich vernichten!>> Wir haben die Fehler in deiner Matrix bereits identifizert!
1. Neo und Trinity können heute nichts mehr ausrichten, denn sie könnten
nicht mehr zurück, weil es heute - 20 Jahre nach dem Filmstart - keine
analogen Telefone mehr gibt. Es gibt zwar öffentliche Zellen mit alten
Hörern, aber die laufen auch mit IP-Telefonie und da hocken die Wächter
dazwischen. Die heißen zwar nicht Smith sondern, Huawei, aber sind
ähnlich lauschfreudig! Die damalige Matrix wurde auch inzwischen durch
Skynet ersetzt, welche sich in Form von Google-Apps auf allen modernen
Telefonen verbreitet hat und nicht mehr zu stoppen ist. Damit ist jeder
Angriff extrem schwierig und Arni ist viel zu alt um nochmal "I'll be
back" zu sagen.
2. Der Typ, der in der deutschen Übersetzung Schlüsselmacher genannt
wurde, ist im Original der "keymaker". Dieser hat in der Zeitachse
einige frames aufgeschnitten sogenannte "keys" eingesetzt, um den
Fortlauf des programmierten Geschehens auf seinen ->Bahnhof umzulenken.
Diese "keys" sind aber die aus Computeranimationen bekannte
Schlüsselbilder. Es handelt sich also um einen Bildereinsetzer, der mit
Schlüsseln für Schlösser nichts zu tun hat. Könnte er echte Schlüssel
machen, dann müsste er nicht im Untergrund herum tüfteln und Leute
erpressen, sondern könnte wie die beiden weißhaarigen Killer beliebig in
der Matrix umher hüpfen. Du bist das Produkt eines Übersetzungsfehlers.
> Kein normaler Mensch löst Matrizen mit Standardverfahren. Wie andere> Schreiber schon erwähnt haben, sucht man erst einmal nach Identitäten,> Spiegelungen und Nullen, um sich die Rechnung zu vereinfachen.
Tja, dann bin ich wohl nicht ganz normal, denn ich löse Matrizen gerne
mit Standardfahren. Bis zu Matrizengrößen von 64x64 kann man die in
zweidimensionalen FPGA-pipelines immer in geringeren Zeiträumen lösen,
als irgendwelche Suchen nach vereinzelt auftretenden
Vereinfachungsmöglichkeiten benötigen würden und 1D-pipelines, schiebt
man bis zur Tiefe Wurzel(n) also z.B. 8 alle entstehenden adjunkten
Matrizen nacheinander durch. Sind dann 64x8 Takte. Auch nicht unbedingt
ein Ziel von weitreichenden Optimierungsansätzen. In Grafikkarten geht
das linear bis z.B. 32x32 und kriegt die Lösung in log2(32) Takten
serviert.
Nur die armen C- und MATLAB-Würstchen mit ihren lahmen Intelkisten
müssen sich Gedanken machen, wie sie schnell werden können :-)
Rolf M. schrieb:> Ja, denn höchstwahrscheinlich sind gerade die bei Matlab auch in C> implementiert. Damit kann es nicht "schneller als C" sein, sondern wie> "Dussel" schreibt:
Höchst wahrscheinlich sind die aber allgemein und dynamisch formuliert
und nicht auf bestimmte Befüllungen hin optimiert oder optimierbar, weil
sie sonst unflexibel werden, während ein Compiler beim Übersetzen einer
konkreten Aufgabe Nullen und Identitäten erkennt (oder zumindest
erkennen kann) und diese optimiert.
Generell darf man nicht aus den Augen verlieren, woher der Begriff
MAT-LAB kommt, nämlich von dem Abarbeiten MAT-rix-artiger Strukturen.
Daher heißt es auch MAT-LAB und nicht etwa MATH-LAB, wie jeder dritte
Projektanbieter schreibt, weil er es mit MathCad oder Mat-CAD
verwechselt.
Jürgen S. schrieb:> Tja, dann bin ich wohl nicht ganz normal, denn ich löse> Matrizen gerne mit Standardfahren.
Solange die Konditionszahl das hergibt, ist da ja auch
nichts Schlechtes dran. Nur manchmal gibt sie es eben
nicht her.
Jürgen S. schrieb:> Höchst wahrscheinlich sind die aber allgemein und> dynamisch formuliert und nicht auf bestimmte> Befüllungen hin optimiert oder optimierbar, weil> sie sonst unflexibel werden,
Das hätte reichlich wenig Sinn. Drei geschachtelte
Schleifen kann jeder Anfänger hinschreiben.
Auf http://www.netlib.org/blas/ findet man, dass
natürlich alle Spezialfälle einzeln ausprogrammiert
sind: Vollbesetzte Matrizen, Matrizen mit Bandstruktur,
symmetrische, symmetrische mit Bandstruktur, Dreiecks-
matrizen etc.p.p.
Dagegen kann eine naive Implementierung nach Lehrbuch
sicher nicht anstinken.
Jiri D. schrieb:> Und auch Matlab wird bei den üblichen Matrizen nicht erst nachprüfen,> welcher der 5 Algorithmen am effizientesten wäre, denn dafür müsste man> die Matrix erst lesen, analysieren usw. In der Zeit hätte man das> Ergebnis mit einem generischen Standardalgorithmus schon längst.
Kann man das nicht bei der Erzeugung der Matrix gleich mit machen und
diese Information mit abspeichern? Bei größeren Matrizen wird sich das
bestimmt lohnen.
Jürgen S. schrieb:> und Arni ist viel zu alt um nochmal "I'll be back" zu sagen.
Wohl nicht, wenn man sich den neuesten Trailer anschaut.
Egon D. schrieb:> natürlich alle Spezialfälle einzeln ausprogrammiert
Das sind aber nur die strukturell analysierbaren Spezialfälle, die mit
irgendwelchen, nicht vorbestimmten Daten arbeiten und arbeiten können.
Ich denke da an anwendungsspezifischen Optimierungen, wo die Struktur
und Inhalt der Daten schon bekannt ist und die Optimierung durch die
Programmierung vorweg genommen wird. Eine Rücksicht darauf kann nur
nehmen, wer seine Eingangsdaten kennt und das zur Compile- und nicht nur
zur Laufzeit! Dann müsste nämlich geprüft werden.
Das ist z.B. bei statisch aufgezogenen Matrizen in FPGAs so herrlich,
wenn alles, was Indentität ist und sich irgendwie anders bilden oder
vereinfachen lässt, zusammenbröselt.
>Nur die armen C- und MATLAB-Würstchen mit ihren lahmen Intelkisten
müssen sich Gedanken machen, wie sie schnell werden können :-)
Nun, diese 64 Quadrat Matrizen sind eine moegliche Anwendung. Schoen.
Bei finiten elementen rechnet man zB oft mit Quadern. Das waeren dann 6
seitenflaechen, die mit den Nachbarn interagieren. Ergibt eine
6-diagonale Matrix. Nun hat man zb 500k solcher Wuerfel. Macht dann eine
500k Quadrat Matrix mit nur 6 diagonalen elementen.
So eine Anwendung hatte ich sogar schon mal. Wärmeberechnung in einem
Quader in Echtzeit. Die Dimensionen können sogar noch steigen und die
Matrizen verkomplizieren, wenn man Terme ansieht, die in den Gleichungen
identisch sind und ineinander gelöst werden können (und damit sollten).
(Es waren 4 Gleichungen pro Würfelelement parallel zu lösen).
Man kann solche mehrdimensionalen Strukturen sehr schön generisch
aufziehen und sich den Struktur-Code erzeugen lassen.
Auch für meinen Audio-DSP habe ich ein solches Matrixsystem. Geht über
x*y Zellen über n FPGAs. In jedem ist ein 3D-Verarbeiter:
http://www.96khz.org/htm/scalableaudiodsp.htm
Jiri D. schrieb:> Matlab wird auch eine Form von BLAS verwenden...
Jein. Jedenfalls nicht direkt. Für normale Matrizen, die in den
Hauptspeicher passen, wird LaPack/ScaLaPack eingesetzt.
Und ja: Große Matrix-Operationen gehen in Matlab irre schnell. So
schnell, daß eine optimierte Implementierung in FORTRAN nur noch
marginale Geschwindigkeitsvorteile bringt.