Могу ли я увеличить скорость умножения массива в Python3 - PullRequest
0 голосов
/ 11 июля 2019

Мне нужно ускорить мой ниже простой код. Я уже использую Numba и Pypy, время выполнения занимает около 0,00018 сек. Однако мне нужно увеличить время выполнения. Есть ли способ сделать это ??

Edit-1

У меня огромная матрица, например 250000x6000. Для каждого элемента мне нужно запустить код ниже. Я использую параллельную обработку с 10 ядрами. Это означает, что (250000 *6000* 0,00018 сек / 10) около 7 или 8 часов.

Edit-2 :
Например: я иду от 0 до 3000
Bn - массив с плавающей запятой 3001x1
value, part и normx являются плавающими скалярами
нога 3001x1 массив с плавающей точкой

i = np.arange(Lmin,Lmax+1)
kernel = np.sum(((2*i+1)/part)*((value)**(i+1))*leg[i]*Bn[i]*((i-1)/normx))

Что я пробовал до сих пор (самый быстрый)

 @njit
 def trial(normx,Lmin,Lmax,Bn,)
     kernel = 0
     part = something*4*np.pi
     value = some value/normx
     leg = some.funtions()
     for i in range(Lmin,Lmax+1)
         kernel += ((2*i+1)/part)*((value)**(i+1))*leg[i]*Bn[i]
 return(kernel)

1 Ответ

0 голосов
/ 16 июля 2019

Умножения не занимают много времени в этом расчете. Но возведение в степень ((value)**(i+1)) очень дорого и, вероятно, не нужно. Также не ясно, используете ли вы глобальные переменные в вашей функции. Если так, избегайте этого.

Оригинальная реализация

@nb.njit(fastmath=True,error_model="numpy")
def trial_orig(part,value,Lmin,Lmax,Bn,leg):
    kernel = 0.
    for i in range(0,Lmax+1):
        kernel += ((2*i+1)/part)*((value)**(i+1))*leg[i]*Bn[i]
    return kernel

Как избежать возведения в степень

Обратите внимание, что умножение fact на самого себя является алгебраически таким же, как непосредственное вычисление с возведением в степень. Поскольку это числовая математика, результаты могут немного отличаться.

@nb.njit(fastmath=True,error_model="numpy")
def trial_mod(part,value,Lmin,Lmax,Bn,leg):
    #I assume that Lmin is always >0
    assert Lmin>=0.
    kernel = 0.
    fact=value**(Lmin+1)
    for i in range(Lmin,Lmax):
        kernel += ((2*i+1)/part)*fact*leg[i]*Bn[i]
        fact*=value
    return kernel

Задержка

leg=np.random.rand(3001)
Bn=np.random.rand(3001)
Lmin=0
Lmax=3000
part=15.
value=0.8

%timeit trial_orig(part,value,Lmin,Lmax,Bn,leg)
100 µs ± 1.11 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit trial_mod(part,value,Lmin,Lmax,Bn,leg)
4.25 µs ± 21.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...