2017-01-05 2 views
1

Fragen:Optimierung der numpy Array-Multiplikation: * schneller als numpy.dot?

1) Wie es ist, dass numpy.dot() langsamer als * im Beispielcode unten, wenn BLAS verwendet wird?

2) Gibt es eine Möglichkeit, numpy.dot() anstelle von * in diesem Fall für schnellere Array-Multiplikation implementiert werden? Ich denke, dass mir eine entscheidende Information fehlt, die Frage 1 beantworten und meinen würde, dass numpy.dot() mindestens genauso schnell ist wie *, wenn nicht schneller.

Details sind unten enthalten. Vielen Dank im Voraus für Antworten und Hilfe.

Details:

ich ein Programm schreibe, die 2.7 (64-Bit), numpy 1.11.2, Anaconda2 auf Windows 7. Zur Verbesserung der Genauigkeit der ich brauche Programmausgabe mit Python gekoppelter PDEs löst um große Arrays zu verwenden (Shape (2, 2^14) und größer) und kleine Integrationsschritte, was zu einer gigantischen Anzahl von Array-Multiplikationsoperationen pro Simulation führt, die ich für die Geschwindigkeit optimieren muss.

Mit looked around scheint es, als ob numpy.dot() für schnellere Array-Multiplikation in Bezug auf * verwendet werden sollte, solange BLAS installiert ist und mit numpy arbeitet. Dies wird häufig empfohlen. Allerdings, wenn ich unter den Timer-Skript verwenden, ist * schneller als numpy.dot() um mindestens einen Faktor 7 In einigen Fällen kann diese Faktoren erhöht> 1000:

from __future__ import division 
import numpy as np 
import timeit 

def dotter(a, b): 
    return np.dot(a, b) 

def timeser(a, b): 
    return a*b 

def wrapper(func, a, b): 
    def wrapped(): 
     return func(a, b) 
    return wrapped 

size = 100 
num = int(3e5) 

a = np.random.random_sample((size, size)) 
b = np.random.random_sample((size, size)) 

wrapped = wrapper(dotter, a, b) 
dotTime = timeit.timeit(wrapped, number=num)/num 
print "\nTime for np.dot: ", dotTime 

wrapped = wrapper(timeser, a, b) 
starTime = timeit.timeit(wrapped, number=num)/num 
print "\nTime for *: ", starTime 

print "dotTime/starTime: ", dotTime/starTime 

Diese Ausgänge:

Time for np.dot: 8.58201189949e-05 
Time for *: 1.07564737429e-05 
dotTime/starTime: 7.97846218436 

sowohl numpy.dot() und * werden über mehrere Kerne verteilt, was ich denke, legt nahe, dass BLAS zu einem gewissen Grad funktioniert, zumindest:

enter image description here

bei numpy.__config__.show() Blick es scheint, als ob ich BLAS und lapack bin mit (wenn auch nicht openblas_lapack?):

lapack_opt_info: 
    libraries = ['mkl_lapack95_lp64', 'mkl_blas95_lp64', 'mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'libiomp5md', 'libifportmd'] 
    library_dirs = ['C:/Program Files (x86)/Intel/Composer XE/mkl/lib/intel64'] 
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)] 
    include_dirs = ['C:/Program Files (x86)/Intel/Composer XE/mkl/include'] 
blas_opt_info: 
    libraries = ['mkl_lapack95_lp64', 'mkl_blas95_lp64', 'mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'libiomp5md', 'libifportmd'] 
    library_dirs = ['C:/Program Files (x86)/Intel/Composer XE/mkl/lib/intel64'] 
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)] 
    include_dirs = ['C:/Program Files (x86)/Intel/Composer XE/mkl/include'] 
openblas_lapack_info: 
    NOT AVAILABLE 
lapack_mkl_info: 
    libraries = ['mkl_lapack95_lp64', 'mkl_blas95_lp64', 'mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'libiomp5md', 'libifportmd'] 
    library_dirs = ['C:/Program Files (x86)/Intel/Composer XE/mkl/lib/intel64'] 
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)] 
    include_dirs = ['C:/Program Files (x86)/Intel/Composer XE/mkl/include'] 
blas_mkl_info: 
    libraries = ['mkl_lapack95_lp64', 'mkl_blas95_lp64', 'mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'libiomp5md', 'libifportmd'] 
    library_dirs = ['C:/Program Files (x86)/Intel/Composer XE/mkl/lib/intel64'] 
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)] 
    include_dirs = ['C:/Program Files (x86)/Intel/Composer XE/mkl/include'] 
+3

Der alte Vergleich zwischen Apfel und Orangen ... – Bakuriu

+0

@Bakuriu Ich kann nicht helfen. Alte Gewohnheiten sterben offenbar hart. –

Antwort

4

np.dot Anrufe Matrix-Matrix-Multiplikation, während * Element weise Multiplikation ist. Das Symbol für die Matrix-Matrix-Multiplikation lautet @ für Python 3.5+.

+0

Ausgezeichnet, danke. Immer wieder gute dumme Fehler! Neue Regel: Mehr Schlaf und weniger Koffein vor langatmigen SO-Posts ... –

Verwandte Themen