Numba: разница между первым и последующим исполнением - PullRequest
0 голосов
/ 20 ноября 2018

Я только начал использовать 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

Производительность numba не одинаковасовсем.Если я перезапущу ядро ​​Python в моей среде spyder, проблема снова возникнет: первое выполнение - это хорошо, а все следующее - нет.

Итак, первый вопрос: почему?и второе: как этого избежать?

Спасибо за вашу помощь

1 Ответ

0 голосов
/ 20 ноября 2018

Большое спасибо Макс за ответ.

Действительно, значение по умолчанию для eps является причиной проблемы.Если я переключаюсь в режим отладки (спасибо Максу за подсказки!):

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.

Спасибо!

...