如果打印值,Numba JIT 会更改结果

Numba JIT changing results if values are printed

我今天开始使用 numba,主要是因为我有一个嵌套的 for 循环,使用常规 python 代码可能需要很长时间。

我有一个带有 llvm-3.6 的 python-2.7 的 macports 版本和 numba 的 pip 版本(一切都是最新的)

这是我使用的代码:

import pandas as pd
from numba import jit
from numpy import nan, full

@jit
def movingAverage(adj_close, maxMA):
    ma = full([len(adj_close), maxMA], nan, dtype=float64)
    ind = range( 1, len(adj_close)+1 )
    for d in ind:
        m = max( 0, d-maxMA-1)
        adj = adj_close[d-1:m:-1] if (m or d==maxMA+1) else adj_close[d-1::-1]
        cs = adj.cumsum()
        for i in range( len(adj) ):
            ma[d-1][i] = ( cs[i] / (i+1) )
        print ma
    return ma

我正在计算最多 maxMA 天的输入 adj_close 的滚动平均值。

adj_close是一组值,每天一个值

我首先创建了 ma,它是将要计算的值的容器。并单独计算每一天的值(注意第一天只能有 1 天的平均值,第二天,2 天,依此类推,直到 maxMA)

如果我输入类似 adj_close = array(range(5), dtype=float64)maxMA = 3 的内容,得到的正确答案如下:

array([[  0.,  nan,  nan],
       [  1.,   0.5,  nan],
       [  2.,   1.5,   1.],
       [  3.,   2.5,   2.],
       [  4.,   3.5,   3.]])

但是,如果我取出 print ma 行,就在我函数的 return 之前,它 return 只是答案的一部分:

array([[ nan,  nan,  nan],
       [ nan,  nan,  nan],
       [ nan,  nan,  nan],
       [  3.,   2.5,   2.],
       [  4.,   3.5,   3.]])

为什么会这样?为什么@jit 需要在这些循环之间打印才能得到正确的答案?我该怎么做才能摆脱 print 语句(这会大大增加运行时间)?


编辑:我接受@JoshAdel 的建议并在 Numba 的 github 开了一个 issue。因此,我接受@MSeifert 的回答,因为解决方法为我解决了这个问题。

我认为 numba 在这里做了一些奇怪的事情,但可能是因为混合了 pythonnopython 模式。如果我使用 Python 3.5,则 return 与 print.

相同

For python 2.7 我认为问题是因为 for 循环是在 nopython 模式(无打印)或 python 模式(有打印)下编译的。但是当它退出循环时转换为 python 。但这只是猜测。但我试过:

import pandas as pd
from numba import jit
from numpy import nan, full
import numpy as np

@jit
def movingAverage(adj_close, maxMA):
    ma = full([len(adj_close), maxMA], nan, dtype=np.float64)
    ind = range( 1, len(adj_close)+1 )
    for d in ind:
        m = max( 0, d-maxMA-1)
        adj = adj_close[d-1:m:-1] if (m or d==maxMA+1) else adj_close[d-1::-1]
        cs = adj.cumsum()
        for i in range( len(adj) ):
            ma[d-1][i] = ( cs[i] / (i+1) )
        if d == ind[-1]:
            return ma # notice that I return it after the last loop but before the loop terminates.
    #return ma

确实如此 return:

array([[  0.,  nan,  nan],
       [  1.,   0.5,  nan],
       [  2.,   1.5,   1.],
       [  3.,   2.5,   2.],
       [  4.,   3.5,   3.]])

然而,由于 len(adj_close)+1 的重新计算,这不是一个非常有效的方法。这可以存储在某个地方。