我刚刚开始使用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内核,则会再次发生该问题:第一次执行是好的,而以下所有条件都不是。
第一个问题是:为什么?第二个是:如何避免这种情况?
感谢您的帮助
答案 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函数中不使用默认参数值。
谢谢!