Jas*_*n S 8 python jit pypy numba
有没有办法使用pypy只是为了编译一个函数而不是我的python程序的其余部分?
我有一个已知的瓶颈,我花了99%的CPU时间(主要包含整数移位和XOR)并在Python中尽可能地优化它.除非绝对必要,否则我不想编写和维护C库.
现在我正在使用Anaconda Python,这是一个普通的python,有很多库.我会使用pypy,除非我不想确保我的所有程序的其余部分都能正常工作.
有没有办法只在一个Python函数上显式运行JIT?
编辑:该函数是GF2(Galois字段)中的模块化乘法步骤
特别:
def _gf2mulmod(x,y,m):
z = 0
while x > 0:
if (x & 1) != 0:
z ^= y
y <<= 1
y2 = y ^ m
if y2 < y:
y = y2
x >>= 1
return z
Run Code Online (Sandbox Code Playgroud)
它需要为bigints工作,所以我不确定如何重写为Cython兼容.
我刚刚尝试了numba的@autojit,但它失败了,因为它不知道要使用哪些变量类型并假设小整数.我似乎无法弄清楚如何告诉它使用标准的Python bigints.
Traceback (most recent call last):
File "/Users/jason_s/Documents/python/libgf2/src/libgf2/gf2.py", line 440, in <module>
dlog43 = GF2DiscreteLog(0x100000000065)
File "/Users/jason_s/Documents/python/libgf2/src/libgf2/gf2.py", line 295, in __init__
factors = _calculateFactors(poly)
File "/Users/jason_s/Documents/python/libgf2/src/libgf2/gf2.py", line 264, in _calculateFactors
if (e1 << m).value != 1:
File "/Users/jason_s/Documents/python/libgf2/src/libgf2/gf2.py", line 379, in __lshift__
return self._wrapraw(_gf2lshiftmod(self.value,k,self.poly))
File "/Users/jason_s/Documents/python/libgf2/src/libgf2/gf2.py", line 195, in _gf2lshiftmod
return _gf2mulmod(x,_gf2powmod(2,k,m),m)
File "/Users/jason_s/Documents/python/libgf2/src/libgf2/gf2.py", line 189, in _gf2powmod
z = _gf2mulmod(z,x,m)
File "numbawrapper.pyx", line 193, in numba.numbawrapper._NumbaSpecializingWrapper.__call__ (numba/numbawrapper.c:3764)
OverflowError: value too large to convert to signed int
Run Code Online (Sandbox Code Playgroud)
小智 6
不,你不能在PyPy和另一个Python的其他部分中运行Python程序的一部分 - 它不仅仅是一个JIT,它有一个完全不同的对象和许多其他内部表示.
如果您唯一关心的是不想确保程序的其余部分与PyPy一起使用,请放心:几乎所有纯Python代码都与PyPy一起使用,唯一的例外是CPython实现细节.这些都是模糊的,很难意外地编写依赖于大多数代码的代码,而其他代码(例如文件没有被及时自动关闭)不会破坏大多数程序.试试用PyPy运行整个程序.
如果PyPy存在其他问题,您可能只想将此函数转换为C并使用ctypes或调用它cffi.烦人的部分是用Python挂钩(例如通过扩展模块),这是什么ctypes和cffi对你来说做.您不需要完整的仲裁精度整数库,只需要一个具有一些非常简单操作的位数组:测试最低有效位,左/右移位,小于和按位异或.每个都只是一个微不足道的循环.如果天真的C实现仍然是瓶颈,你可以对所有这些循环进行矢量化.您也可以优化班次以避免复制任何内容.