2016-06-01 13 views
2

Ordinary Matrixprodukt zwischen Bitfeld berechnen:Wie Matrixprodukt auf (sparse) Bitmatrix effizient in Python

  1, 0, 0 
Matrix A = 1, 1, 1 
      0, 0, 1 

       1, 1, 0 
Transpose of A = 0, 1, 0 
       0, 1, 1 

C = Matrix A times (Transpose of Matrix A) 

    1, 1, 0 
C = 1, 3, 1 
    0, 1, 1 

A ist ein Bitfeld von 1 und 0. Die tatsächliche Matrix A ist groß und hat ungefähr 0,25% 1 Einträge und 99,75% Null Einträge.

C ist ein Array von Ganzzahl.

Wie berechnet man dies schnell ohne viel Speicher zu verwenden?

Derzeit verwende ich scipy's Sparse Matrix Multiplikation Routinen für komprimierte Sparse Zeilenmatrizen von Fließkomma 1.0 und 0.0 in Python. Ich versuche auch, c-Funktionen in mkl-Bibliothek direkt aufzurufen, um die Speichernutzung zu reduzieren.

+0

Wie groß? Wie lange dauert es für eine 1000 x 1000-Matrix? – casevh

+0

ist es, Produkt zwischen einer 750,000 x b-Matrix und seiner Transponierten zu berechnen. b ist mindestens 10.000. Je größer das b, desto besser. Der Speicher pro CPU-Kern ist jedoch begrenzt. – rxu

+0

Sorry, ich meine eine Matrix A mit einer Form von b x 750.000. Also sollte die A-Zeit-Transponierte von A die Form von b x b haben. – rxu

Antwort

2

Vorhandene Leistungsbibliotheken wie MKL verwenden immer float/double als Datentyp. Vergleicht man das Konvertieren von A in eine Float-CSR und dann den Aufruf von .dot() oder einigen MKL-Routinen, kann es sein, dass Sie Ihren eigenen bit-mat-mul Code schneller schreiben. Sie brauchen nicht einmal die Multiplikationsoperation. Es zählt nur die Bits.

bearbeiten

nach dem Kontext auf dem queation zu wissen, würde ich das folgende Verfahren vorschlagen.

  1. Konvertieren Sie Ihr Array A in das CSR-Format und speichern Sie nur col-Indizes und row ptr;
  2. Für jede Zeile i und Zeile j von A, zählen Sie die Anzahl der gemeinsamen col-Indizes und speichern Sie das Ergebnis in C (i, j) mit i < = j nur als C ist symmetrisch. Dies ist schnell, wenn col-Indizes sortiert werden.

Die dichte Matric C ist, was Sie wollen.

Angesichts der Größe (b x 750.000) und der Dichte (0,25%) von Ihrem A ist die Dichte von C 99.1%; Die durchschnittliche Länge jedes col Indizes ist 1875.

Also Ihr Problem wird die Anzahl der gemeinsamen Elemente von 2 1875-D-Vectoers für b*(b+1)/2 mal zählen.

Die Geschwindigkeit der for-Schleife scheint das einzige verbleibende Problem zu sein.

+0

Vorherige Fragen von @ rxu implizieren, dass die Daten als 'gmpy2.mpz' Typ gespeichert werden können. Wenn das korrekt ist, sollte 'gmpy2.hamdist (row & col, 0)' sehr schnell sein. – casevh

+0

Lass mich das versuchen. Ich mache mir Sorgen, dass die Overhead-Python-Schleife und das Aufrufen von C++ aus Python die Dinge langsam machen werden ... Tatsächlich habe ich eine Version geschrieben, die Pythons Satz und Schnittpunkt einmal verwendet. Dieser ist viel langsamer als Scipys Punkt für spärliche Matrix. Auch wenn der Aufbau der Sparse-Matrix Zeit braucht. Die kombinierte Zeit ist immer noch viel schneller als die eingestellte Version. Im vorherigen Teil des Programms habe ich mpz und Python-Schleife verwendet, um logisch_und sehr schnell zu berechnen. Das hat sehr gut funktioniert, und scipy kann das nicht so schnell machen und verbraucht jede Menge Speicher. – rxu

+0

Bei diesem ersten Teil des Programms arbeiten auf dichten Bit-Array. Jetzt muss ich im zweiten Teil des Programms mit sparse array arbeiten. – rxu