我正在尝试在Cython中进行计算,这些计算严重依赖于一些像numpy.log
这样的numpy/scipy数学函数。我注意到,如果我在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 函数。如果我将那一行替换为:
This is very expensive, presumably because np.log
goes through Python rather than calling the numpy C function directly. If I replace that line with:
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.*
),重新实现所有这些函数是疯狂的,因此必须调用它们的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.stats
的概率密度函数等函数主要是用 Python 实现的。你可以通过一次处理多个数字来避免开销。 - pv.