Cython - 定义二维数组

4

这是我正在尝试优化的Cython代码:

    import cython
    cimport cython
    from libc.stdlib cimport rand, srand, RAND_MAX
    import numpy as np
    cimport numpy as np

    def genLoans(int loanid):
        cdef int i, j, k
        cdef double[:,:,:] loans = np.zeros((240, 20, 1000))
        cdef double[:,:] aggloan = np.zeros((240, 20))
        for j from 0<=j<1000:
            srand(loanid*1000+j)
            for i from 0<=i<240:
                for k from 0<=k<20:
                    loans[i,k,j] = rand()
                    ###some other logics
            aggloan[i,k] += loans[i,k,j]/1000
        return aggloan

cython -a 展示

enter image description here 我猜当我试着初始化零数组loans和aggloan时,numpy会减慢我的速度。然而,我需要运行5000多个贷款。只是想知道在定义3D / 2D并返回数组时是否有其他避免使用numpy的方法...

1个回答

4
黄色部分是因为Numpy调用时,你需要分配数组。你可以将这些数组作为参数传递给函数,并从一个函数中重复使用它们。
此外,我看到你正在重新编写所有元素,所以你在声明内存、用零写入并放入数字。如果你确定要覆盖所有元素,可以使用np.empty,这不会初始化变量。
注意:Linux内核有一种特定的分配内存的方式,初始化为0,比其他任何值都快,现代Numpy可以使用它,但仍然比empty慢。
In [4]: %timeit np.zeros((100,100))
100000 loops, best of 3: 4.04 µs per loop

In [5]: %timeit np.ones((100,100))
100000 loops, best of 3: 8.99 µs per loop

In [6]: %timeit np.empty((100,100))
1000000 loops, best of 3: 917 ns per loop

最后但并非最不重要的,您确定这是您的瓶颈吗?我不知道您正在进行什么处理,但黄色表示的是C代码行数,而不是时间。无论如何,从时间上看,使用empty应该可以将速度提高四倍。如果您想获得更多帮助,请在CR上发布您的其余代码。 编辑: 进一步解释我的第二句话:您的函数签名可以是
def genLoans(int loanid, cdef double[:,:,:] loans,  cdef double[:,:] aggloan):

在您的循环之前初始化数组,然后再次传递它们。

无论如何,在我的机器上(Linux Intel i5),它需要9微秒,因此您总共要花费45毫秒。这绝对不是您的瓶颈。进行性能分析!


1
如果我在pyx文件中定义'cdef double[:] zeros = np.zeros(360)',然后将aggloan = zeros,这会有影响吗?每次调用函数时会变慢吗? - kaiyan711
你的评论似乎不完整,@kaiyan711 - Davidmh
1
我在Python中的循环中调用了这个函数。虽然在Python中使用循环会消耗更多时间,但是Python更方便读取文本文件和数据库。另一种选择是将所有文件内容作为数组传递到Cython中并在那里进行循环。只是想知道其他人会如何处理... - kaiyan711
2
@kaiyan711,我已经解释了一种绕过它的方法,但我相信你在错误的地方花费了时间(这只占用了你完整运行时间的毫秒级别)。如果可以的话,请在Code Review上发布您的代码,我们可以看一下。在这里@我,以便我不会错过它。 - Davidmh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接