J'ai écrit un programme Cython appelant Intel MKL pour la multiplication de matrices, dans le but de le rendre parallèle. Il était basé sur un ancien post SO lié à BLAS et utilisait un tas de méthodes Cython que je n'avais jamais vues, mais je l'ai fait fonctionner et c'était beaucoup plus lent que NumPy (également lié à MKL). Afin de l'accélérer, j'ai utilisé le format Memoryview typique (il utilisait le type de données ndarray
np.float64_t
pour quelques opérations). Mais maintenant, il ne fonctionne plus en utilisant double[::1]
Memoryviews. Voici l'erreur générée: 'type cast': cannot convert from '__Pyx_memviewslice' to 'double *'
Tapez l'erreur '__Pyx_memviewslice' sur 'double *' Cython, quel est l'équivalent? MKL fonction prange code
Et en raison de la distribution de type ne fonctionne pas, la fonction MKL ne voit que 3 5 arguments: error C2660: 'cblas_ddot': function does not take 3 arguments
Voici le code .PYX:
import numpy as np
cimport numpy as np
cimport cython
from cython cimport view
from cython.parallel cimport prange #this is your OpenMP portion
from openmp cimport omp_get_max_threads #only used for getting the max # of threads on the machine
cdef extern from "mkl_cblas.h" nogil: #import a function from Intel's MKL library
double ddot "cblas_ddot"(int N,
double *X,
int incX,
double *Y,
int incY)
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
cpdef matmult(double[:,::1] A, double[:,::1] B):
cdef int Ashape0=A.shape[0], Ashape1=A.shape[1], Bshape0=B.shape[0], Bshape1=B.shape[1], Arowshape0=A[0,:].shape[0] #these are defined here as they aren't allowed in a prange loop
if Ashape1 != Bshape1:
raise TypeError('Inner dimensions are not consistent!')
cdef int i, j
cdef double[:,::1] out = np.zeros((Ashape0, Bshape1))
cdef double[::1] A_row = np.zeros(Ashape0)
cdef double[:] B_col = np.zeros(Bshape1) #no idea why this is not allowed to be [::1]
cdef int Arowstrides = A_row.strides[0] // sizeof(double)
cdef int Bcolstrides = B_col.strides[0] // sizeof(double)
cdef int maxthreads = omp_get_max_threads()
for i in prange(Ashape0, nogil=True, num_threads=maxthreads, schedule='static'): # to use all cores
A_row = A[i,:]
for j in range(Bshape1):
B_col = B[:,j]
out[i,j] = ddot(Arowshape0, #call the imported Intel MKL library
<double*>A_row,
Arowstrides,
<double*>B_col,
Bcolstrides)
return np.asarray(out)
Je suis sûr que c'est facile pour quelqu'un sur SO à signaler. Et s'il vous plaît conseiller si vous voyez où l'amélioration peut être faite - cela a été piraté et coupé ensemble et je ne pense pas que les boucles d'i/j sont même nécessaires. L'exemple le plus propre autour de: https://gist.github.com/JonathanRaiman/f2ce5331750da7b2d4e9 que j'ai finalement compilé est en réalité beaucoup plus rapide (2x) mais ne donne aucun résultat donc je le mettrai dans un autre post (ici: Calling BLAS/LAPACK directly using the SciPy interface and Cython - also how to add MKL)
Très apprécié.
fonction DGEMM de MKL fait la multiplication de la matrice et est – user7138814
multi-thread @ user7138814 j'ai vu aussi. J'ai vu votre commentaire sur mon autre message Cython - apparemment, je pourrais utiliser la même approche basée sur un pointeur au lieu de ce qui précède? – Matt