考虑使用以下函数计算 3 n + 1 问题的给定输入的步数:
def num_steps(b, steps):
e = b
d = 0
while True:
if e == 1:
d += steps[e]
return d
if e % 2 == 0:
e //= 2
else:
e = 3*e + 1
d += 1
在这里,
steps
存在允许结果的内存,但为了这个问题,我们只注意到只要 steps[1] == 0
,它应该没有影响,因为在这种情况下,d += steps[e]
的影响是将 0 添加到 d
.事实上,下面的例子给出了预期的结果:import numpy as np
steps = np.array([0, 0, 0, 0])
print(num_steps(3, steps)) # Prints 7
但是,如果我们使用
numba.jit
对方法进行 JIT 编译(或 njit
),我们不再得到正确的结果:import numpy as np
from numba import jit
steps = np.array([0, 0, 0, 0])
print(jit(num_steps)(3, steps)) # Prints 0
如果我们去掉看似多余的
d += steps[e]
不过,在编译该方法之前,我们确实得到了正确的结果。我们甚至可以输入 print(steps[e])
之前 d += steps[e]
并看到值为0。我也可以移动d += 1
到循环的顶部(并初始化 d = -1
代替)以获得在 Numba 情况下也有效的东西。Python 3.8(通过标准 conda channel 提供的最新版本)上的 Numba 0.48.0 (llvmlite 0.31.0) 会发生这种情况。
最佳答案
对我来说,它看起来像是一个错误,与 steps[e]
的就地增量有关。 .如果您设置 parallel=True
这就是 Numba 崩溃的地方。您可以在 Numba github repo 中创建一个问题,也许开发人员可以解释它。
如果我重写函数以避免最终的就地增量,它对我有用:
@numba.njit
def numb_steps(b, steps):
e = b
d = 0
while True:
if e == 1:
return d + steps[e]
if e % 2 == 0:
e //= 2
else:
e = 3*e + 1
d += 1
和:
python 3.7.6
numba 0.47.0
关于python - 将某种类型的 0 添加到局部变量时,Numba 抖动会改变结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60260414/