Рассматривают оптимизированного кода Cython в двух случаях:Cython 0,2: Прейндж замедляя код неожиданно
for j in xrange(8):
for x in xrange(1, 600):
tmp[j] = 0.0
for y in xrange(1, 800):
tmp[j] += mag[j, x - 1, y - 1]
hgi_out[j, x, y] = tmp[j] + hgi_out[j, x - 1, y]
и:
for j in prange(8): # < prange used for parallelization with openmp
for x in xrange(1, 600):
tmp[j] = 0.0
for y in xrange(1, 800):
tmp[j] += mag[j, x - 1, y - 1]
hgi_out[j, x, y] = tmp[j] + hgi_out[j, x - 1, y]
В обоих случаях код находится в пределах собственной функции с nogil объявленных и числовых массивов с представлениями памяти и оптимизированной компоновкой. Рабочее время для первого случая: 14.97 мсек, а для второго - 26.64 примерно удвоение !!
У меня есть другие функции, где использование prange значительно улучшает производительность на моей многоядерной машине, за исключением вышеуказанных случаев, я не понимаю, что происходит.
Любые идеи о том, почему prange замедляет код?
FWIW, вот полный исходный код:
# cython: boundscheck=False
# cython: wraparound=False
# cython: nonecheck=False
# cython: overflowcheck.fold=True
# cython: embedsignature=False
# cython: cdivision=True
# cython: cdivision_warnings=False
# cython: always_allow_keywords=False
# cython: profile=False
# cython: linetrace=False
# cython: infer_types=False
# cython: language_level=2
# cython: c_string_type=unicode
# cython: c_string_encoding=utf-8
# cython: type_version_tag=True
# cython: unraisable_tracebacks=True
from __future__ import division
import numpy as np
cimport numpy as np
cimport cython
from cython.parallel import prange
DTYPE = np.int
ctypedef np.int_t DTYPE_t
UITYPE = np.uint
ctypedef np.uint_t UITYPE_t
U8TYPE = np.uint8
ctypedef np.uint8_t U8TYPE_t
F32TYPE = np.float32
ctypedef np.float32_t F32TYPE_t
F64TYPE = np.float64
ctypedef np.float64_t F64TYPE_t
ctypedef Py_ssize_t DSIZE_t
cdef void native_hog_integral_b(F64TYPE_t [:, :, ::1] mag,
F64TYPE_t [:, :, ::1] hgi_out) nogil:
cdef DSIZE_t m, n, x, y, j, dims = mag.shape[0]
cdef F64TYPE_t [32] tmp
cdef F64TYPE_t val = 0
m, n = mag.shape[1] + 1, mag.shape[2] + 1
for j in prange(dims):
for x in xrange(1, m):
tmp[j] = 0.0
for y in xrange(1, n):
tmp[j] += mag[j, x - 1, y - 1]
hgi_out[j, x, y] = tmp[j] + hgi_out[j, x - 1, y]
def hog_integral_b(mag, hgi_out=None, orientations=8):
if hgi_out is None:
hgi_out = np.zeros((orientations + 1, mag.shape[0] + 1, mag.shape[1] + 1), dtype=F64TYPE)
native_hog_integral_b(mag, hgi_out)
return hgi_out
Чтобы проверить код выше, попробуйте:
mg2 = np.random.rand(9, 600, 800).astype(F64TYPE)
hg2 = np.zeros((9, mg2.shape[1] + 1, mg2.shape[2] + 1), dtype=F64TYPE)
print timeit(lambda:hog_integral_b(mg2, hgi_out=hg2), number=10)
UPDATE:
Хорошо, я внимательно посмотрел на мои настройки .py для компилятора:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy as np
ext_modules = [Extension("hog_cy", ["hog_cy.pyx"],
#extra_compile_args = ["-O3", "-fopenmp", "-fno-strict-aliasing"],
extra_compile_args = ["-O3", "-fopenmp"],
extra_link_args=["-fopenmp"]
)]
setup (
name = 'performance test app',
cmdclass = {'build_ext': build_ext},
include_dirs = [np.get_include()],
ext_modules = ext_modules,
)
вариант -fno-strict-aliasing
, кажется, создает проблему, после отключения я не получаю ускорения, но не теряю.
Может ли вы опубликовать полный пример? – YXD
Надеюсь, что вопрос станет более четким размещением всего кода. –
Извините, что вы так педантичны, но можете ли вы добавить функцию для вызова 'hog_integral_b' с образцовыми (случайными) данными правой формы и dtype? – YXD