J'ai écrit un code et j'essaie d'utiliser numba pour accélérer le code. Le but principal du code est de regrouper certaines valeurs en fonction d'une condition. A cet égard, iter_
est utilisé pour faire converger le code afin de satisfaire la condition. J'ai préparé un petit cas ci-dessous pour reproduire l'exemple de code :
import numpy as np
import numba as nb
rng = np.random.default_rng(85)
# --------------------------------------- small data volume ---------------------------------------
# values_ = {'R0': np.array([0.01090976, 0.01069902, 0.00724112, 0.0068463 , 0.01135723, 0.00990762,
# 0.01090976, 0.01069902, 0.00724112, 0.0068463 , 0.01135723]),
# 'R1': np.array([0.01836379, 0.01900166, 0.01864162, 0.0182823 , 0.01840322, 0.01653088,
# 0.01900166, 0.01864162, 0.0182823 , 0.01840322, 0.01653088]),
# 'R2': np.array([0.02430913, 0.02239156, 0.02225379, 0.02093393, 0.02408692, 0.02110411,
# 0.02239156, 0.02225379, 0.02093393, 0.02408692, 0.02110411])}
#
# params = {'R0': [3, 0.9490579204466154, 1825, 7.070272000000002e-05],
# 'R1': [0, 0.9729203826820172, 167 , 7.070272000000002e-05],
# 'R2': [1, 0.6031363088057902, 1316, 8.007296000000003e-05]}
#
# Sno, dec_, upd_ = 2, 100, 200
# -------------------------------------------------------------------------------------------------
# ----------------------------- UPDATED (medium and large data volumes) ---------------------------
# values_ = np.load("values_med.npy", allow_pickle=True)[()]
# params = np.load("params_med.npy", allow_pickle=True)[()]
values_ = np.load("values_large.npy", allow_pickle=True)[()]
params = np.load("params_large.npy", allow_pickle=True)[()]
Sno, dec_, upd_ = 2000, 1000, 200
# -------------------------------------------------------------------------------------------------
# values_ = [*values_.values()]
# params = [*params.values()]
# @nb.jit(forceobj=True)
# def test(values_, params, Sno, dec_, upd_):
final_dict = {}
for i, j in enumerate(values_.keys()):
Rand_vals = []
goal_sum = params[j][1] * params[j][3]
tel = goal_sum / dec_ * 10
if params[j][0] != 0:
for k in range(Sno):
final_sum = 0.0
iter_ = 0
t = 1
while not np.allclose(goal_sum, final_sum, atol=tel):
iter_ += 1
vals_group = rng.choice(values_[j], size=params[j][0], replace=False)
# final_sum = 0.0016 * np.sum(vals_group) # -----> For small data volume
final_sum = np.sum(vals_group ** 3) # -----> UPDATED For med or large data volume
if iter_ == upd_:
t += 1
tel = t * tel
values_[j] = np.delete(values_[j], np.where(np.in1d(values_[j], vals_group)))
Rand_vals.append(vals_group)
else:
Rand_vals = [np.array([])] * Sno
final_dict["R" + str(i)] = Rand_vals
# return final_dict
# test(values_, params, Sno, dec_, upd_)
Dans un premier temps, pour appliquer le numba sur ce code @nb.jit
a été utilisé ( forceobj=True
est utilisé pour éviter les avertissements et ), ce qui aura un effet négatif sur les performances. nopython
est également vérifié, avec @nb.njit
qui obtient l'erreur suivante en raison de ne pas soutenir (comme mentionné dans 1 , 2 ) type de dictionnaire des entrées :
ne peut pas déterminer le type de Numba de <classe 'dict'>
Je ne sais pas si (comment) cela pourrait être traité par Dict
de numba.typed
(en convertissant les dictionnaires python créés en numba Dict) ou si l'on convertit le fichier dictionnaires a listes de tableaux n'ont aucun avantage. Je pense que la parallélisation peut être possible si certaines lignes de code, par ex. Rand_vals.append(vals_group)
o autre section ou être pris ou être modifié hors de la fonction pour obtenir les mêmes résultats que précédemment, mais je n'ai aucune idée de la façon de le faire.
Je vous serai reconnaissant d'aider à utiliser numba sur ce code. numba parallelization
sera la solution la plus souhaitée (probablement la meilleure méthode applicable en termes de performances) si elle pouvait .
Données :
- un volume de données moyen : Valeurs_médicales , params_med
- un grand volume de données : valeurs_grandes , params_large