2010-12-07 8 views
5

In numpy, was der effizienteste Weg ist x.T * x zu berechnen, wo x ist eine große (200.000 x 1000) dicht float32 Matrix und .T ist der transponierte Operator?numpy: berechnen x.T * x für eine große Matrix

Zur Vermeidung von Missverständnissen ist das Ergebnis 1000 x 1000

bearbeiten: In meiner ursprünglichen Frage stellte ich fest, dass np.dot(x.T, x) Stunden nahmen. Es stellte sich heraus, dass ich einige NaNs in die Matrix schleichen hatte, und aus irgendeinem Grund, dass die Leistung von np.dot (irgendwelche Erkenntnisse, warum?) Vollständig getötet wurde Dies ist jetzt gelöst, aber die ursprüngliche Frage steht.

Antwort

10

dies die Antwort nicht sein kann, nach dem Sie suchen, sondern eine Möglichkeit, es wesentlich zu beschleunigen ist ein gpu statt Ihrer CPU zu verwenden. Wenn Sie eine anständig starke Grafikkarte haben, wird sie Ihre CPU jeden Tag übertreffen, auch wenn Ihr System sehr gut abgestimmt ist.

Für eine gute Integration mit numpy könnten Sie theano verwenden (wenn Ihre Grafikkarte von nvidia stammt). Die Berechnung im folgenden Code läuft für mich in wenigen Sekunden (obwohl ich habe eine sehr leistungsstarke Grafikkarte):

$ THEANO_FLAGS=device=gpu0 python 
Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) 
[GCC 4.4.3] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import theano 
Using gpu device 0: GeForce GTX 480 
>>> from theano import tensor as T 
>>> import numpy 
>>> x = numpy.ones((200000, 1000), dtype=numpy.float32) 
>>> m = T.matrix() 
>>> mTm = T.dot(m.T, m) 
>>> f = theano.function([m], mTm) 
>>> f(x) 
array([[ 200000., 200000., 200000., ..., 200000., 200000., 200000.], 
     [ 200000., 200000., 200000., ..., 200000., 200000., 200000.], 
     [ 200000., 200000., 200000., ..., 200000., 200000., 200000.], 
     ..., 
     [ 200000., 200000., 200000., ..., 200000., 200000., 200000.], 
     [ 200000., 200000., 200000., ..., 200000., 200000., 200000.], 
     [ 200000., 200000., 200000., ..., 200000., 200000., 200000.]], dtype=float32) 
>>> r = f(x) 
>>> r.shape 
(1000, 1000) 

Ich wollte warten, um herauszufinden, wie lange >>> numpy.dot(x.T, x) durch Vergleich nahm, aber ich Langeweile ...

Sie können PyCuda oder PyOpenCL auch versuchen (wenn Sie nicht eine nvidia Grafikkarte haben), obwohl ich nicht weiß, ob ihre numpy Unterstützung so direkt ist.

+1

Es ist mir gerade eingefallen, dass bei Matrizen dieser große Speicher eine Einschränkung bei vielen Grafikkarten sein wird. Etwas, auf das man achten sollte. –

+2

obwohl dies in der Tat eine nette Alternative ist, ist es sicherlich nicht normal, dass seine CPU-Multiplikation so viel Zeit braucht – steabert

+0

Vielen Dank für den Zeiger. Das ist sehr interessant und lohnt sich sicherlich. – NPE

2

hmm, x ist etwa 800 Mb, vorausgesetzt, es benötigt das gleiche für das Ergebnis, sind Sie sicher, dass Sie genug physischen Speicher haben und es nicht swappt?

anders als das sollte numpy eine BLAS-Funktion verwenden, und obwohl die Standardbibliothek, die numpy verwendet, relativ langsam sein kann, sollte es für diese Größe funktionieren.

bearbeiten

import numpy as npy 
import time 

def mm_timing(): 
    print " n Gflops/s" 
    print "===============" 
    m = 1000 
    n = 200000 
    a = npy.random.rand(n, m) 
    flops = (2 * float(n) - 1) * float(m)**2 
    t1 = time.time() 
    c = npy.dot(a.T, a) 
    t2 = time.time() 
    perf = flops/(t2 - t1)/1.e9 
    print "%4i" % n + "  " + "%6.3f" % perf 

mm_timing() 
+0

@steabert Ziemlich sicher, dass es nicht vertauscht (wie durch 'vmstat' belegt). Es nimmt auch 100% eines Kerns, was es nicht wäre, wenn es I/O-gebunden wäre. Etwas anderes muss weitergehen. – NPE

+0

Welche FLOPS messen Sie für die Matrixmultiplikation für einige kleinere Matrizen? – steabert

+0

@steabert Was ist der Standard-Benchmark dafür? – NPE

5

Stellen Sie zuerst sicher, dass Sie ein optimiertes Blas/Lapack verwenden, dies kann einen enormen Unterschied machen (bis zu einer Größenordnung). Wenn Sie beispielsweise einen ATLAS-Thread verwenden, werden alle Ihre Kerne relativ effizient verwendet (Sie müssen jedoch einen neueren ATLAS verwenden, und das Kompilieren von ATLAS ist ein PITA).

Warum Nan alles verlangsamt: das ist ziemlich unvermeidlich, NaN-Handling ist viel langsamer als "normales" Floaten auf der CPU-Ebene: http://www.cygnus-software.com/papers/x86andinfinity.html. Es hängt vom CPU-Modell, von der Art des verwendeten Anweisungssatzes und natürlich von den Algorithmen/Implementierungen ab, die Sie verwenden.

+0

Haben Sie Hinweise darauf, dass 'NaN-Handling viel langsamer ist als" normales Float auf CPU-Ebene "? Das einzige, was ich finden konnte, ist http://stackoverflow.com/questions/3606054/how-slow-is-nan-arithmetic-in-the-intel-x64-fpu/3606088#3606088 Thanks – NPE

+0

hinzugefügt einen Link. Die Verlangsamung hängt von vielen Parametern ab, so dass es schwierig ist, einen Grund festzuhalten, und es ist ein Fall-für-Fall. –