【发布时间】:2015-05-05 23:47:57
【问题描述】:
当我写入“a”数组时,我想做的简化代码要慢得多:
在 pyx 文件中:
import cython
import numpy as np
cimport numpy as np
ctypedef np.float64_t DTYPE_t
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
def writearray(np.ndarray[DTYPE_t, ndim=1] a):
cdef int i,j,k,l
cdef DTYPE_t sum=0.0
for i in range(100):
for j in range(100):
for k in range(100):
for l in range(1000):
sum+=1.0
a[0]+=sum #this is the trouble line that makes the code slow.
我以为我有“a[0]”和“sum”是同一类型,但我是这样吗? 在调用这个函数之前,“a”数组被声明为
a=np.zeros(5, dtype=np.float64)
使用“cython -a”分析“a[0]+=sum”显示(没有黄色):
__pyx_t_5 = 0;
*__Pyx_BufPtrStrided1d(__pyx_t_11kobpairwise_DTYPE_t *,
__pyx_pybuffernd_a.rcbuffer->pybuffer.buf, __pyx_t_5,
__pyx_pybuffernd_a.diminfo[0].strides) += __pyx_v_sum;
提前致谢。
这个问题比 a 的索引取决于所有 i,j,k,l 并且 sum 不再增加一个常数的完整问题要简化得多,所以我需要找出这个问题的根本原因问题而不是将 a[0] 移出循环等。
【问题讨论】:
-
请用
cython -a编译,然后给我们看a[0] += sum行变成的C代码。您应该在与 PYX 相同的目录中获得一个 HTML 文件。单击有问题的行,它将扩展为已翻译的 C。 -
没有黄色:a[0]+=sum __pyx_t_5 = 0; *__Pyx_BufPtrStrided1d(__pyx_t_11kobpairwise_DTYPE_t *, __pyx_pybuffernd_a.rcbuffer->pybuffer.buf, __pyx_t_5, __pyx_pybuffernd_a.diminfo[0].strides) += __pyx_v_sum; } } }
-
很难确定。我猜
sum生活在一个寄存器中,而a[0]不是。这意味着后者每次迭代都需要额外的加载/存储。宏也可能没有像 Cython 假设的那样优化。如果你只在整个函数的末尾添加一次sum到a[0],你可能会有更好的运气。 -
您可能会从将
a的声明更改为np.ndarray[DTYPE_t, ndim=1,mode="c"]获得一些小好处。这告诉 Cython 该数组是 C 连续的(即它可以忽略步幅),这在您的情况下是正确的。 -
也许当您删除
a[0]+=sum时,C 编译器能够优化很多(如果不是全部)循环。这是对编译代码进行微基准测试时的常见缺陷。
标签: python arrays numpy cython