2016-08-08 23 views
4

Ich verwende Eigen für ein Projekt, an dem ich arbeite, wo die Laufzeitleistung absolut entscheidend ist (muss Echtzeit-Einschränkungen erfüllen).Eigen: Effiziente Kronecker Produkt

Bisher gibt mir Eigen ziemlich gute Leistung. Ich muss jedoch ein Kronecker-Produkt bewerten. Ich verwende Eigens nicht unterstütztes KroneckerProduct-Modul, aber ich denke, dass es für meine Bedürfnisse suboptimal ist.

Die beiden Matrizen, mit denen ich das Kronecker-Produkt bearbeite, haben eine feste Größe (bekannt zur Kompilierzeit) und Struktur. Eine Matrix ist quadratisch und diagonal, nehmen wir an, dass es sich um eine Identitätsmatrix handelt. Die andere ist eine kleine, quadratische Matrix. Im Code wie folgt aus:

MatrixXf I = MatrixXf::Identity(4,4); 
MatrixXf X = MatrixXf::Random(8,8); 
MatrixXf P = kroneckerProduct(I,X); 

Da ich diagonal, ich vermute, dass wir das schneller machen können, da wir nur durch Skalarmultiplikationen bewerten, um 4-Matrix müssen alle Elemente (da viele Willen zu berechnen sei null).

Was ist der schnellste und effizienteste Weg, dies mit Eigen zu tun?

Antwort

5

In Eigen 3,3 beta gibt es jetzt (nicht unterstützte) Unterstützung für sparse Kronecker products. Wenn die Performance kritisch ist, würde ich noch nicht empfehlen, zu 3.3 Beta zu wechseln. Außerdem, wenn Sie wissen, dass I eine Diagonalmatrix ist, würden Sie wahrscheinlich bessere Leistung erhalten, Ihre eigenen zu schreiben. Plus, wenn die Größe zur Kompilierzeit bekannt ist (und nicht zu groß), können Sie MatrixXf durch Matrix4f ersetzen (feste Größe, wird auf dem Stapel zugewiesen, nicht der Heap). So rollen alle zusammen und Sie erhalten:

Matrix4f I4 = Matrix4f::Identity(); 
MatrixXf P2(I4.rows() * X.rows(), I4.cols() * X.cols()); 
P2.setZero(); 

for (int i = 0; i < I4.RowsAtCompileTime; i++) 
{ 
    P2.block(i*X.rows(), i*X.cols(), X.rows(), X.cols()) = I4(i, i) * X; 
} 
+0

Dies stellt tatsächlich einen angemessenen beschleunigen. Da wir auf die RowsAtCompileTime verweisen, gehe ich davon aus, dass der Compiler diese Schleife ausrollen kann? Welche Optionen sollte ich neben -march = nativ -mtune = nativ -O3 verwenden (ich benutze clang ++)? – NOP

+0

Die Verwendung von 'RowsAtCompileTime' sollte dem Compiler helfen, die Schleife zu entrollen. Die Beschleunigung ist vermutlich darauf zurückzuführen, dass nur die Blockdiagonale und nicht das gesamte äußere Produkt berechnet wird. Die entrollte Schleife trägt wahrscheinlich nicht zur Beschleunigung bei. Ich bin mir ziemlich sicher, dass 'I4.rows()' in diesem Fall die gleiche Konstante sein würde. Versuchen Sie auch, 'X' zu einer Matrix fester Größe zu machen. –

-2

Eine Option, die ich denken kann, ist eine Klasse, die MatrixXf erben wird und 3 Matrizen enthalten wird: I, X und P. P wird eine Struktur sein, die 2 Matrizen mit der Größe von P enthalten wird einer von ihnen wird der Inhalt der Matrix bool und der andere wird der gleiche wie das Produkt sein.

class MatrixXfExample : public MatrixXf { 

MatrixXf I,X; 
MatrixXfPair Data; 
} 

struct MatrixXfPair { 
MatrixXf Visited,Contant; 
} 

Der MatrixXfPair-Konstruktor initiiert Visited to false und lässt den Inhalt in Ruhe (Standard).

Der MatrixXfExample-Konstruktor wird I, X mit Kopierkonstruktor und Data mit Standard initiieren.

Jetzt, überschreiben Sie einfach() -Operator, um zu überprüfen, ob der Inhalt in Data.Visited falsch ist, und um die Mehrfachberechnung nur durchzuführen, wenn sie vorher nicht berechnet wurde. (Art der Umsetzung der Idee, den Code nur bei der Verwendung zu kompilieren).

+0

Ich bin nicht sicher, ich folge, was Sie sagen, aber das scheint nicht effizienter als nur naiv das Kronecker-Produkt Computing ... – NOP