Ich habe mich gefragt, ob es eine schnelle und effiziente Methode gibt, um die Anzahl der Nicht-Nullen im Voraus für die Sparse-Matrix-Multiplikationsoperation zu ermitteln, vorausgesetzt, beide Matrizen sind im CSC- oder CSR-Format.
Ich weiß, dass es ein smmp-Paket gibt, aber ich benötige etwas, das bereits in C oder C ++ implementiert ist.
Jede Hilfe wird geschätzt. Danke im Voraus.
matrix
sparse-matrix
Recker
quelle
quelle
Antworten:
Sie können das Matrix-Matrix-Produkt einfach simulieren, indem Sie das Produkt der beiden Sparsity-Muster bilden. Das heißt, Sie betrachten das Sparsity-Muster (das in separaten Arrays im CSR-Format gespeichert ist) als Matrix, die entweder eine Null oder eine Eins enthält jeder Eintrag. Für die Ausführung dieses simulierten Produkts müssen Sie nur das und bildenDie Operation mit diesen Nullen und Einsen ist also viel schneller als das eigentliche Matrix-Matrix-Produkt. Sie müssen lediglich die Zeilen und Spalten der beiden Matrizen durchgehen und sicherstellen, dass in a mindestens ein Eintrag vorhanden ist Zeile und die Spalte, mit der multipliziert wird, wobei beide Matrizen ungleich Null sind. Dies ist eine billige Operation - auf jeden Fall viel billiger als die eigentliche Gleitkommamultiplikation im eigentlichen Produkt, die nicht nur Gleitkomma-Arithmetik (teuer) erfordert, sondern auch das Einlesen der tatsächlichen Gleitkommazahlen aus dem Speicher ( noch teurer, aber das brauchen Sie nicht, wenn Sie das Sparsity-Muster multiplizieren, weil die Nicht-Null-Werte der Matrix separat im CSR gespeichert werden.
quelle
Ich habe tatsächlich den Originalcode in Matlab für A * B geschrieben, sowohl für A als auch für B sparsam. Die Vorbelegung des Platzes für das Ergebnis war in der Tat der interessante Teil. Wir haben beobachtet, worauf Godric hinweist: Die Anzahl der Nonzeros in AB zu kennen, ist genauso kostspielig wie AB zu berechnen.
Wir haben die erste Implementierung von spärlichem Matlab um 1990 durchgeführt, bevor das Edith-Cohen-Papier die erste praktische und schnelle Möglichkeit bot, die Größe von AB genau abzuschätzen. Wir haben einen Schätzer für eine minderwertige Größe zusammengestellt und, wenn uns während der Berechnung der Speicherplatz ausgeht, die Zuordnung verdoppelt und das teilweise berechnete Ergebnis kopiert.
Ich weiß nicht, was jetzt in Matlab ist.
Eine andere Möglichkeit wäre, AB spaltenweise zu berechnen. Jede Spalte kann vorübergehend in einem Akkumulator mit geringer Dichte gespeichert werden (eine Erklärung hierzu finden Sie im Matlab-Papier mit geringer Dichte). Der zugewiesene Speicherplatz enthält die genau bekannte Größe der Ergebnisspalte. Das Ergebnis wäre eine verstreute, komprimierte, dünn besetzte Spaltenform - jede Spalte in CSC, aber keine Intercolumn-Kontiguität - unter Verwendung von 2 Vektoren der Länge numcols (Spaltenanfang, Spaltenlänge) anstelle von einem als Metadaten. Es ist eine Speicherform, die einen Blick wert sein kann; Es hat eine weitere Stärke: Sie können eine Spalte vergrößern, ohne die gesamte Matrix neu zuzuweisen.
quelle
Diese Arbeit beschreibt einen Algorithmus zur Approximation der Größe einer Resultierenden aus dem Matrixprodukt zweier dünn besetzter Matrizen.
Das Problem beim Finden einer exakten Anzahl von Nicht-Null-Einträgen in einer Multiplikation mit einer dünnen Matrix besteht darin, dass jedes Element in der Resultierenden von der Wechselwirkung zweier Vektoren abhängt, von denen beide wahrscheinlich mindestens einige Nicht-Null-Elemente enthalten. Um die Anzahl zu berechnen, müssen Sie logische Operationen für ein Vektorpaar für jedes Element in der Ergebnismenge auswerten. Das Problem dabei ist, dass eine Anzahl von Operationen erforderlich ist, die der Anzahl der Operationen entspricht, die zum Berechnen des Matrixprodukts selbst erforderlich sind. In meinen Kommentaren erwähnte ich die Möglichkeit, bestimmte Strukturen in den Nicht-Null-Elementen der ursprünglichen Matrizen auszunutzen, jedoch könnten dieselben Exploits auch dazu verwendet werden, die bei der Matrixmultiplikation geleistete Arbeit zu reduzieren.
Es ist wahrscheinlich besser, das obige Papier zu verwenden, um den Speicherbedarf zu überschätzen, die Multiplikation durchzuführen und dann den zugewiesenen Speicher abzuschneiden oder die resultierende Matrix in ein Array mit geeigneterer Größe zu verschieben. Auch dünn besetzte Matrixprodukte sind keine Seltenheit, und ich würde fast garantieren, dass dieses Problem bereits gelöst wurde. Wenn Sie sich ein wenig mit Open Source-Bibliotheken mit spärlicher Matrix beschäftigen, sollten Sie sich mit den Algorithmen befassen, mit denen sie Speicher vorbelegen.
quelle
Haben Sie bei CSR oder CSC die Garantie, dass Ihr Array von Matrixelementen bereits keine Nullen enthält? In diesem Fall ist es einfach herauszufinden, wie viele Nicht-Null-Elemente es gibt, und zwar mit etwas ähnlichem wie:
Wenn dies jedoch nicht der Fall ist (scheint ein bisschen zu einfach zu sein), können Sie eine Reduzierung versuchen . Wenn Ihr Array von Matrixelementen sehr groß ist, ist dies möglicherweise die effizienteste Methode, um die Anzahl der Elemente ungleich Null zu berechnen. Viele parallele C / C ++ - Bibliotheken wie Thrust (eine CUDA-Bibliothek) oder OpenCL (für deren Verwendung Sie keine GPU benötigen) unterstützen bedingte Reduktionen. Fügen Sie für jedes Element das Ergebnis von hinzu
Condition(Element)
. Wenn Sie die Bedingung auf setzenElement != 0
, addieren Sie die Anzahl der Elemente ungleich Null. Möglicherweise möchten Sie auch die Elemente mit dem Wert Null aus Ihrem Array von Elementen, dem Array von Zeilen- / Spaltenindizes entfernen und Ihre Spalten- / Zeilenzeiger anpassen.quelle
Die einfachste Möglichkeit zur Implementierung von CSR ist der Versuch
um deine Matrix darzustellen. In diesem Fall kümmern Sie sich nicht wirklich um die Anzahl der Nicht-Null-Elemente. Auf alle wird über zugegriffen
in jeder Reihe. Beste ..
quelle