如果打印值,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
在这里做了一些奇怪的事情,但可能是因为混合了 python
和 nopython
模式。如果我使用 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
的重新计算,这不是一个非常有效的方法。这可以存储在某个地方。
我今天开始使用 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
在这里做了一些奇怪的事情,但可能是因为混合了 python
和 nopython
模式。如果我使用 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
的重新计算,这不是一个非常有效的方法。这可以存储在某个地方。