J'ai un (ou, mathématiquement, actuellement, j'ai un mais depuis k * n code> matrix x et un k * k code> matrice A. Pour chaque colonne de x code>, je tiens à calculer le scalaire xi '* a * xi code>). p> pour code> boucle: p> n code> est grand, je voudrais le faire plus vite si possible (c'est-à-dire en utilisant certains Fonctions numpées au lieu d'une boucle). P> p>
3 Réponses :
Vous ne pouvez pas le faire plus vite sauf si vous parallélisez le tout: un fil par colonne. Vous utiliserez toujours des boucles - vous ne pouvez pas vous échapper de cela. P>
La carte Réduire est une bonne façon de regarder ce problème: Map Matit Multiples, réduire les sommets. P>
Bien sûr, je ne peux pas aller plus vite à partir d'un point de vue de la complexité, mais éviter les boucles Python (en faveur de constructions numpées) fournit généralement une vitesse simplement en évitant le code Python plus lent.
Vous pouvez utiliser le Cela obtiendra le même résultat. Voyons si c'est beaucoup plus rapide: p> ressemble à numpy.einsum code>: dot code> est toujours l'option la plus rapide, en particulier parce qu'il utilise des blas filetés, par opposition à einsum code> qui fonctionne sur un noyau. p>
Ceci est considérablement plus lent pour une grande dimension sur les processeurs modernes en raison de sa capacité à utiliser une blas filetée.
@Ophion bon point, mais je crois que ce sera toujours plus rapide que le python pour code> boucle ... quelque chose qui vaut la peine d'être vérifié
Python pour code> boucle CYTHON / NUMPLY pour code> La boucle n'a pas d'importance. Le temps n'est vraiment pas dans la boucle.
Je n'ai pas de blas enfilé (bien que je devrais évidemment l'obtenir à un moment donné). Pour N = 10000 CODE>, cela surperformez mon code d'origine (76,2ms contre 1,48ms).
@nneonneo Je termine un test ici, le mien est Blas avec 4 cœurs ... Voyons les résultats ...
@Ophion ... vous avez raison ... J'ai mis à jour la réponse avec certaines comparaisons contre une blas optimisée et pour High N code>, le numpy.einsum code> est beaucoup plus lent.
Vous devez créer les tableaux en dehors de la fonction pour éviter l'impact de aléatoire code>.
@nneonneo mais cela ne changerait pas de manière significative les résultats
Juste pour confirmer certains résultats, j'utilise MKL et il est certainement plus lent sur ma machine.
HM, vous avez peut-être raison. Merci pour le lien einsum code>; C'est bien de savoir ce qu'il peut faire. Dommage que ce ne soit pas la solution la plus rapide. (Très surprenant qu'il soit plus rapide que la solution de @ ianh pour n = 10000, k = 10 code> sur un noyau, cependant)
@nneNneo Vérifiez cette question où il est montré de nombreux cas où Einsum code> surperforms ... il peut être très utile et plus rapide dans certains cas
@nneonneo apporte un bon point. Lorsque tout est dit et fait, quelle version est plus rapide dépendra probablement de la taille des matrices et de la configuration du système à utiliser.
@LANH Je pense que nous pouvons dire que lorsque l'Atlas échoue à plus d'un noyau, votre solution sera plus rapide, sinon le einsum code> peut être plus rapide ...
@nneonneo np.dot (x, x) code> échelle à environ n ^ 2.8 code> pendant np.einsum ("ij, jk", x, x) code> est naïf et des échelles à n ^ 3 code>. np.dot code> sera toujours plus rapide par noyau pour les grandes tableaux.
Cela semble le faire bien:
Edit: Ceci est un peu plus rapide. (x.t.dot (a) * x.t) .sum (axe = 1) code> p>
np.einsum ('... I, ... I -> ...', x.t.dot (a), x.t) code>. Les deux fonctionnent mieux si x code> et a code> sont contigus de force contiguë. P>
Apparaît Handly i> battre mon code d'origine: pour n = 10000, k = 10 code>, mon code est 76,2ms, le nouveau code est 1.64ms i> . Agréable!