运行时生成和编译 Cython 函数



简要版本

有没有一种简单的方法可以在运行时编译 Cython 函数,给定函数的代码作为字符串?

在细节上

我有一个参数化的子程序,例如

cdef algo(x, params)
  • 该算法执行相对较少的操作,但调用频率非常高;
  • params在编译时是未知的,但在开始时是已知的(例如通过配置设置),并且在程序的整个生命周期内是固定的;
  • algo可以针对特定params进行算法优化(优化超出了编译器可以执行的操作),但是,可能的优化algo的数量非常大。

换句话说,有一个函数接收params并生成这些params的快速实现algo的代码:

def meta_algo(params):
<meta magic>
return code_of_super_fast_algo

问题是如何编译和导入由meta_algo输出定义的函数?

一个例子

假设您有一小组固定的字符串ys. 对于给定的另一个字符串x您希望计算x的最大公共前缀的长度,其中包含ys中的每个字符串,并将其作为整数数组返回。参考朴素实现:

def max_prefix(x, ys):
result = []
for i, y in enumerate(ys):
j = 0
while x[j] == y[j]:
j++
result[i] = j
return result

例如,如果知道ys字符串彼此严重交叉,则可以轻松计算比较树,但使用任何树数据结构都会引入不需要的开销。相反,人们可以在一系列if中"内联"这个树结构并生成一个有效的代码。

对于ys = ['aaa', 'aab', 'baa'],可能会得到:

cdef max_prefix(str x):
if x[0] == 'a':
if x[1] != 'a':
return [1, 1, 0]
if x[2] == 'a':
return [3, 2, 0]
elif x[2] == 'b':
return [2, 3, 0]
else:
return [2, 2, 0]
elif ...:
...

在深入挖掘 Cython 胆量后,我发现了以下池请求:

https://github.com/cython/cython/pull/555

它提供了我想要的确切功能:

code = """
cpdef int plus(int a, int b):
return a + b
"""
module = cython_inline_module(code)
plus = getattr(module, 'plus')
assert plus(1, 2) == 3

最新更新