7
votes

Est-ce que Array.copy () plus rapide que pour la boucle, pour les matrices 2D?

J'ai récemment changé xxx

à xxx

où les valeurs de courant et d'origine sont des constantes 0 et 1 respectivement. FieldValues ​​est un champ et des valeurs sur le terrain sont un paramètre.

à l'endroit où je l'utilisais, j'ai trouvé la version Array.copy () pour être plus rapide. Mais un autre développeur dit qu'il a chronométré la boucle à la boucle contre Array.copy () dans un programme autonome et a trouvé la boucle plus rapide.

est-il possible que la matry.copy () ne soit pas vraiment plus rapide? Je pensais que c'était censé être super-optimisé!


5 commentaires

C'est très important, si vous vous souciez des détails de la performance, tels que cela, vous pourrez écrire des programmes d'analyse comparative simples :)


Et avoir la connaissance de ce qui se passe sous le capot.


Mon hypothèse est que l'array.copy serait plus rapide que la boucle d'autant plus que la taille de la matrice se développe. En outre, lorsque vous avez la possibilité d'utiliser une méthode de cadre VS Roulant à la main ... Vous devez toujours utiliser la méthode-cadre que si vous avez une exigence très spécifique et mesurable à faire autrement.


Très probablement: il est totalement non pertinent.


Ce n'est pas non pertinent. J'ai géré un profileur sur le code, dans une situation qui causait des problèmes de performance et l'identifiait comme le plus grand point chaud. Dans cette situation, utiliser Array.copy () le rendit notablement plus rapide, mais dans le programme d'essai autonome, Tary.copy () semblait perdre à la boucle.


3 Réponses :


5
votes

La façon dont .Net fonctionne sous la hotte, je suppose que dans une situation optimisée, la gamme. Copy éviterait les limites de vérification.

Si vous faites une boucle sur n'importe quel type de collection, le CLR vérifiera par défaut pour vous assurer que vous n'abandonnez pas la fin de la collection, puis le JIT devra soit faire une évaluation d'exécution ou un code d'émission qui n'a pas besoin de vérifier. (Vérifiez l'article dans mon commentaire pour de meilleurs détails de cela)

Vous pouvez modifier ce comportement, mais vous ne économisez généralement pas beaucoup. Sauf si vous êtes dans une boucle intérieure bien exécutée où chaque milliseconde compte, c'est-à-dire.

Si la matrice est grande, j'utiliserais une array.copy, si elle est petite, soit de la même manière.

Je pense que c'est la vérification des limites qui créent des résultats différents pour vous.


1 commentaires

C'est une lecture longue, mais c'est un excellent blog MSDN sur les limites Optimisation de la vérification: blogs.msdn.com/b/crcodegeneration/archive/2009/08/13/...



-4
votes

Dans votre exemple particulier, il existe un facteur que pourrait (en théorie) indiquer la pour la boucle est plus rapide.

array.copy est un O (n) opération pendant que votre boucle est O (n / 2), où n est la taille totale de votre matrice.

array.copy doit être en boucle de tous les éléments de votre tableau en deux dimensions car:

Lors de la copie entre les tableaux multidimensionnels, la matrice se comporte comme un Tableau d'une dimension longue, où les rangées (ou colonnes) sont conceptuellement mis fin à la fin. Par exemple, si un tableau a trois rangées (ou colonnes) avec quatre éléments chacun, copiant six éléments de la Le début de la matrice copierait tous les quatre éléments de la première rangée (ou colonne) et les deux premiers éléments de la deuxième ligne (ou colonne).


1 commentaires

Cette réponse montre un malentendu total de ce que signifie la notation O (n).



11
votes

Dans ma propre expérience, j'ai constaté que je ne peux pas faire confiance à mon intuition sur quoi que ce soit en matière de performance. Par conséquent, je garde une application de référence rapide et sale autour (que j'appelle "stupideformformanceRicks"), que j'utilise pour tester ces scénarios. Ceci est inestimable, comme j'ai fait toutes sortes de découvertes surprenantes et contre-intuitives sur les tours de performance. Il est également important de rappeler d'exécuter votre application de référence en mode de sortie, sans débogger joint, car vous n'avez pas autrement d'obtenir des optimisations JIT, et ces optimisations peuvent faire une différence significative: la technique A peut être plus lente que la technique B en mode de débogage, mais significativement plus rapide en mode de libération, avec un code optimisé.

Cela dit, en général, ma propre expérience de test indique que si votre matrice est <~ 32 éléments, vous obtiendrez une meilleure performance en roulant votre propre boucle de copie - probablement parce que vous n'avez pas la méthode appelle la méthode. peut être significatif. Toutefois, si la boucle est supérieure à ~ 32 éléments, vous obtiendrez une meilleure performance en utilisant Array.copy (). (Si vous copiez des véhicules ou des flotteurs ou des éléments similaires de choses, vous voudrez peut-être également enquêter sur la mémoire tampon.blockcopy (), qui est ~ 10% plus rapide que le tableau.Copy () pour les petits tableaux.)

Mais tout ce qui dit, la réponse réelle est: «Écrivez vos propres tests qui correspondent à ces alternatives précises le plus près possible, enveloppez-les chacune avec une boucle, donnez-les suffisamment d'itérations à la boucle pour mâcher au moins 2-3 secondes de la CPU, puis comparez les alternatives vous-même. "


0 commentaires