Arrays 在Cython中调用numpy函数确实会减慢速度

Arrays 在Cython中调用numpy函数确实会减慢速度,arrays,python-3.x,numpy,cython,probability,Arrays,Python 3.x,Numpy,Cython,Probability,我正在尝试调用np.random.choice,不需要替换,而是在二维numpy数组中逐行调用。我用Cython来提速。代码的运行速度仅比纯python实现快3倍,这不是一个好结果。瓶颈是numpy函数调用本身。当我把它注释掉,只给每一行提供一个静态结果,比如说[3,2,1,0],我会得到1000倍的加速(当然,它不会做很多事情:) 我的问题是:调用numpy函数是否有什么地方我做错了,导致它变得超慢?从理论上讲,这是C对C的对话,所以它应该很快。我查看了编译后的代码,对numpy函数的调用看起

我正在尝试调用
np.random.choice
,不需要替换,而是在二维numpy数组中逐行调用。我用Cython来提速。代码的运行速度仅比纯python实现快3倍,这不是一个好结果。瓶颈是numpy函数调用本身。当我把它注释掉,只给每一行提供一个静态结果,比如说
[3,2,1,0]
,我会得到1000倍的加速(当然,它不会做很多事情:)


我的问题是:调用numpy函数是否有什么地方我做错了,导致它变得超慢?从理论上讲,这是C对C的对话,所以它应该很快。我查看了编译后的代码,对numpy函数的调用看起来很复杂,有
\uuupyx\ugotref
\uuupyx\upyobject\ugetattrstr
这样的语句,这让我相信它在这个过程中使用的是纯python(糟糕!!)

我的代码:

# tag: numpy

import numpy as np

# compile-time info for numpy
cimport numpy as np
np.import_array()

# array dtypes
W_DTYPE = np.float
C_DTYPE = np.int

cdef int NUM_SELECTIONS = 4  # FIXME should be function kwarg

#compile-time dtypes
ctypedef np.float_t W_DTYPE_t
ctypedef np.int_t C_DTYPE_t


def allocate_choices(np.ndarray[W_DTYPE_t, ndim=2] round_weights,
                     np.ndarray[C_DTYPE_t, ndim=1] choice_labels):
    """
    For ea. row in  `round_weights` select NUM_SELECTIONS=4 items among
    corresponding `choice_labels`, without replacement, with corresponding
    probabilities in `round_weights`.

    Args:
        round_weights (np.ndarray): 2-d array of weights, w/
            size [n_rounds, n_choices]
        choice_labels (np.ndarray): 1-d array of choice labels,
            w/ size [n_choices]; choices must be *INTEGERS*

    Returns:
        choices (np.ndarray): selected items per round, w/ size
            [n_rounds, NUM_SELECTIONS]
    """

    assert round_weights.dtype == W_DTYPE
    assert choice_labels.dtype == C_DTYPE
    assert round_weights.shape[1] == choice_labels.shape[0]

    # initialize final choices array
    cdef int n_rows = round_weights.shape[0]
    cdef np.ndarray[C_DTYPE_t, ndim=2] choices = np.zeros([n_rows, NUM_SELECTIONS],
                                                          dtype=C_DTYPE)

    # Allocate choices, per round
    cdef int i, j
    cdef bint replace = False
    for i in range(n_rows):
        choices[i] = np.random.choice(choice_labels,
                                      NUM_SELECTIONS,
                                      replace,
                                      round_weights[i])

    return choices

在与一些人聊天并检查编译后的代码后,更新此内容:@DavidW上面的评论说得很好:


“理论上是C和C对话,所以应该很快”——不,不是真的。 cimport Numpy直接访问的Numpy的主要位是 只是更快的数组索引。Numpy函数是使用 正常的Python机制。它们最终可能用C实现,但是 从Cython的观点来看,这并没有给出捷径


因此,这里的问题是,调用这个Numpy函数需要将输入转换回python对象,传入它们,然后让Numpy完成它的工作。我不认为所有的Numpy函数都是这样(从计时实验来看,其中一些我称之为工作速度非常快),但很多函数都不是“Cythonized”。

什么是
W\u DTYPE\u t
C\u DTYPE\u t
?@JérômeRichard它们被定义为接近顶部的“理论上它是C在和C说话,所以它应该很快”—不,不是真的。
cimport Numpy
提供直接访问的Numpy的主要部分是更快的数组索引。Numpy函数是使用普通Python机制调用的。它们最终可能是用C实现的,但从Cython的观点来看,这并没有给出一条捷径。