Numba:首次执行与后续执行之间的差异

时间:2018-11-20 08:40:50

标签: python numba execution-time

我刚刚开始使用numba来提高程序的性能。我减少了我要提出的案子

import numba as nb
import numpy as np
from time import time


def dt_max(U,f, eps=1e-5):
    return np.min( np.abs( U ) / ( np.abs( f ) + eps ) )

@nb.njit(cache=True)
def fast_dt_max(U,f, eps=1e-5):      
    m=U[0]
    if m<0 : m=-U[0]
    for i in range(len(U)) :
        v = abs(U[i]) / ( abs(f[i]) + eps )
        if v < m : m = v
    return m


N=100
Niter = int(1e5)

x=np.linspace(-50,50,N)

t0 = time()
for i in range(Niter):
    dt_max(x,x)
print('numpy',time()-t0)

t0 = time()
for i in range(Niter):
    fast_dt_max(x,x)
print('numba' ,time()-t0)

我在spyder中按照以下分布执行整个文件:

Python 3.5.5 |Anaconda custom (64-bit)| (default, Apr  7 2018, 04:52:34) [MSC v.1900 64 bit (AMD64)]
Type "copyright", "credits" or "license" for more information.

问题如下。当我第一次执行该程序时,它看起来工作良好:

runfile('E:/02-Codes/TestCode/Python_numba/bug_second_execution.py', wdir='E:/02-Codes/TestCode/Python_numba')
numpy 0.45239996910095215
numba 0.2964000701904297

但是当我重复执行所有文件时:

runfile('E:/02-Codes/TestCode/Python_numba/bug_second_execution.py', wdir='E:/02-Codes/TestCode/Python_numba')
numpy 0.45239996910095215
numba 3.5879998207092285

runfile('E:/02-Codes/TestCode/Python_numba/bug_second_execution.py', wdir='E:/02-Codes/TestCode/Python_numba')
numpy 0.4679999351501465
numba 3.5734000205993652

数字键盘的性能完全不同。如果我在spyder环境中重新启动Python内核,则会再次发生该问题:第一次执行是好的,而以下所有条件都不是。

第一个问题是:为什么?第二个是:如何避免这种情况?

感谢您的帮助

1 个答案:

答案 0 :(得分:1)

非常感谢Max的回答。

实际上,eps的默认值是问题的原因。如果我切换到调试模式(感谢Max提供此技巧!):

import os
os.environ['NUMBA_DEBUG_CACHE'] = '1'
import numba as nb
import numpy as np
from time import time

@nb.njit(cache=True)
def fast_dt_max(U,f, eps=1e-5):
    m=U[0]
    if m<0 : m=-U[0]
    for i in range(len(U)) :
        v = abs(U[i]) / ( abs(f[i]) + eps )
        if v < m : m = v
    return m

此代码显示每次执行时,将完成4个操作(2个加载和2个保存)。现在,如果我通过保持调试模式删除eps的默认值,则:

@nb.njit(cache=True)
def fast_dt_max(U,f, eps):
    m=U[0]
    if m<0 : m=-U[0]
    for i in range(len(U)) :
        v = abs(U[i]) / ( abs(f[i]) + eps )
        if v < m : m = v
    return m

函数的连续调用,每次执行仅出现2个操作(1个加载+ 1个保存)

结论:在numba函数中不使用默认参数值。

谢谢!