Frage

Der folgende Code läuft zu langsam, obwohl alles vektorisiert zu sein scheint.

from numpy import *
from scipy.sparse import *

n = 100000;
i = xrange(n); j = xrange(n);
data = ones(n);

A=csr_matrix((data,(i,j)));

x = A[i,j]

Das Problem scheint zu sein, dass der Indexierungsvorgang als Python-Funktion implementiert ist, und Aufrufe A[i,j] Ergebnisse in der folgenden Profilierungs Ausgabe

         500033 function calls in 8.718 CPU seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   100000    7.933    0.000    8.156    0.000 csr.py:265(_get_single_element)
        1    0.271    0.271    8.705    8.705 csr.py:177(__getitem__)
(...)

Und zwar wird die Python-Funktion _get_single_element 100000 mal aufgerufen, die wirklich ineffizient ist. Warum ist das nicht in reinem C umgesetzt? Kennt jemand eine Möglichkeit, um diese Einschränkung zu bekommen, und die Beschleunigung den obigen Code auf? Soll ich einen anderen Sparse-Matrix-Typen sein mit?

War es hilfreich?

Lösung

Sie können A.diagonal() verwenden, um die Diagonale viel schneller (0,0009 Sekunden gegenüber 3,8 Sekunden auf meinem Rechner) abgerufen werden. Wenn Sie jedoch willkürliche Indizierung tun wollen, dann ist das eine kompliziertere Frage, weil Sie nicht Scheiben so viel wie eine Liste von Indizes verwendet. Die _get_single_element Funktion wird 100.000 mal genannt, weil es nur durch den Iteratoren Iterieren (i und j), die Sie an sie übergeben. [: 60,10 30] oder etwas ähnlich der A slice würde A sein.

Außerdem würde ich csr_matrix(eye(n,n)) verwenden, um die gleiche Matrix, die Sie mit Iteratoren, die nur für Einfachheit.

Update:

Ok, da Ihre Frage wirklich über der Lage ist, wobei viele zufällige Elemente schnell zugreifen zu können, werde ich Ihre Fragen so gut beantworten wie ich kann.

  • Warum ist dies in reinem C nicht umgesetzt?

Die Antwort ist einfach: niemand es bekommen hat um. Es gibt noch viel Arbeit in der Sparse Matrix Module Bereich von Scipy getan wird von dem, was ich gesehen habe. Ein Teil, der in C umgesetzt wird, ist die Umwandlung zwischen verschiedenen sparse Matrix Formaten.

  • Kennt jemand eine Möglichkeit, um diese Einschränkung zu bekommen, und den obigen Code zu beschleunigen?

Sie können versuchen, tatsächlich Tauchen in die Sparse Matrix Module und versuchen, sie zu beschleunigen. Ich tat es und war in der Lage, die Zeit bis zu weniger bekommen als ein Drittel der ursprünglichen, wenn Ihren Code oben für Zufallszugriffe mit csr Matrizen ausprobieren. Es musste direkt _get_single_element zugreifen und deutlich den Code abspecken zu tun, dass mit gebundenen Kontrollen herausnehmen.

Es war jedoch schneller noch lil_matrix zu verwenden (wenn auch langsamer, die Matrix zu initialisieren), aber ich hatte das zugreifende mit einer Liste Verständnis zu tun, weil lil Matrizen nicht Setup für die Art der Indizierung sind Sie tun. Mit hinterlässt eine Liste Verständnis für den csr_matrix noch das lil-Matrix-Verfahren weit voraus durch die Art und Weise. Letztlich ist die lil Matrix schneller für den Zugriff auf zufällige Elemente, weil es nicht komprimiert wird.

die lil_matrix in seiner ursprünglichen Form Verwendung läuft in etwa ein Fünftel der Zeit des Codes Sie oben aufgeführt haben. Wenn ich ein paar gebundene Kontrollen herausnehmen und direkt lil_matrix der _get1 () -Methode aufrufen, kann ich die Zeit bringen weitere etwa 7% der ursprünglichen Zeit. Aus Gründen der Klarheit, die ein Beschleunigungs-3,4-3,8 Sekunden bis etwa 0,261 Sekunden.

Schließlich habe ich versucht, meine eigene Funktion zu machen, dass die lil Matrix der Daten greift direkt auf und vermeidet die wiederholten Funktionsaufrufe. Die Zeit dafür war etwa 0,136 Sekunden. Dies hat nicht die Vorteile der Daten sortiert werden, was eine weitere mögliche Optimierung (insbesondere wenn Sie viele Elemente zugreifen, die auf den gleichen Zeilen) ist.

Wenn Sie schneller als die dann müssen Sie Ihre eigene C-Code Sparse Matrix Implementierung schreiben wahrscheinlich.

  • Soll ich einen anderen Sparse-Matrix-Typen verwenden?

Nun, schlage ich vor, die lil-Matrix, wenn Ihre Absicht ist es, eine ganze Menge Elemente zugreifen, aber es hängt alles davon ab, was Sie tun müssen. Sie benötigen auch Matrizen zum Beispiel zu vermehren? Denken Sie daran, dass zumindest manchmal zwischen Matrizen zu ändern (unter bestimmten Umständen) wird recht schnell so nicht zu einem anderen Matrixformat zu ändern Sie ausschließen zu verschiedenen Operationen zu tun.

Wenn Sie tun müssen, tun nicht wirklich keine Algebra Operationen auf Ihrer Matrix, dann sollten Sie vielleicht nur ein defaultdict oder etwas ähnliches verwenden. Die Gefahr bei defaultdicts ist, dass, wenn ein Element für das ist nicht in der dict gefragt wird, setzt es dieses Element auf den Standard und speichert es das könnte so problematisch sein.

Andere Tipps

Ich denke, _get_single_element nur, wenn der Standard dtype von ‚Objekt‘ genannt wird, verwendet wird. Haben Sie versucht, eine dtype, wie csr_matrix((data, (i,j)), dtype=int32) Bereitstellung

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top