Vous êtes somme réduction/effondrement des colonnes de A
à l'aide L
pour sélectionner ces colonnes. En outre, vous mettez à jour les colonnes du tableau de sortie en fonction de l'unicité de L
elems.
Ainsi, vous pouvez utiliser np.add.reduceat
pour une solution vectorisée, comme si -
sidx = L.argsort()
col_idx, grp_start_idx = np.unique(L[sidx],return_index=True)
B_out = np.zeros((len(A), n_cols))
B_out[:,col_idx] = np.add.reduceat(A[:,sidx],grp_start_idx,axis=1)
Test d'exécution -
In [129]: def org_app(A,n_cols):
...: B = np.zeros((len(A), n_cols))
...: for i, a in enumerate(A.T):
...: B[:, L[i]] += a
...: return B
...:
...: def vectorized_app(A,n_cols):
...: sidx = L.argsort()
...: col_idx, grp_start_idx = np.unique(L[sidx],return_index=True)
...: B_out = np.zeros((len(A), n_cols))
...: B_out[:,col_idx] = np.add.reduceat(A[:,sidx],grp_start_idx,axis=1)
...: return B_out
...:
In [130]: # Setup inputs with an appreciable no. of cols & lesser rows
...: # so as that memory bandwidth to work with huge number of
...: # row elems doesn't become the bottleneck
...: d,n_cols = 10,5000
...: A = np.random.rand(d,n_cols)
...: L = np.random.randint(0,n_cols,(n_cols,))
...:
In [131]: np.allclose(org_app(A,n_cols),vectorized_app(A,n_cols))
Out[131]: True
In [132]: %timeit org_app(A,n_cols)
10 loops, best of 3: 33.3 ms per loop
In [133]: %timeit vectorized_app(A,n_cols)
100 loops, best of 3: 1.87 ms per loop
Comme le nombre de lignes deviennent comparables avec le nombre de Col. Dans A
, les exigences de largeur de bande de mémoire haute pour l'approche vectorisée compenserait toute accélération notable de celle-ci.
Pensez-vous que vous pourriez poster un exemple complet? (c'est-à-dire [mcve]) Cela aiderait si nous pouvions voir l'effet de ce code sur les petites matrices et un exemple de liste 'L' aussi. – Praveen
@Praveen J'ai rempli un peu plus l'exemple. –