Векторизовать код в функции, в которой циклы используют диапазон в Python / NumPy - PullRequest
1 голос
/ 30 мая 2020

У меня есть функция, которая вызывается много раз в других функциях. Чтобы улучшить вычисления, я пытаюсь векторизовать код, хотя мне не удалось этого сделать в данном конкретном случае, когда задействованы сложные диапазоны. Кто-нибудь из вас видит, как это можно сделать в этом конкретном c случае?

def growdh_no_bloom(mx, mn, daylen, baset):

    if mn == 0:
        mn = 0.01
    if mx == mn:
        mx += 0.01
    dt = mx - mn

    idl = int(np.floor(daylen))

    # calculate day time hourly temperatures
    t = np.zeros(24)
    t[0] = mn

    for hour in range(1, idl+1):
        t[hour] = dt * np.sin(np.pi/(daylen+4)*(hour)) + mn

    # calculate sunset time and temperature
    ts1 = dt*np.sin(np.pi/(daylen+4)*daylen) + mn
    if ts1 <= 0:
        ts1 = 0.01

    # calculate hourly temperatures (nighttime)
    count = 0
    for hour in range(idl + 1, 24):
        count += 1
        t[hour] = ts1-(ts1-mn)/(np.log(24-daylen))*np.log(count)

    # growing degree hours
    gdhour = 0
    for hour in range(0, 24):
        if t[hour] - baset > 0:
            gdhour += (t[hour] - baset)
    return gdhour

Заранее спасибо!

Ответы [ 2 ]

3 голосов
/ 30 мая 2020
from numba import jit
sig = np.random.randn(44100)
import numpy as np

vectorized = jit(growdh_no_bloom)

Или просто

import numba
import random

@numba.njit()
def growdh_no_bloom:
    for i in range(): #your for loop with range

Numba - это JIT-компилятор с открытым исходным кодом, который переводит подмножество Python и NumPy в быстрый машинный код с использованием LLVM через Пакет llvmlite Python. Он предлагает ряд вариантов распараллеливания кода Python для ЦП и графических процессоров, часто с незначительными изменениями кода.

Numba

В случае это исключение:

NumbaWarning: Compilation is falling back to object mode WITHOUT looplifting enabled because Function 'growdh_no_bloom' failed type inference due to: cannot determine Numba type of <class 'numba.dispatcher.LiftedLoop'>

Получить:

numba.__version__

, если это 0.44.0 или новее

pip install --upgrade numba==0.43.1
2 голосов
/ 30 мая 2020

Хотя Numba определенно даст лучшую производительность, я думаю, что оптимизированная функция будет полезна и вам в будущем. Обратите внимание, как я удалил все петли с помощью простой трансляции.

def growdh_no_bloom(mx, mn, daylen, baset):
    mn = 0.01 if mn==0 else mn
    mx = mx + 0.01 if mx == mn else mx
    dt = mx - mn
    idl = int(np.floor(daylen))

    # calculate day time hourly temperatures
    t = np.zeros(24)
    t[0] = mn
    t[1:idl+1] = dt * np.sin(np.pi/(daylen+4)*np.arange(1,idl+1)) + mn

    # calculate sunset time and temperature
    ts1 = dt*np.sin(np.pi/(daylen+4)*daylen) + mn
    ts1 = 0.01 if ts1 <= 0 else ts1

    # calculate hourly temperatures (nighttime)
    t[idl+1:24] = ts1-(ts1-mn)/(np.log(24-daylen))*np.log(np.arange(1,24-idl))

    gdhour = t-baset
    return gdhour[gdhour>0].sum()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...