【问题标题】:Cython calling lapack, error: `Cannot take address of Python variable'Cython 调用 lapack,错误:“无法获取 Python 变量的地址”
【发布时间】:2014-11-10 06:14:21
【问题描述】:

我的问题与here 提出的问题非常相似,因此我正在尝试实现那里的答案中提出的问题,基于调用 blas 与 python 捆绑的example。我的代码只是那个 example.pyx 的一个稍微修改过的版本,这是我的相关代码(文件 f2pyptr.h 未更改):

#example.pyx (single precision linear system solver via lapack)
import numpy as np
import scipy.linalg.lapack
import cython
cimport numpy as np

cdef extern from "/(pwd)/f2pyptr.h":
void *f2py_pointer(object) except NULL

ctypedef int sgesv_t(
int *N, int *NRHS,
float *A, int* LDA,
int* IPIV,
float *B,
int *LDB,
int *INFO)

cdef sgesv_t *sgesv = <sgesv_t*>f2py_pointer(scipy.linalg.lapack.sgesv._cpointer)

def myfunc_sgesv():
  cdef int N, NRHS, LDA, LDB, INFO
  N = 10
  NRHS = 1
  LDA = 10
  LDB = 10
  cdef np.ndarray[np.float32_t, ndim=2] A = np.ones((N,N), np.float32, order = "F")
  cdef np.ndarray[np.float32_t, ndim=2] B = np.ones((N, NRHS),np.float32, order = "F")
  cdef np.ndarray[np.int_t, ndim=1] IPIV = np.empty((N,), dtype = np.int)
  sgesv(&N, &NRHS, &A[0,0], &LDA, &IPIV, &B[0,0], &LDB, &INFO)*

def myfunc_sgesv():
  cdef int N, NRHS, LDA, LDB, INFO
  N = 10
  NRHS = 1
  LDA = 10
  LDB = 10

  cdef np.ndarray[np.float32_t, ndim=2] A = np.ones((N,N), np.float32, order = "F")
  cdef np.ndarray[np.float32_t, ndim=2] B = np.ones((N, NRHS),np.float32, order = "F")
  cdef np.ndarray[np.int_t, ndim=1] IPIV = np.empty((N,), dtype = np.int)

  sgesv(&N, &NRHS, &A[0,0], &LDA, &IPIV, &B[0,0], &LDB, &INFO)

使用标准的 setup.py 文件,我调用 python setup.py build_ext --inplace

导致

Compiling example.pyx because it changed.
Cythonizing example.pyx

Error compiling Cython file:
------------------------------------------------------------
...

    cdef np.ndarray[np.float32_t, ndim=2] A = np.ones((N,N), np.float32, order = "F")
    cdef np.ndarray[np.float32_t, ndim=2] B = np.ones((N, NRHS),np.float32, order = "F")
    cdef np.ndarray[np.int_t, ndim=1] IPIV = np.empty((N,), dtype = np.int)

    sgesv(&N, &NRHS, &A[0,0], &LDA, &IPIV, &B[0,0], &LDB, &INFO)
                            ^
------------------------------------------------------------

example.pyx:103:33: Cannot take address of Python variable
Traceback (most recent call last):
File "setup.py", line 5, in <module>
ext_modules = cythonize("example.pyx")
File "/idiap/home/jnewling/.local/lib/python2.7/site-packages/Cython-0.20.1/Cython/Buil/Dependencies.py", line 785, in cythonize
cythonize_one(*args[1:]) File "/idiap/home/jnewling/.local/lib/python2.7/site-packages/Cython-0.20.1/Cython/Buil/Dependencies.py", line 902, in cythonize_one raise CompileError(None, pyx_file) Cython.Compiler.Errors.CompileError: example.pyx

我的原始 example.pyx 运行良好,以及修改后的单精度版本(即 sgemm),因此无法理解为什么我的 sgesv 实现失败。

非常欢迎任何具体的诊断或替代方法的建议。

【问题讨论】:

  • 您可能想看看这个repository。您应该能够安装它,然后从中 cimport 。唯一的问题是,在您的设置文件中,您必须添加包含头文件和 cython pxd 文件的安装目录。

标签: python cython lapack blas


【解决方案1】:

不确定这个答案是否正确,但我会告诉你我的尝试,因为它可能会对你有所帮助:

编译您的代码时,我在不同的地方收到了错误Cannot take address of Python variable。我在&amp; IPIV 收到错误消息。然后我注意到它是一个数组,所以我将其更改为:

sgesv(&amp;N, &amp;NRHS, &amp;A[0,0], &amp;LDA, &amp;IPIV[0], &amp;B[0,0], &amp;LDB, &amp;INFO)。然后我得到了错误 Cannot assign type 'int_t *' to 'int *' 。然后找到下面的答案:Passing numpy integer array to c code 并将代码改为:

cdef np.ndarray[int, ndim=1, mode='c'] IPIV = np.empty((N,), dtype = ctypes.c_int) sgesv(&N, &NRHS, &A[0,0], &LDA, &IPIV[0], &B[0,0], &LDB, &INFO)

现在它编译没有任何错误。

【讨论】:

  • 完美答案!奇怪的是 ^ 不在 & IPIV 之下,但如果我数了 33 个字符,它就会在 & IPIV 之下,我会(我愿意相信)发现粗心的错误。第二个编译错误看起来更糟糕,谢谢你也节省了我诊断的时间!
猜你喜欢
  • 2020-05-27
  • 1970-01-01
  • 2016-03-07
  • 1970-01-01
  • 2020-02-24
  • 2015-02-23
  • 2010-09-23
  • 2014-07-25
相关资源
最近更新 更多