2017-06-22 1 views
0

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 ndarraynp.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é.

+0

fonction DGEMM de MKL fait la multiplication de la matrice et est – user7138814

+0

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

Répondre

2

Pour obtenir un pointeur d'un memoryview vous devez prendre l'adresse du premier élément

ddot(Arowshape0, #call the imported Intel MKL library 
         &A_row[0], 
         Arowstrides, 
         &B_col[0], 
         Bcolstrides) 
+0

Voulez-vous dire aussi bien en passant le pointeur que je peux me débarrasser de toutes les boucles ci-dessus? Ce serait parfait. – Matt

+0

Je ne pense pas - vous avez besoin des boucles pour faire 'A_row' et' B_col'. Il est possible que certaines fonctions autres que 'ddot' puissent tout faire. – DavidW

+0

Merci Je suis en train de construire ma boîte à outils Cython. – Matt