赛通的系列没有提高性能



我试图用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度量。以下是_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
) 

EDIT 1:这是cython -a生成的html链接:custom_metrics .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)

我认为并行化正在工作,但是并行化的额外开销正在消耗它本可以节省的时间。如果我尝试使用不同大小的数组那么我确实开始看到并行版本的速度加快

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中的开销降低了速度——串行版本实际上对示例中的数组更快。

相关内容

  • 没有找到相关文章

最新更新