python如何调用math函数库函数_如何直接从Cython调用numpy / scipy C函数,而没有Python调用开销?...

1586010002-jmsa.png

I am trying to make calculations in Cython that rely heavily on some numpy/scipy mathematical functions like numpy.log. I noticed that if I call numpy/scipy functions repeatedly in a loop in Cython, there are huge overhead costs, e.g.:

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)

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)

then it's much faster. However, when I try to pass a numpy array to libc.math.log:

cdef np.ndarray[long, ndim=1] foo = np.array([1, 2, 3])

log(foo)

it gives this error:

TypeError: only length-1 arrays can be converted to Python scalars

My questions are:

Is it possible to call the C function and pass it a numpy array? Or can it only be used on scalar values, which would require me to write a loop (eg if I wanted to apply it to the foo array above.)

Is there an analogous way to call scipy functions from C directly without a Python overhead? Which how can I import scipy's C function library?

Concrete example: say you want to call many of scipy's or numpy's useful statistics functions (e.g. scipy.stats.*) on scalar values inside a for loop in Cython? It's crazy to reimplement all those functions in Cython, so their C versions have to be called. For example, all the functions related to pdf/cdf and sampling from various statistical distributions (e.g. see http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.rv_continuous.pdf.html#scipy.stats.rv_continuous.pdf and http://www.johndcook.com/distributions_scipy.html) If you call these functions with Python overhead in a loop, it'll be prohibitively slow.

thanks.

解决方案

You cannot apply C functions such as log on numpy arrays, and numpy does not have a C function library that you can call from cython.

Numpy functions are already optimized to be called on numpy arrays. Unless you have a very unique use case, you're not going to see much benefit from reimplementing numpy functions as C functions. (It's possible that some functions in numpy are not implemented well, in chich case consider submitting your importations as patches.) However you do bring up a good point.

# A

from libc.math cimport log

for i in range(N):

r[i] = log(foo[i])

# B

r = np.log(foo)

# C

for i in range(n):

r[i] = np.log(foo[i])

In general, A and B should have similar run times, but C should be avoided and will be much slower.

Update

Here is the code for scipy.stats.norm.pdf, as you can see it's written in python with numpy and scipy calls. There is no C version of this code, you have to call it "through python". If this is what is holding you back, you'll need to re-implant it in C/Cython, but first I would spend some time very carefully profiling the code to see if there are any lower hanging fruit to go after first.

def pdf(self,x,*args,**kwds):

loc,scale=map(kwds.get,['loc','scale'])

args, loc, scale = self._fix_loc_scale(args, loc, scale)

x,loc,scale = map(asarray,(x,loc,scale))

args = tuple(map(asarray,args))

x = asarray((x-loc)*1.0/scale)

cond0 = self._argcheck(*args) & (scale > 0)

cond1 = (scale > 0) & (x >= self.a) & (x <= self.b)

cond = cond0 & cond1

output = zeros(shape(cond),'d')

putmask(output,(1-cond0)+np.isnan(x),self.badvalue)

if any(cond):

goodargs = argsreduce(cond, *((x,)+args+(scale,)))

scale, goodargs = goodargs[-1], goodargs[:-1]

place(output,cond,self._pdf(*goodargs) / scale)

if output.ndim == 0:

return output[()]

return output

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值