如何通过llvmlite在Numba即时编译代码中调用Numpy原生排序C API(PyArray_Sort)并实现跨会话稳定缓存?
如何通过llvmlite在Numba即时编译代码中调用Numpy原生排序C API(PyArray_Sort)并实现跨会话稳定缓存?
这是我对之前问题的跟进:如何在带持久磁盘缓存的Numba即时编译代码中封装Numpy函数?
背景
一般来说,Numba对Numpy函数的实现效率很高,但像numpy.sort()这类函数是例外。我希望在Numba流水线中使用Numpy原生的排序功能(即numpy.sort),目标是在多个Python会话中能稳定、带缓存地调用底层的C API排序函数。
Numpy中对应ndarray.sort的排序C API定义为:
PyObject *PyArray_Sort(PyArrayObject *self, int axis, NPY_SORTKIND kind)
该函数在Numpy官方C API文档中关于数组项选择与操作的章节有说明。
我想到的一个潜在解决方案是使用llvmlite.binding.load_library_permanently来稳定加载Numpy扩展库multiarray_umath,这样指向PyArray_Sort的C函数指针就能保持稳定。
不过这个思路可能存在两个待解决的问题:
PyArray_Sort必须作为公共符号暴露,但目前看起来并非如此;PyArray_Sort使用的类型(如PyObject、PyArrayObject)在定义C函数签名时可能无法直接获取。
请问是否有可能从外部即时编译的代码中访问Numpy原生的排序函数?我对C++内部机制和Numpy构建系统的经验有限,任何见解、变通方案或建议都将不胜感激!
感谢您的时间!
以下是我尝试但未成功的代码:
import numpy as np from numpy._core import _multiarray_umath as multiarray_umath from numba import njit from numba.core import types, typing from llvmlite.binding import load_library_permanently, address_of_symbol # 稳定加载Numpy扩展库 np_library_path = multiarray_umath.__file__ load_library_permanently(np_library_path) # 检查符号是否公开并能找到地址 np_fn_name = 'PyArray_Sort' # 问题1:'PyArray_Sort'不是公共符号 func_addr = address_of_symbol(np_fn_name) if func_addr is None: raise RuntimeError(f"Could not find symbol {np_fn_name}") print(f"Address of {np_fn_name}:", hex(func_addr)) # >>> 这里会抛出RuntimeError,因为符号未公开 # 问题2:定义C函数签名时是否有匹配的类型可用? # >>> PyObject的返回类型该如何定义? return_type = types.pyobject # >>> PyArrayObject的参数类型该如何定义? arg_types = (types.pyobject, types.int64, types.int64) np_fn_signature = typing.signature(return_type, *arg_types) pyarray_sort = types.ExternalFunction(np_fn_name, np_fn_signature) @njit(cache=True) def wrapped_numpy_sort(arr, axis, kind): return pyarray_sort(arr, axis, kind)
备注:内容来源于stack exchange,提问作者Olibarer
相关产品推荐
相关产品推荐

