Я пытаюсь улучшить производительность некоторых метрических вычислений с помощью Cython prange
. Вот мои коды:
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
По сути, на каждой итерации метрика Хаусдорфа вычисляется между XA
и каждым XB[i]
. Вот сигнатура функции _hausdorff
:
cdef inline float64_t _hausdorff(float64_t[:,::1] XA, float64_t[:,::1] XB) nogil:
...
моя проблема в том, что и последовательный shausdorff
, и параллельный phausdorff
имеют одинаковые тайминги. Кроме того, кажется, что phausdorff
вообще не создает никакой темы.
Итак, мой вопрос в том, что не так с моим кодом, и как я могу это исправить, чтобы заставить работать многопоточность.
Вот мой 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
)
РЕДАКТИРОВАНИЕ 1: Вот ссылка на HTML-код, сгенерированный cython -a
: custom_metric. html
EDIT 2: Вот пример вызова соответствующих функций (необходимо скомпилировать файл Cython сначала)
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)
omp_get_thread_num()
в теле циклаprange
. См. cython.readthedocs.io/en/latest/src/userguide/parallelism. .html - person Harald   schedule 19.08.2016XB
является объектом Python? Запуститеcython -a custom_metric.pyx
с аннотацией. - person cgohlke   schedule 19.08.2016phausdorff
украшен@cython.boundscheck(False)
и@cython.wraparound(False)
? - person J.J. Hakala   schedule 19.08.2016#cython: boundscheck=False
и#cython: wraparound=False
включены в начало файла. - person mavillan   schedule 19.08.2016Converting to Python object not allowed without gil
- person mavillan   schedule 19.08.2016shausdorff
иphausdorff
? - person Harald   schedule 24.08.2016chunk_size
? В зависимости от алгоритма вы можете иметь очень плохую локализацию данных, используяchunk_size
из1
. - person smateo   schedule 27.08.2016