Il ya quelques années, quelqu'un posted sur Recettes d'état actif à des fins de comparaison, trois fonctions python/NumPy; chacun de ceux-ci a accepté les mêmes arguments et a renvoyé le même résultat, une matrice de distance .Pourquoi le bouclage bat-il l'indexation ici?
Deux d'entre eux ont été extraits de sources publiées; ils sont tous les deux - ou ils me semblent être - un code numérique idiomatique. Les calculs répétitifs requis pour créer une matrice de distance sont pilotés par la syntaxe d'index élégante de numpy. Voici l'un d'eux:
from numpy.matlib import repmat, repeat
def calcDistanceMatrixFastEuclidean(points):
numPoints = len(points)
distMat = sqrt(sum((repmat(points, numPoints, 1) -
repeat(points, numPoints, axis=0))**2, axis=1))
return distMat.reshape((numPoints,numPoints))
Le troisième créé la matrice à distance en utilisant une seule boucle (ce qui est évidemment beaucoup de looping étant donné qu'une matrice de distance de seulement 1000 points 2D, a un million d'entrées). À première vue, cette fonction me semblait être le code que j'écrivais quand j'apprenais NumPy et j'écrivais du code NumPy en écrivant d'abord du code Python, puis en le traduisant ligne par ligne.
Plusieurs mois après la publication de l'état actif, les résultats des tests de performance comparant les trois ont été postés et discutés dans un thread sur la liste de diffusion NumPy.
La fonction avec la boucle en fait significativement surperformé les deux autres:
from numpy import mat, zeros, newaxis
def calcDistanceMatrixFastEuclidean2(nDimPoints):
nDimPoints = array(nDimPoints)
n,m = nDimPoints.shape
delta = zeros((n,n),'d')
for d in xrange(m):
data = nDimPoints[:,d]
delta += (data - data[:,newaxis])**2
return sqrt(delta)
Un participant dans le fil (Keir Mierle) a offert une raison pour laquelle cela pourrait être vrai:
La raison pour laquelle je suspecte que ce sera plus rapide est qu'il a une meilleure localité, en terminant complètement un calcul sur un ensemble de travail relativement petit avant de passer à la prochaine un. Les liners doivent tirer le tableau MxN potentiellement grand dans le processeur à plusieurs reprises.
Par son propre compte cette affiche, sa remarque est qu'un soupçon, et il ne semble pas qu'il a été discuté plus loin.
Avez-vous d'autres idées sur la façon de comptabiliser ces résultats?
En particulier, y a-t-il une règle utile - en ce qui concerne quand boucler et quand indexer - qui peut être extraite de cet exemple comme guide dans l'écriture de code numpy?
Pour ceux qui ne connaissent pas NumPy, ou qui n'ont pas regardé le code, cette comparaison n'est pas basée sur un cas limite - ce ne serait certainement pas si intéressant pour moi si c'était le cas. Au lieu de cela, cette comparaison implique une fonction qui effectue une tâche commune dans le calcul matriciel (c.-à-d., Création d'un tableau de résultats avec deux antécédents); de plus, chaque fonction est à son tour composée des inserts numpy les plus courants.
très utile, merci. +1 de moi. – doug