Domanda

io ho un numpy Script che spende circa il 50% del suo runtime nel seguente codice:

s = numpy.dot(v1, v1)

dove

v1 = v[1:]

e v è un 1D da 4000 elementi ndarray di float64 memorizzato in memoria contigua (v.strides è (8,)).

Qualche suggerimento per accelerare questo?

modificare Questo è su hardware Intel. Ecco l'output del mio numpy.show_config():

atlas_threads_info:
    libraries = ['lapack', 'ptf77blas', 'ptcblas', 'atlas']
    library_dirs = ['/usr/local/atlas-3.9.16/lib']
    language = f77
    include_dirs = ['/usr/local/atlas-3.9.16/include']

blas_opt_info:
    libraries = ['ptf77blas', 'ptcblas', 'atlas']
    library_dirs = ['/usr/local/atlas-3.9.16/lib']
    define_macros = [('ATLAS_INFO', '"\\"3.9.16\\""')]
    language = c
    include_dirs = ['/usr/local/atlas-3.9.16/include']

atlas_blas_threads_info:
    libraries = ['ptf77blas', 'ptcblas', 'atlas']
    library_dirs = ['/usr/local/atlas-3.9.16/lib']
    language = c
    include_dirs = ['/usr/local/atlas-3.9.16/include']

lapack_opt_info:
    libraries = ['lapack', 'ptf77blas', 'ptcblas', 'atlas']
    library_dirs = ['/usr/local/atlas-3.9.16/lib']
    define_macros = [('ATLAS_INFO', '"\\"3.9.16\\""')]
    language = f77
    include_dirs = ['/usr/local/atlas-3.9.16/include']

lapack_mkl_info:
  NOT AVAILABLE

blas_mkl_info:
  NOT AVAILABLE

mkl_info:
  NOT AVAILABLE
È stato utile?

Soluzione

I tuoi array non sono molto grandi, quindi Atlas probabilmente non sta facendo molto. Quali sono i tuoi tempi per il seguente programma Fortran? Supponendo che Atlas non stia facendo molto, questo dovrebbe darti un'idea di quanto velocemente () potrebbe essere se non ci fosse un sovraccarico di Python. Con Gfortran -O3 ottengo velocità di 5 +/- 0,5 US.

    program test

    real*8 :: x(4000), start, finish, s
    integer :: i, j
    integer,parameter :: jmax = 100000

    x(:) = 4.65
    s = 0.
    call cpu_time(start)
    do j=1,jmax
        s = s + dot_product(x, x)
    enddo
    call cpu_time(finish)
    print *, (finish-start)/jmax * 1.e6, s

    end program test

Altri suggerimenti

Forse il colpevole sta copiando gli array passati punto.

Come ha detto Sven, il punto Il prodotto si basa su operazioni BLAS. Queste operazioni richiedono array memorizzati in ordine C contiguo. Se entrambi gli array sono passati a punto sono in c_contigue, dovresti vedere prestazioni migliori.

Naturalmente, se i tuoi due array sono passati al punto sono effettivamente 1D (8), allora dovresti vedere Entrambi le flag C_contigue e f_contigue impostate su true; Ma se sono (1, 8), allora puoi vedere l'ordine misto.

>>> w = NP.random.randint(0, 10, 100).reshape(100, 1)
>>> w.flags
   C_CONTIGUOUS : True
   F_CONTIGUOUS : False
   OWNDATA : False
   WRITEABLE : True
   ALIGNED : True
   UPDATEIFCOPY : False


Un'alternativa: usa _gemm da blas, che è esposto attraverso il modulo, Scipy.Linalg.fblas. (I due array, A e B, sono ovviamente in ordine di Fortran perché fblas viene usato.)

from scipy.linalg import fblas as FB
X = FB.dgemm(alpha=1., a=A, b=B, trans_b=True)

L'unica cosa a cui riesco a pensare per accelerare questo è assicurarsi che l'installazione numpy sia compilata su una libreria BLAS ottimizzata (come Atlas). numpy.dot() è una delle poche funzioni numpy che utilizzano Blas.

numpy.dot utilizzerà multithreading se compilato correttamente. Assicurati che lo faccia con TOP. Conosco casi in cui le persone non hanno ottenuto il multithreading in Numpy con Atlas per funzionare. Inoltre, vale la pena provare a utilizzare una versione numpy che viene compilata contro le librerie Intel MKL. Includono routine BLAS che dovrebbero essere più veloci dell'Atlante sull'hardware Intel. Potresti provare Python Distro di enthought. Contiene tutto questo ed è gratuito per le persone con un account e -mail EDU.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top