【问题标题】:Learning to write to an array in Cython学习在 Cython 中写入数组
【发布时间】: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 假设的那样优化。如果你只在整个函数的末尾添加一次suma[0],你可能会有更好的运气。
  • 您可能会从将a 的声明更改为np.ndarray[DTYPE_t, ndim=1,mode="c"] 获得一些小好处。这告诉 Cython 该数组是 C 连续的(即它可以忽略步幅),这在您的情况下是正确的。
  • 也许当您删除a[0]+=sum 时,C 编译器能够优化很多(如果不是全部)循环。这是对编译代码进行微基准测试时的常见缺陷。

标签: python arrays numpy cython


【解决方案1】:

您说 a[0] += sum 是使代码变慢的问题所在。你是怎么确定的?关于它有多快或多慢的宝贵信息很少。与将其注释掉相比,是否需要多 10% 或 1000% 的时间?

这是一个理论

鉴于您所谈论的实际情况涉及许多其他变量,这些变量决定了 a 的索引,我怀疑它根本不在缓存中,并且每次都必须获取。其他一切都很快,因为它是可预测的(线性地遍历数组),但是如果 a 足够大(数千个条目)并且您正在随机索引它,那么它可能不适合缓存以及其他所有内容开。

所以并不是 a[0] += sum 很慢。这很快。数学肯定很快。而且可预测的索引也很快。

这是因为a[random_index]加载慢,因为它不在缓存中,因为当前random_index和最后一个random_index之间的差异通常很大,所以CPU通常会做的一切隐藏一些或大部分您的延迟时间会下降。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-13
    • 2021-03-05
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-01
    相关资源
    最近更新 更多