我正在尝试用cython编程一个函数来进行蒙特卡罗模拟。该函数涉及多个小的线性代数运算,如点积和矩阵求逆。由于该功能被称为成千上万次,所以numpy开销占了很大一部分成本。 三年前,有人问过这个问题:calling dot products and linear algebra operations in Cython? 我试图使用两个答案的建议,但第一个scipy.linalg.blas仍然通过一个python包装器,我没有真正得到任何改进。第二种,使用gsl包装器也相当慢,当向量的尺寸非常大时,往往会冻结我的系统。我还发现了Ceygen软件包,看起来非常有前途,但似乎安装文件在最后一次Cython更新中破了。 另一方面,我看到scipy正在使用一个用于lapack的cython包装器,但它看起来仍然不可用(scipy-cython-lapack) 最后,我还可以为这些操作编写自己的C例程,但它似乎有点重新发明轮子。
总结一下:在Cython中有这种操作的新方法吗? (因此我不认为这是重复的)或者您是否找到了一种更好的方法来处理我还没有看到的这类问题?
强制性代码示例: (这只是一个例子,当然它仍然可以改进,但只是为了提出这个想法)
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:如何在cython中使用线性代数?
答案 0 :(得分:1)
答案you link to仍然是从Cython调用BLAS函数的好方法。它实际上不是一个python包装器,仅仅使用Python,因此获取指向该函数的C指针,这可以在初始化时完成。所以你应该得到基本上类似C的速度。我可能是错的,但我认为即将推出的Scipy 0.16版本将提供一个方便的BLAS Cython API,基于这种方法,它不会改变性能方面。
如果你在重复调用BLAS函数移植到Cython之后没有经历任何加速,那么在numpy中执行此操作的python开销并不重要(例如,如果计算本身是最昂贵的部分)或者你做错了(不必要的记忆副本等)。
我想说这种方法应该比使用GSL更快更容易维护,前提是您使用优化的BLAS(OpenBLAS,ATLAS,MKL等)编译scipy。
答案 1 :(得分:0)
作为einsum
补丁的一部分,我编写了函数c
代码的Python模拟。当我在Python中解析字符串时,我使用cython
来编写产品总和计算。
pyx
位于https://github.com/hpaulj/numpy-einsum/blob/master/sop.pyx
您甚至可以通过Python调用来调用compile einsum
模块。比较np.dot
和np.einsum
有很多SO问题,这对于不同的计算更好。
http://docs.cython.org/src/userguide/memoryviews.html
另请参阅cython
memoryviews
- 您可以使用这些或cython数组,就像使用numpy
数组一样。例如,此文档提到您可以使用[None,:]
添加维度。这是否意味着您可以通过广播来制作常见的numpy
外部产品?