Ich verwende Armadillo, um sehr intensive Matrixmultiplikationen mit Seitenlängen von , wobei bis zu 20 oder sogar mehr kann. Ich verwende Armadillo mit OpenBLAS für die Matrixmultiplikation, was in parallelen Kernen sehr gute Arbeit zu leisten scheint, außer dass ich ein Problem mit dem Formalismus der Multiplikation in Armadillo zur Superoptimierung der Leistung habe. n
Angenommen, ich habe eine Schleife in der folgenden Form:
arma::cx_mat stateMatrix, evolutionMatrix; //armadillo complex matrix type
for(double t = t0; t < t1; t += 1/sampleRate)
{
...
stateMatrix = evolutionMatrix*stateMatrix;
...
}
In grundlegendem C ++ stelle ich hier das Problem fest, dass C ++ ein neues Objekt cx_mat
zum Speichern zuweist evolutionMatrix*stateMatrix
und dann das neue Objekt stateMatrix
mit kopiert operator=()
. Das ist sehr, sehr ineffizient. Es ist bekannt, dass die Rückgabe komplexer Klassen großer Datentypen eine schlechte Idee ist, oder?
Ich sehe dies effizienter, wenn eine Funktion die Multiplikation in der folgenden Form ausführt:
void multiply(const cx_mat& mat1, const cx_mat& mat2, cx_mat& output)
{
... //multiplication of mat1 and mat2 and then store it in output
}
Auf diese Weise müssen keine großen Objekte mit einem Rückgabewert kopiert werden, und die Ausgabe muss nicht bei jeder Multiplikation neu zugewiesen werden.
Die Frage : Wie kann ich einen Kompromiss finden, bei dem ich Armadillo für die Multiplikation mit seiner schönen BLAS-Oberfläche verwenden kann, und dies effizient, ohne Matrixobjekte neu erstellen und bei jeder Operation kopieren zu müssen?
Ist das nicht ein Implementierungsproblem in Armadillo?
stateMatrix = evolutionMatrix*stateMatrix
kopiert der Ausdruck überhaupt nicht. Stattdessen nimmt Armadillo einen ausgefallenen Speicherzeigerwechsel vor. Es wird weiterhin neuer Speicher für das Ergebnis zugewiesen (daran führt kein Weg vorbei), aber anstatt zu kopieren, verwendet die stateMatrix
Matrix einfach den neuen Speicher und verwirft den alten Speicher.