python - 将某种类型的 0 添加到局部变量时,Numba 抖动会改变结果

标签 python numpy jit numba collatz

考虑使用以下函数计算 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/

相关文章:

python - 在条件下向前填充列

python - 为什么我的 numpy 构造忽略元组解构?

clang - LLVM jit 和 native

java - JVM JIT 是否生成系统调用指令?

python - 未绑定(bind)本地错误: local variable 'fullfilename' referenced before assignment

Python Pandas - 如果某些值为空则合并行

java - 是否可以在一个网站上使用多种编程语言

python - 除了一个维度外,所有维度上的归约运算

python - 根据索引和条件更改 numpy 数组中的值

dart - 如何在关闭 JIT 的情况下以解释器模式运行 Dart VM?