Diggum hat geschrieben:Hallo,
schonmal daran gedacht, das Ganze auf der GPU zu rechnen?
Viele Tausend Datenpunkte mit ihrerseits vielen Hundert kleinen Matrixmultiplikationen hört sich nach guter Parallelisierbarkeit an.
Ich bin vor einiger Zeit auf eine Bibliothek namens Arrayfire (C/C++ und Python-Wrapper) gestoßen und es ist genaugenommen kein Mehraufwand im Vergleich zum Rechnen auf der CPU.
Ich glaube ich würde für jeden Datenpunkt einen parallelen Thread spawnen und dann die matmuls direkt rechnen oder auch wieder Threads dafür spawnen.
Schaut's euch mal an, es gibt jede Menge implementierte Funktionen, läuft auf CPU, CUDA und OpenCL und es ist open source.
http://www.arrayfire.com
https://github.com/arrayfire/arrayfire-python
Danke für den Tip, ich werde das gleich mal lesen.
Wie's der Zufall so will bin ich nämlich grade dabei Parallelisierung des Pakets zu ermöglichen. Eigentlich würde ich das lieber auf der Python-Ebene lösen, aber wenn es sinnvoll ist auch kurze Rechnungen zu parallelisieren, dann sollte ich mir das vielleicht anders überlegen.
Bei meiner jetztigen Variante der Parallelisierung bin ich auf ein seltsames Problem gestoßen. Offenbar werden einige Inputs nach dem Threaden nicht mehr erkann, vielleicht weiß jemand Rat bei dem Problem. Hier ist ein Minimalbeispiel:
Pyparr.pyx
Code: Alles auswählen
import cython
cdef class Myclass:
cdef int dummy
def __init__(self, i):
self.dummy=i
def getdummy(self):
return self.dummy
def pyfunc(a):
return a.getdummy()
setup.py: Ausführen mit python setup.py build_ext --inplace
Code: Alles auswählen
from distutils.core import setup, Extension
from Cython.Build import cythonize
setup(ext_modules = cythonize(Extension(
"Pyparr", # the extension name
sources=["Pyparr.pyx"],
)))
Code: Alles auswählen
import Pyparr as Pyp
from joblib import Parallel, delayed
if __name__ == '__main__':
a=[]
a=a+[Pyp.Myclass(4)]
a=a+[Pyp.Myclass(5)]
a=a+[Pyp.Myclass(6)]
a=a+[Pyp.Myclass(7)]
n=1
out=Parallel(n_jobs=n)(delayed(Pyp.pyfunc)(a[i]) for i in range(4))
print out
a=[]
a=a+[Pyp.Myclass(4)]
a=a+[Pyp.Myclass(5)]
a=a+[Pyp.Myclass(6)]
a=a+[Pyp.Myclass(7)]
n=4
out=Parallel(n_jobs=n)(delayed(Pyp.pyfunc)(a[i]) for i in range(4))
print out
Bei mir steht dann als Ausgabe:
[4,5,6,7]
[0,0,0,0]
Die Ausgabe hängt also auf seltsame Art von der Anzahl der Jobs ab, die joblib Parallel verteilt.
Mit einer nativen Python-Klasse anstatt einer kompilierten Cython-Klasse tritt das Problem nicht auf.