mav*_*lan 8 python numpy openmp cython gil
我正在尝试使用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
Run Code Online (Sandbox Code Playgroud)
基本上,在每一次迭代的Hausdorff度量之间计算XA
每个XB[i]
.这是_hausdorff
函数的签名:
cdef inline float64_t _hausdorff(float64_t[:,::1] XA, float64_t[:,::1] XB) nogil:
...
Run Code Online (Sandbox Code Playgroud)
我的问题是顺序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
)
Run Code Online (Sandbox Code Playgroud)
编辑1:这是生成的html的链接cython -a
:custom_metric.html
编辑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)
Run Code Online (Sandbox Code Playgroud)
我认为并行化正在发挥作用,但是并行化的额外开销正在消耗它本来可以节省的时间。如果我尝试使用不同大小的数组,那么我确实开始看到并行版本的速度加快
XA = np.random.random((900, 2100))
XB = np.random.random((100, 2100, 90))
Run Code Online (Sandbox Code Playgroud)
对我来说,并行版本大约需要串行版本时间的 2/3,这当然不是您期望的 1/4,但至少显示出一些好处。
我可以提供的一项改进是替换修复连续性的代码:
XB = np.asanyarray([np.ascontiguousarray(XB[:,:,i]) for i in range(n)])
Run Code Online (Sandbox Code Playgroud)
和
XB = np.ascontiguousarray(np.transpose(XB,[2,0,1]))
Run Code Online (Sandbox Code Playgroud)
这相当显着地加速了并行和非并行函数的速度(与您最初给出的数组相比,速度提高了 2 倍)。它确实使您的速度因开销而变慢,这一点更加明显prange
- 对于示例中的数组来说,串行版本实际上更快。
归档时间: |
|
查看次数: |
579 次 |
最近记录: |