Le problème réel que je souhaite résoudre est, étant donné qu'un ensemble de vecteurs d'unité n em> et un autre ensemble de vecteurs m em> calculez pour chacun des vecteurs de l'unité la moyenne du Valeur absolue du produit DOT de celui-ci avec chacun des vecteurs m em>. Essentiellement cela consiste à calculer le produit extérieur des deux matrices et en résumant et en moyenne avec une valeur absolue bloquée entre les deux. pour n em> et m em> pas trop grand ceci est Pas difficile et il existe de nombreuses façons de procéder (voir ci-dessous). Le problème est quand n em> et m em> sont importants, les temporaires créés sont énormes et offrent une limitation pratique pour l'approche fournie. Ce calcul peut-il être fait sans créer des temporaires? La principale difficulté que j'ai est due à la présence de la valeur absolue. Existe-t-il des techniques générales pour "threading" de tels calculs? P> à titre d'exemple, considérez le code suivant P> T = np.einsum('ik,jk,j', nhat, m, np.ones(M)) / M
3 Réponses :
Ceci est un peu plus lent, mais ne crée pas la grande matrice intermédiaire.
m2 = np.average(m,0) vals = np.zeros(N) for i in xrange(N): u=nhat[i] if u[0] >= 0 and u[1] >= 0 and u[2] >= 0: vals[i] = abs(np.dot(u,m2)) else: for j in xrange(M): vals[i]+=abs(np.dot(u,m[j])) vals[i]/=M
Cela fonctionne, bien sûr, mais pour toutes les grandes valeurs de n i> ou m i> cela sera douloureusement lent. Il peut être fait plus rapidement en utilisant une seule boucle et diffuser uniquement un i> de n i> ou m i> (semblable au code que j'ai fourni dans la question mais appliqué à un seul Nhat code> ou
m code>). Mais même cela est douloureusement lent pour les deux n i> et m i> grand.
Vous pouvez utiliser Cython pour améliorer encore la vitesse de la ou des boucles. Il peut également améliorer l'indexation des valeurs uniques telles que les vals [i] (pas des tranches).
Cela semble invraisemblable qu'il y aurait une différence de performance significative lorsqu'elle ne fait qu'une des boucles de Python, tant que au moins, au moins le plus grand de N et M est vectorisé. Si N ou M est vraiment si gros, la surcharge en boucle ne doit pas dominer par rapport aux calculs engendrés. Avez-vous enfoncé cela? Si vous décidez que vous avez besoin d'une boucle C, jetez un coup d'œil à Numba. Pas tout aussi mature que Cyron, mais pour ce type de fonctionnalité, cela fonctionne parfaitement.
Je ne pense pas qu'il y ait un moyen facile (en dehors de Cyron et similaire) pour accélérer votre opération exacte. Mais vous voudrez peut-être déterminer si vous avez vraiment besoin de calculer ce que vous calculez. Car si au lieu de la moyenne des valeurs absolues, vous pouvez utiliser le carré moyen racine , vous seriez toujours Soyez en quelque sorte à la moyenne des grossitudes de produits intérieurs, mais vous pouvez l'obtenir en un seul coup comme étant:
rms_2 = np.sqrt(np.average(np.einsum('ij,kj->ik', nhat, m)**2, axis=-1))
Sur la base de certains des commentaires, il semble que l'utilisation de Cyron soit la meilleure façon d'y aller. Je n'ai bêtement jamais regardé à l'aide de Cyron. Il s'avère être relativement facile à produire du code de travail.
Après la recherche, je mets ensemble le code Cython suivant. Ceci est einsum () code> dans la question originale de sorte que ce n'est pas trop mauvais! Il a été écrit pour travailler explicitement avec des tableaux créés comme dans la question initiale (d'où les modes supposés des tableaux d'entrée).
Malgré les mises en garde, il fournit une solution raisonnablement efficace au problème initial et peut servir de point de départ dans des situations similaires. P>
Pouvez-vous le faire avec
DOT CODE> < / a> et certains axes violent?
Tensordot code> A> pourrait être plus utile.
Ce n'est pas évident comment cela aide à cause de la nécessité pour le
ABS () code>. S'il n'y avait pas que l'expression
einsum () code> dans la question serait idéale!
Je pense que vous pouvez utiliser
dot code> ou
tensordot code> pour générer le passage temporaire transmis à
ABS code>, sauvegarder une commande de magnitude ou deux de mémoire depuis que vous n'avez pas " t faut
somme code>. Je doute que vous puissiez éviter l'appel code> abs code>, cependant.
Hmm ... Si vous travaillez dans quelque chose comme R ^ 3 au lieu d'un espace de configuration de zillion-paramètre, cela ne coupe que votre consommation maximale de mémoire jusqu'à 1/3 de l'ancienne valeur. Cela ne serait probablement pas suffisant.
@ user2357112 correct, c'est vraiment le temporaire qui est envoyé à
ABS () code> avant la moyenne du problème. Avec le code
einsum () code> même pour n i> = 1000000 et m i> = 5000 Il ne faut que 75 secondes environ pour exécuter et utiliser non (notable) mémoire supplémentaire. Tout ce que je veux vraiment faire, c'est insérer une valeur absolue au bon endroit dans ce calcul!
Toute chance que les vecteurs de l'unité dans le problème réellement constituent une base?
@Zhenya Eh bien, il y a n i >> 3 d'entre eux, alors ... mais non, ils ne forment pas de base, ce sont vraiment des directions aléatoires.