Cython 中用于循环调用的快速基本线性代数

BVJ*_*BVJ 5 python numpy cython scipy

我正在尝试在 cython 中编写一个用于蒙特卡罗模拟的函数。该函数涉及多个小的线性代数运算,如点积和矩阵求逆。随着函数被调用数十万次,numpy 开销占据了很大一部分成本。三年前有人问过这个问题:在 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
Run Code Online (Sandbox Code Playgroud)

谢谢!!

tl;dr:如何在 cython 中学习线性代数?

rth*_*rth 1

您链接到的答案仍然是从 Cython 调用 BLAS 函数的好方法。它并不是真正的 Python 包装器,只是使用 Python,因此获取指向该函数的 C 指针,这可以在初始化时完成。所以你应该获得基本上类似 C 的速度。我可能是错的,但我认为即将发布的 Scipy 0.16 版本将提供方便的 BLAS Cython API,基于这种方法,它不会改变性能。

如果您在重复调用 BLAS 函数移植到 Cython 后没有体验到任何加速,则在 numpy 中执行此操作的 Python 开销并不重要(例如,如果计算本身是最昂贵的部分),或者您做错了什么(不必要的内存副本等)

我想说,这种方法应该比 GSL 更快、更容易维护,当然前提是您使用优化的 BLAS(OpenBLAS、ATLAS、MKL 等)编译了 scipy。

  • 你好谢谢。看来最后一部分是问题所在。我安装了 ATLAS,现在效果好多了。仅仅制作一个矩阵乘积似乎就需要相当多的工作,因此 scipy BLAS Cython API 可以节省大量工作。顺便说一句,我使用东京的免验证功能得到了非常相似的结果,所以对于那些只需要简单操作的人来说,它绝对更容易使用。 (2认同)