我正试图在cython中为蒙特卡罗模拟编程一个函数。该函数涉及多个小的线性代数运算,如点积和矩阵逆。当函数被调用数十万次时,numpy开销占成本的很大一部分。三年前有人问了这个问题:在Cython中调用点积和线性代数运算?我尝试使用了两个答案中的建议,但是第一个scipy. linalg2 .blas仍然要经过一个python包装器,而且我并没有真正得到任何改进。第二,使用gsl包装器也相当慢,并且当向量的维度非常大时,往往会冻结我的系统。我还找到了Ceygen包,看起来非常有前途,但似乎安装文件在上次Cython更新中损坏了。另一方面,我看到scipy正在为lapack开发cython包装器,但它看起来仍然不可用(scipy-cython-lapack)。最后,我还可以为这些操作编写自己的C例程,但这似乎是重新发明轮子。
总结一下:在Cython中是否有new方法来完成这类操作?(所以我不认为这是重复的)或者你有更好的方法来处理这类问题,我还没有看到?
强制性代码示例:(这只是一个例子,当然它仍然可以改进,但只是给出一个想法)
cimport numpy as np
import numpy as np
cpdef double risk(np.ndarray[double, ndim=2, mode='c'] X,
np.ndarray[double, ndim=1, mode='c'] v1,
np.ndarray[double, ndim=1, mode='c'] v2):
cdef np.ndarray[double, ndim=2, mode='c'] tmp, sumX
cdef double ret
tmp = np.exp(X)
sumX = np.tile(np.sum(tmp, 1).reshape(-1, 1), (1, tmp.shape[0]))
tmp = tmp / sumX
ret = np.inner(v1, np.dot(X, v2))
return ret
谢谢! !
tl;dr: how-to linear algebra in cython?
您链接到的答案仍然是从Cython调用BLAS函数的好方法。它不是真正的python包装器,python只是用来获取指向函数的C指针,这可以在初始化时完成。所以你应该得到c型的速度。我可能是错的,但我认为即将发布的Scipy 0.16版本将提供一个方便的BLAS cythapi,基于这种方法,它不会改变性能方面的事情。
如果你在移植到Cython后没有体验到重复调用BLAS函数的任何速度提升,要么在numpy中执行此操作的python开销无关紧要(例如,如果计算本身是最昂贵的部分),要么你做错了什么(不必要的内存拷贝等)
我想说,这种方法应该比使用GSL更快,更容易维护,当然前提是您使用优化的BLAS (OpenBLAS, ATLAS, MKL等)编译scipy。
作为einsum
补丁的一部分,我编写了该函数c
代码的Python模拟。当我在Python中解析字符串时,我使用cython
来编写乘积和计算。
pyx
在https://github.com/hpaulj/numpy-einsum/blob/master/sop.pyx
您甚至可以通过Python调用来调用compile einsum
模块。比较np.dot
和np.einsum
有许多SO问题,它们更适合不同的计算。
也看看cython
memoryviews
-你可能能够使用这些,或cython数组,就像你会numpy
数组。例如,本文档提到可以使用[None,:]
添加维度。这是否意味着你可以通过广播来做常见的numpy
外部产品?