【发布时间】:2015-04-22 11:12:13
【问题描述】:
编辑:这个问题已经严重过时了! numba 现在支持开箱即用的Enum 和namedtuple,它们都为分组常量提供了合理的解决方案。
我正在 python 中进行一些位移,并希望使用 numba 加速它。为此,我有很多常量整数值,我必须以一种可能易于阅读的方式处理它们。我想将它们组合在一起成为类似枚举的对象,将所有常量都放在一个命名空间中,可以通过属性获取运算符进行访问。当然我也希望 numba 了解那里发生的事情,以便它可以通过 jit 编译保持高速。我的第一次也是最天真的尝试是这样的:
class SomeConstantsContainer:
SOME_NAME = 0x1
SOME_OTHER_CONSTANT = 0x2
AND_ANOTHER_CONSTANT = 0x4
不幸的是,当我查看注释时,看起来 numba 不理解值是恒定的,并且它总是退回到对 python 对象的缓慢对象访问。这就是注释所说的:
# $29.2 = global(SomeConstantsContainer: <class 'constants.SomeConstantContainer'>) :: pyobject
# $29.3 = getattr(attr=SOME_VARIABLE, value=$29.2) :: pyobject
我知道我总是可以退回到这样的事情:
from numpy import np
SOME_STUPID_CONSTANT = np.int64(0x1)
ANOTHER_STUPID_CONSTANT = np.int64(0x2)
在这种情况下,jit 编译器 a) 不需要查找容器的属性 b) 肯定知道它必须处理一个纯整数。这样写简直丑到令人难以置信。我可以忍受将所有常量显式标记为整数,或者让容器这样做。尽管如此,为了清楚起见,我真的很想将常量分组在容器中,并且 jit 编译的版本理解语法,而不是浪费时间在每次使用常量时进行一些缓慢的 python 属性查找。任何更好的想法,如何使第二种方法更像第一种方法,但保持高执行速度?是否有一些 numba 理解的枚举容器,我只是错过了?
编辑:
同样使用新的enum 容器也无济于事:
@enum.unique
class SomeConstantsContainer(enum.IntEnum):
SOME_NAME = 0x1
SOME_OTHER_CONSTANT = 0x2
AND_ANOTHER_CONSTANT = 0x4
这给出了:
# $42.3 = global(SomeConstantsContainer: <enum 'SomeConstantsContainer'>) :: pyobject
# $42.4 = getattr(attr=SOME_OTHER_CONSTANT, value=$42.3) :: pyobject
【问题讨论】:
-
很不清楚你在问什么。您是否试图在发出的 C/机器代码中将这些变量表示为
const值?如果是这样,为什么?您无法在 Python 级别验证 const 正确性,因此这可能没有意义。也就是说,如果这些作为类属性存在,就像在您的示例代码中一样,那么任何人都可以在 Python before 中随时修改它们,并且调度 JIT 编译的函数调用。在 C 级别做 const-correctness 不会给你带来任何好处,我知道(但会对反例非常感兴趣)。 -
我希望它们不是作为 python 对象被识别和处理,而是作为整数常量。我还希望 jit 编译器能够刮掉容器对象上的属性查找。
-
注意:这个问题现在已经严重过时了。 numba 现在支持
Enums 和namedtuples,它们都提供了更优雅的方式来回答这个问题。
标签: python enums constants numba