numba @jit медленнее, чем чистый питон?

поэтому мне нужно улучшить время выполнения сценария, над которым я работаю. Я начал работать с декоратором numba jit, чтобы попробовать параллельные вычисления, но это сбивает меня с толку.

KeyError: "Does not support option: 'parallel'"

поэтому я решил протестировать nogil, если он разблокирует все возможности моего процессора, но он был медленнее, чем чистый python, я не понимаю, почему это произошло, и если кто-то может мне помочь или направить меня, я буду очень благодарен

import numpy as np
from numba import *
@jit(['float64[:,:],float64[:,:]'],'(n,m),(n,m)->(n,m)',nogil=True)
def asd(x,y):
    return x+y
u=np.random.random(100)
w=np.random.random(100)

%timeit asd(u,w)
%timeit u+w

10000 циклов, лучший из 3: 137 мкс на цикл Самый медленный запуск занял в 7,13 раза больше времени, чем самый быстрый. Это может означать, что промежуточный результат кэшируется 1000000 циклов, лучший из 3: 1,75 мкс на цикл.


person jmparejaz    schedule 18.07.2017    source источник


Ответы (1)


Вы не можете ожидать, что numba превзойдет numpy в такой простой векторизованной операции. Кроме того, ваше сравнение не совсем справедливо, поскольку функция numba включает стоимость вызова внешней функции. Если вы просуммируете больший массив, вы увидите, что производительность двух сходится, и то, что вы видите, просто накладные расходы на очень быструю операцию:

import numpy as np
import numba as nb

@nb.njit
def asd(x,y):
    return x+y

def asd2(x, y):
    return x + y

u=np.random.random(10000)
w=np.random.random(10000)

%timeit asd(u,w)
%timeit asd2(u,w)

The slowest run took 17796.43 times longer than the fastest. This could mean 
that an intermediate result is being cached.
100000 loops, best of 3: 6.06 µs per loop

The slowest run took 29.94 times longer than the fastest. This could mean that 
an intermediate result is being cached.
100000 loops, best of 3: 5.11 µs per loop

Что касается параллельной функциональности, для этой простой операции вы можете использовать nb.vectorize:

@nb.vectorize([nb.float64(nb.float64, nb.float64)], target='parallel')
def asd3(x, y):
    return x + y

u=np.random.random((100000, 10))
w=np.random.random((100000, 10))

%timeit asd(u,w)
%timeit asd2(u,w)
%timeit asd3(u,w)

Но опять же, если вы работаете с небольшими массивами, вы столкнетесь с накладными расходами на диспетчеризацию потоков. Для указанных выше размеров массива я вижу, что параллель дает мне 2-кратное ускорение.

Где numba действительно сияет, так это в выполнении операций, которые трудно выполнить в numpy с использованием широковещательной передачи, или когда операции приведут к большому количеству временных распределений промежуточного массива.

person JoshAdel    schedule 18.07.2017
comment
Привет, @JoshAdel, спасибо за ваш ответ, мой настоящий код представляет собой алгоритм оптимизации, поэтому он должен повторять одну и ту же функцию и проверять наличие улучшений, поэтому я не знаю, будут ли постоянные изменения значений аргументов и количества вложенных функций. проблема, если я векторизую наиболее выполняемую функцию. Еще раз спасибо - person jmparejaz; 18.07.2017