Python 如果打印了值,则会更改JIT结果

Python 如果打印了值,则会更改JIT结果,python,numpy,jit,numba,Python,Numpy,Jit,Numba,我今天开始使用numba,主要是因为我有一个嵌套的for循环,使用常规python代码可能需要很长时间 我有一个macports版本的python-2.7和llvm-3.6,还有一个pip版本的numba(一切都是最新的) 以下是我正在使用的代码: import pandas as pd from numba import jit from numpy import nan, full @jit def movingAverage(adj_close, maxMA): ma = ful

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

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

以下是我正在使用的代码:

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
我正在计算输入
adj_close
最多
maxMA
天的滚动平均值

adj_close
是一个值数组,每天一个值

我首先创建了
ma
,一个将要计算的值的持有者。并分别计算出每天的VAULE(注意,第一天的平均值只能包括1天、第二天、2天,以此类推,直至最大值)

如果我输入类似于
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
行,它只返回部分答案:

array([[ nan,  nan,  nan],
       [ nan,  nan,  nan],
       [ nan,  nan,  nan],
       [  3.,   2.5,   2.],
       [  4.,   3.5,   3.]])
为什么会这样?为什么@jit需要在这些循环之间打印才能得到正确的答案?我能做些什么来摆脱print语句(这大大增加了运行时间)



编辑:我接受了@JoshAdel的建议,并在Numba的github开了一个网站。因此,我接受@MSeifert answer作为解决问题的方法。

我认为
numba
在这里做了一些奇怪的事情,但可能是因为
python
nopython
模式的混合。如果我使用Python3.5,则返回值与使用和不使用
print
的返回值相同

对于Python2.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
它确实返回:

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

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

在我看来像个bug。我想在github上发布一些关于Numba问题的文章,因为您有一个演示这个问题的最小示例。不幸的是,我在运行它时得到了正确的答案(Python3,可能还有一个不同版本的Numba)。但是,我想知道将索引行更改为
ma[d-1,I]=…
是否会有所帮助。我认为@MSeifert对python与nopython模式的比较是正确的,我记得nopython模式不能很好地处理顺序(即
[a][b]
)索引。如果d==len(adj_close)+1:我可以使用
如果d==ind[-1]
来获得相同的结果,而无需重新计算,我已经编辑了答案,我不知道这样的列表查找是否比计算快,但它看起来更快,尤其是对于小输入。对于
len(adj_close)
maxMA=1000
,典型值的顺序是200.000。为此,如果d==ind[-1](与在其他地方存储相同),则使用
运行需要16分钟,如果d==len(adj_close)+1运行需要20分钟