gpt4 book ai didi

python - 如何优化速度以计算 3D 阵列中沿 Z 轴的平均值? Cython 与 Numpy

转载 作者:太空宇宙 更新时间:2023-11-03 15:34:03 24 4
gpt4 key购买 nike

我正在尝试加快 3d 数组中沿 Z 轴的平均值的计算。我阅读了 cython 的文档以添加类型、内存 View 等,以完成此任务。但是,当我比较两者时:基于 numpy 的函数和另一个基于 .so 文件中的 cython 语法和编译的函数,第一个胜过第二个。我的代码中是否有错误/缺失的步骤或类型声明?

这是我的 numpy 版本:python_mean.py

    import numpy as np


def mean_py(array):
x = array.shape[1]
y = array.shape[2]
values = []
for i in range(x):
for j in range(y):
values.append((np.mean(array[:, i, j])))

values = np.array([values])
values = values.reshape(500,500)
return values

这是我的 cython_mean.pyx 文件

     %%cython
from cython import wraparound, boundscheck
import numpy as np
cimport numpy as np

DTYPE = np.double

@boundscheck(False)
@wraparound(False)
def cy_mean(double[:,:,:] array):
cdef Py_ssize_t x_max = array.shape[1]
cdef Py_ssize_t y_max = array.shape[2]
cdef double[:,:] result = np.zeros([x_max, y_max], dtype = DTYPE)
cdef double[:,:] result_view = result
cdef Py_ssize_t i,j
cdef double mean
cdef list values
for i in range(x_max):
for j in range(y_max):
mean = np.mean(array[:,i,j])
result_view[i,j] = mean
return result

当我导入这两个函数并开始对 3D numpy 数组进行计算时,我得到以下结果:

    import numpy as np
a = np.random.randn(250_000)
b = np.random.randn(250_000)
c = np.random.randn(250_000)

array = np.vstack((a,b,c)).reshape(3, 500, 500)

import mean_py
from mean_py import mean_py
%timeit mean_py(array)


4.82 s ± 84.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)



import cython_mean
from cython_mean import cy_mean


7.3 s ± 499 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

为什么 cython 代码的性能这么低?感谢您的帮助

最佳答案

Numpy 解决方案

对于这个特定问题,使用 numpy.meanaxis 参数可能是最快的实现(即 values = np.mean(array, axis =0)).

请参阅下面的基准测试,使用您的示例,numpy.mean 的速度提高了将近 1000 倍。

In []: %timeit mean_py(array)
1.23 s ± 3.99 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In []: %timeit array.mean(0)
1.07 ms ± 3.76 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In []: np.all(array.mean(0) == mean_py(array))
Out[]: True

对您最初方法的建议

不是解释为什么 cython 版本不是更快,而是关于如何改进 numpy-only 版本的建议(避免 list作为(慢速)中间数据结构):

    import numpy as np


def mean_py(array):
x = array.shape[1]
y = array.shape[2]
#avoid creating values as list first
#and create empty array instead
values = np.empty((x,y), type(array[0][0][0]))
for i in range(x):
for j in range(y):
#no more need for append operations
values[i][j] = ((np.mean(array[:, i, j])))

#no more need for conversion to array
#values = np.array([values])
#values = values.reshape(500,500)
return values

关于python - 如何优化速度以计算 3D 阵列中沿 Z 轴的平均值? Cython 与 Numpy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55986605/

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