Mathématique.Pow vs opérateur de multiplication (performance)
N'importe qui sait si l'opérateur de multiplication est plus rapide que L'utilisation des mathématiques.La méthode Pow? Comme:
n * n * n
vs
Math.Pow ( n, 3 )
10 réponses
en gros, vous devriez benchmark pour voir.
travaux théoriques (peu fiables):
dans le cas où il n'est pas optimisé à la même chose par un compilateur...
il est très probable que x * x * x
est plus rapide que Math.Pow(x, 3)
comme Math.Pow
doit traiter du problème dans son cas général, traitant des pouvoirs fractionnaires et d'autres questions, tandis que x * x * x
serait il suffit de prendre quelques instructions de multiplication, il est donc très probable d'être plus rapide.
je viens de réinstaller windows donc visual studio n'est pas installé et le code est laid""
using System;
using System.Diagnostics;
public static class test{
public static void Main(string[] args){
MyTest();
PowTest();
}
static void PowTest(){
var sw = Stopwatch.StartNew();
double res = 0;
for (int i = 0; i < 333333333; i++){
res = Math.Pow(i,30); //pow(i,30)
}
Console.WriteLine("Math.Pow: " + sw.ElapsedMilliseconds + " ms: " + res);
}
static void MyTest(){
var sw = Stopwatch.StartNew();
double res = 0;
for (int i = 0; i < 333333333; i++){
res = MyPow(i,30);
}
Console.WriteLine("MyPow: " + sw.ElapsedMilliseconds + " ms: " + res);
}
static double MyPow(double num, int exp)
{
double result = 1.0;
while (exp > 0)
{
if (exp % 2 == 1)
result *= num;
exp >>= 1;
num *= num;
}
return result;
}
}
les résultats:
csc /o test.cs
test.exe
MyPow: 6224 ms: 4.8569351667866E+255
Math.Pow: 43350 ms: 4.8569351667866E+255
Exponentiation par la quadrature (voir https://stackoverflow.com/questions/101439/the-most-efficient-way-to-implement-an-integer-based-power-function-powint-int ) est beaucoup plus rapide que les Mathématiques.Pow dans mon test (mon CPU est un Pentium T3200 à 2 Ghz)
EDIT: .net version est 3.5 SP1, OS Est Vista SP1 et le plan de puissance est haute performance.
il se trouve que j'ai testé ceci hier, puis j'ai vu votre question maintenant.
sur ma machine, un Core 2 Duo tournant 1 thread de test, il est plus rapide à utiliser multiplier jusqu'à un facteur de 9. À 10 Ans, En Maths.Pow (b, e) est plus rapide.
Cependant, même à un facteur de 2, les résultats sont souvent pas identiques. Il y a des erreurs d'arrondi.
Certains algorithmes sont très sensibles aux erreurs d'arrondi. J'ai dû littéralement courir sur un million. des tests aléatoires jusqu'à ce que je découvre ça.
quelques règles empiriques de plus de 10 ans d'optimisation dans le traitement de l'image et l'informatique scientifique:
Optimisations au niveau algorithmique battre n'importe quel montant d'optimisation à un faible niveau. En dépit de la sagesse conventionnelle" écrire l'évidence, puis optimiser " cela doit être fait au début. Pas après.
Les opérations mathématiques codées à la main(spécialement les types SIMD SSE+) seront généralement plus performantes que les erreurs vérifiées, généralisées et intégrées.
toute opération où le compilateur sait à l'avance ce qui doit être fait est optimisée par le compilateur. Ces inclure:
1. Les opérations de mémoire comme Tableau.Copie()
2. Pour les boucles sur les tableaux où la longueur du tableau est donnée. Comme pour ( ..; i<array.Length;..
)
Toujours fixer des objectifs irréalistes (si vous voulez).
j'ai vérifié, et Math.Pow()
est défini pour prendre deux doubles. Cela signifie qu'il ne peut pas faire répétées des multiplications, mais doit utiliser une approche plus générale. S'il y avait un Math.Pow(double, int)
, il pourrait probablement être plus efficace.
cela dit, la différence de performance est presque certainement tout à fait insignifiante, et vous devriez donc utiliser celle qui est la plus claire. Les micro-optimisations comme celle-ci sont presque toujours inutiles, peuvent être introduites pratiquement à tout moment, et devrait être laissé à la fin du processus de développement. À ce moment-là, vous pouvez vérifier si le logiciel est trop lent, où les points chauds sont, et passer votre effort de micro-optimisation où il fera réellement une différence.
C'est tellement micro que vous devriez probablement le comparer pour des plateformes spécifiques, Je ne pense pas que les résultats pour un Pentium Pro seront nécessairement les mêmes que pour un bras ou un Pentium II.
dans l'ensemble, c'est probablement totalement hors de propos.
utilisons la convention x^N. Supposons que n soit toujours un entier.
pour de petites valeurs de n, La multiplication ennuyeuse sera plus rapide, parce que les mathématiques.Pow (probablement dépendant de la mise en œuvre) utilise des algorithmes sophistiqués pour permettre à n d'être non intégral et/ou négatif.
pour les grandes valeurs de n, Math.Pow sera probablement plus rapide, mais si votre bibliothèque n'est pas très intelligente, il utilisera le même algorithme, ce qui n'est pas idéal si vous savez que n est toujours un entier. Pour cela, vous pouvez coder une implémentation de exponentiation par la quadrature de ou un autre algorithme fantaisiste.
bien sûr, les ordinateurs modernes sont très rapides et vous devriez probablement vous en tenir à la méthode la plus simple, la plus facile à lire, la moins susceptible d'être buggy jusqu'à ce que vous benchmark votre programme et êtes sûr que vous obtiendrez une accélération significative en utilisant un algorithme différent.
Voici une discussion sur le thème de inline multiplication vs Mathématiques.pow
Apparemment Des Maths.pow est plus lent, mais pas de beaucoup...
Je ne suis pas d'accord sur le fait que les fonctions manuelles sont toujours plus rapides. Les fonctions cosine sont plus rapides et plus précises que tout ce que je pourrais écrire. Comme pour les pow(). J'ai fait un test rapide pour voir comment ralentir Mathématiques.pow () était en javascript, parce que Mehrdad a mis en garde contre les conjectures
for (i3 = 0; i3 < 50000; ++i3) {
for(n=0; n < 9000;n++){
x=x*Math.cos(i3);
}
}
voici les résultats:
Each function run 50000 times
time for 50000 Math.cos(i) calls = 8 ms
time for 50000 Math.pow(Math.cos(i),9000) calls = 21 ms
time for 50000 Math.pow(Math.cos(i),9000000) calls = 16 ms
time for 50000 homemade for loop calls 1065 ms
si vous n'êtes pas d'accord, essayez le programme à http://www.m0ose.com/javascripts/speedtests/powSpeedTest.html
Math.Pow(x, y)
est généralement calculé à l'interne comme Math.Exp(Math.Log(x) * y)
. Chaque équation de puissance nécessite de trouver un log naturel, une multiplication, et de soulever e
à une puissance.
comme je l'ai mentionné dans ma réponse précédente, ce n'est qu'à une puissance de 10 que Math.Pow()
devient plus rapide, mais la précision sera compromise si on utilise une série de multiplications.