gpt4 book ai didi

python - Cython 的 prange 没有提高性能

转载 作者:太空狗 更新时间:2023-10-29 21:06:45 28 4
gpt4 key购买 nike

我正在尝试使用 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

基本上,在每次迭代中,hausdorff 度量是在 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: 这是 cython -a 生成的 html 的链接:custom_metric.html

EDIT 2: 下面是一个如何调用相应函数的例子(你需要先编译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)

最佳答案

我认为并行化是有效的,但并行化的额外开销正在耗尽它本应节省的时间。如果我尝试使用不同大小的数组,那么我确实开始看到并行版本的速度有所提高

XA = np.random.random((900, 2100))
XB = np.random.random((100, 2100, 90))

对我而言,并行版本花费的时间大约是串行版本的 2/3,这当然不是您预期的 1/4,但至少显示出一些好处。


我可以提供的一个改进是替换修复连续性的代码:

XB = np.asanyarray([np.ascontiguousarray(XB[:,:,i]) for i in range(n)]) 

XB = np.ascontiguousarray(np.transpose(XB,[2,0,1]))

这相当显着地加快了并行和非并行函数的速度(与您最初提供的数组相比是 2 倍)。它确实使您因 prange 中的开销而变慢的速度变得更加明显 - 对于示例中的数组,串行版本实际上更快。

关于python - Cython 的 prange 没有提高性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39033170/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com