J'essaie d'améliorer les performances de certains calculs métriques avec Cython prange
. Voici mes codes:Prange pas améliorer les performances de Cython
def shausdorff(float64_t[:,::1] XA not None, float64_t[:,:,::1] XB not None):
cdef:
Py_ssize_t i
Py_ssize_t n = XB.shape[2]
float64_t[::1] hdist = np.zeros(n)
#arrangement to fix contiguity
XB = np.asanyarray([np.ascontiguousarray(XB[:,:,i]) for i in range(n)])
for i in range(n):
hdist[i] = _hausdorff(XA, XB[i])
return hdist
def phausdorff(float64_t[:,::1] XA not None, float64_t[:,:,::1] XB not None):
cdef:
Py_ssize_t i
Py_ssize_t n = XB.shape[2]
float64_t[::1] hdist = np.zeros(n)
#arrangement to fix contiguity (EDITED)
cdef float64_t[:,:,::1] XC = np.asanyarray([np.ascontiguousarray(XB[:,:,i]) for i in range(n)])
with nogil, parallel(num_threads=4):
for i in prange(n, schedule='static', chunksize=1):
hdist[i] = _hausdorff(XA, XC[i])
return hdist
En fait, à chaque itération la métrique de Hausdorff est calculée entre XA
et chaque XB[i]
. Voici la signature de la fonction _hausdorff
:
cdef inline float64_t _hausdorff(float64_t[:,::1] XA, float64_t[:,::1] XB) nogil:
...
mon problème est que le shausdorff
et le phausdorff
parallèle séquentiel ont les mêmes horaires. En outre, il semble que phausdorff
ne crée aucun thread.
Donc, ma question est ce qui ne va pas avec mon code, et comment puis-je le réparer pour que le thread fonctionne.
Voici mon setup.py
:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
from Cython.Distutils import build_ext
ext_modules=[
Extension("custom_metric",
["custom_metric.pyx"],
libraries=["m"],
extra_compile_args = ["-O3", "-ffast-math", "-march=native", "-fopenmp" ],
extra_link_args=['-fopenmp']
)
]
setup(
name = "custom_metric",
cmdclass = {"build_ext": build_ext},
ext_modules = ext_modules
)
EDIT 1: Voici un lien vers le code HTML généré par cython -a
: custom_metric.html
EDIT 2: Voici un exemple sur la façon d'appeler les fonctions correspondantes (vous devez d'abord compiler the Cython file)
import custom_metric as cm
import numpy as np
XA = np.random.random((9000, 210))
XB = np.random.random((1000, 210, 9))
#timing 'parallel' version
%timeit cm.phausdorff(XA, XB)
#timing sequential version
%timeit cm.shausdorff(XA, XB)
Avez-vous essayé d'imprimer l'équivalent de 'omp_get_thread_num()' dans le corps de la boucle de 'prange'. Voir http://cython.readthedocs.io/en/latest/src/userguide/parallelism.html – Harald
Peut-être que 'XB' est un objet Python? Exécutez 'cython -a custom_metric.pyx' avec une annotation. – cgohlke
Y a-t-il des changements si 'phausdorff' est décoré avec' @ cython.boundscheck (False) 'et @ @ cython.wraparound (False)'? –