The numba+numpy version of the Python loops kernel combines Numba and Numpy.
The following code snippet shows the change introduced to the code:
from numba import njit, jit
@jit(nopython=False)
def compute_step_1(sizes, weight_list, num_scen_found, load_orig, prob, vents, float_th, exposure_time):
for size in sizes:
if size == 'E':
continue
i_size = sizes.index(size)
num_scen = num_scen_found[i_size-1]
weights = weight_list[i_size-1]
for i_scen in range(num_scen):
w = weights[i_scen]
if w == 0:
# weight of this scenario is 0, pass
continue
load_orig_scen = load_orig[i_scen]
for i_area in range(len(prob[i_size])):
for i_loc in range(len(prob[i_size][i_area])):
i_sel = vents[i_loc][i_area]
persist_th = np.zeros((len(float_th)))
for time_ in range(exposure_time):
load_iarea = (load_orig_scen[time_].T.ravel())[i_sel] * 1000.0
persist_th += np.greater(load_iarea, float_th)
prob[i_size, i_area, i_loc, :] += (persist_th/exposure_time)*w
return prob
@jit(nopython=False)
def compute_step_2(alpha, beta, prob, h, vents, n, n_sizes):
for i_area in range(len(vents[0])):
for i_vent in range(len(vents)):
for i_size in range(n_sizes):
if i_size == 0:
continue
alpha[i_area, i_vent, i_size, 0] += h * prob[i_size, i_area, i_vent, 0]
beta[i_area, i_vent, i_size, 0] += h * (1-prob[i_size, i_area, i_vent, 0])
for i_n in range(1, n, 1):
tai = prob[i_size][i_area][i_vent][i_n]
tai1 = prob[i_size][i_area][i_vent][i_n-1]
if tai1 > 0:
f = tai / tai1
alpha[i_area, i_vent, i_size, i_n] += h * f
beta[i_area, i_vent, i_size, i_n] += h * (1-f)
else:
alpha[i_area, i_vent, i_size, i_n] += 0
beta[i_area, i_vent, i_size, i_n] += h
The code is the same as in the numpy version, the only difference is that now compute functions use
Numba decorators. We had to set noPython=False
because Numba was not able to compile our Numpy code without the help
of Python’s interpreter.