我正在尝试驯化
numba
cfunc
编译器;)
这是我的 base_model.py 文件(我的函数的来源)。
import numpy
import numba
import numba.pycc
cc = numba.pycc.CC('base_model')
cc.verbose = True
@cc.export('cumulativeMin','float64[:](float64[:])')
def cumulativeMin(A):
r = numpy.empty(len(A))
t = numpy.inf
for i in range(len(A)):
t = numpy.minimum(t, A[i])
r[i] = t
return r
if __name__ == "__main__":
cc.compile()
然后我这样做(在终端中,我运行 ubuntu):
$ python3 base_module.py
base_model.py:3: NumbaPendingDeprecationWarning: The 'pycc' module is pending deprecation. Replacement technology is being developed.
Pending Deprecation in Numba 0.57.0. For more information please see: https://numba.readthedocs.io/en/stable/reference/deprecation.html#deprecation-of-the-numba-pycc-module
import numba.pycc
然后我就这样做(用Python):
import numpy
import ctypes
mylib = ctypes.cdll.LoadLibrary('./base_model.cpython-310-x86_64-linux-gnu.so')
array = numpy.random.uniform(-1,0,1000)
mylib.cumulativeMin(array)
然后我收到此错误:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[1], line 7
5 mylib = ctypes.cdll.LoadLibrary('./base_model.cpython-310-x86_64-linux-gnu.so')
6 array = numpy.random.uniform(-1,0,1000)
----> 7 mylib.cumulativeMin(array)
File /usr/lib/python3.10/ctypes/__init__.py:387, in CDLL.__getattr__(self, name)
385 if name.startswith('__') and name.endswith('__'):
386 raise AttributeError(name)
--> 387 func = self.__getitem__(name)
388 setattr(self, name, func)
389 return func
File /usr/lib/python3.10/ctypes/__init__.py:392, in CDLL.__getitem__(self, name_or_ordinal)
391 def __getitem__(self, name_or_ordinal):
--> 392 func = self._FuncPtr((name_or_ordinal, self))
393 if not isinstance(name_or_ordinal, int):
394 func.__name__ = name_or_ordinal
AttributeError: ./base_model.cpython-310-x86_64-linux-gnu.so: undefined symbol: cumulativeMin
#编辑:
我希望提前编译这个函数(cumulativeMin)(https://numba.pydata.org/numba-doc/dev/user/pycc.html)。
这不是您应该导入 numba/pycc 生成的代码的方式。
ctypes
用于使用外部库,不是为 python 编译的。
当然,它的构建更简单(尤其是对于 C 程序员来说。您只需像平常一样编写 C 代码,而不关心 python,并让 ctypes(在显式包装的帮助下)处理它)。您甚至可以使用任何已存在的 .so ,而不是出于该目的编写的。但也不太确定。只要给出错误的参数,你就很容易出现段错误。而且你必须自己管理C世界的内存。并且不能直接弄乱 python 数据。
这是 cpython 扩展。所以“纯Python”函数是用C 编写的,如果我可以使用这个矛盾的话。使用 python 内存管理(垃圾收集器)来创建 python 数据的函数。 更难编写,因为您必须读取和写入 python 内部数据格式(当然使用提供的 python API)。 但当然,无论如何,生成代码时都是更好的选择。
无论标准是什么,无论如何,要点是,它是一个 python 模块,应该在 python 代码中导入,可以访问 cpython api。
长话短说:
import base_model
base_model.cumulativeMin(...)
这是你应该使用它的方式。
因为我的答案是,我很确定,不明白,所以我更明确地表达它(即使这主要是通过重复问题)
我所做的是
创建
MySource.py
文件
import numpy
import numba
import numba.pycc
cc = numba.pycc.CC('base_model')
cc.verbose = True
@cc.export('cumulativeMin','float64[:](float64[:])')
def cumulativeMin(A):
r = numpy.empty(len(A))
t = numpy.inf
for i in range(len(A)):
t = numpy.minimum(t, A[i])
r[i] = t
return r
if __name__ == "__main__":
cc.compile()
然后我这样做(在终端中,我运行 ubuntu):
$ python3 MySource.py
MySource.py:3: NumbaPendingDeprecationWarning: The 'pycc' module is pending deprecation. Replacement technology is being developed.
Pending Deprecation in Numba 0.57.0. For more information please see: https://numba.readthedocs.io/en/stable/reference/deprecation.html#deprecation-of-the-numba-pycc-module
import numba.pycc
然后我就这样做(用Python):
import numpy
import base_model
array = numpy.random.uniform(-1,0,1000)
base_model.cumulativeMin(array)
我没有收到错误,但结果
array([-0.00492896, -0.80422352, -0.80422352, -0.80422352, -0.80422352,
-0.80422352, -0.8844663 , -0.8844663 , -0.8844663 , -0.8844663 ,
-0.8844663 , -0.90776422, -0.90776422, -0.90776422, -0.90776422,
...
-0.99972223, -0.99972223, -0.99972223, -0.99972223, -0.99972223,
-0.99972223, -0.99972223, -0.99972223, -0.99972223, -0.99972223])
请注意,除了我的主要答案之外(不要使用 ctypes 加载它,而是使用 import 加载它),我在答案中只更改了一件事:我更改了源文件的名称,从
base_model.py
到 mySource.py
。
澄清一点:这里 import base_model
导入的是 .so
而不是 .py
文件。它是加载的编译文件。