【发布时间】:2013-04-08 09:16:03
【问题描述】:
我正在尝试在 Cython 中进行严重依赖于一些 numpy/scipy 数学函数(如 numpy.log)的计算。我注意到如果我在 Cython 中循环调用 numpy/scipy 函数,会产生巨大的间接成本,例如:
import numpy as np
cimport numpy as np
np.import_array()
cimport cython
def myloop(int num_elts):
cdef double value = 0
for n in xrange(num_elts):
# call numpy function
value = np.log(2)
这是非常昂贵的,大概是因为np.log通过Python而不是直接调用numpy C函数。如果我将该行替换为:
from libc.math cimport log
...
# calling libc function 'log'
value = log(2)
然后它会快得多。但是,当我尝试将 numpy 数组传递给 libc.math.log 时:
cdef np.ndarray[long, ndim=1] foo = np.array([1, 2, 3])
log(foo)
它给出了这个错误:
TypeError: only length-1 arrays can be converted to Python scalars
我的问题是:
- 是否可以调用 C 函数并将其传递给 numpy 数组?或者它只能用于标量值,这需要我编写一个循环(例如,如果我想将它应用到上面的
foo数组。) - 是否有类似的方法可以直接从 C 调用 scipy 函数而无需 Python 开销?如何导入 scipy 的 C 函数库?
具体示例:假设您想在 Cython 的 for 循环内的标量值上调用许多 scipy 或 numpy 的有用统计函数(例如 scipy.stats.*)?在 Cython 中重新实现所有这些函数太疯狂了,因此必须调用它们的 C 版本。例如,所有与 pdf/cdf 相关的函数以及来自各种统计分布的采样(例如,请参阅 http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.rv_continuous.pdf.html#scipy.stats.rv_continuous.pdf 和 http://www.johndcook.com/distributions_scipy.html)如果您在循环中使用 Python 开销调用这些函数,它会非常慢。
谢谢。
【问题讨论】:
-
scipy.statspdf等函数主要用Python实现。您可以通过一次处理多个数字来避免开销。 -
我刚刚发现这篇文章,因为我有一个非常相似的问题。我已经对我的循环进行了 cythonized 处理,但是循环中有 numpy 和 scipy 调用,所以我没有看到默认 Python 有任何加速。看到重写 numpy 和 scipy 函数是不切实际的,这似乎让 cython 的价值主张没有我最初希望的那么有吸引力。
标签: python optimization numpy scipy cython