Math.pow vs opérateur de multiplication (performance)
-
06-09-2019 - |
Question
Tout le monde sait que si l'opérateur se multiplient est plus rapide que d'utiliser la méthode Math.pow? Comme:
n * n * n
vs
Math.Pow ( n, 3 )
La solution
En fait, vous devriez référence pour voir.
Instruit devinette (peu fiable):
Dans le cas où il n'est pas optimisé pour 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 faire face au problème dans son cas général, portant sur les pouvoirs des fractions et d'autres questions, alors que x * x * x
serait tout simplement prendre quelques instructions se multiplient, il est donc très probablement plus rapide .
Autres conseils
I fenêtres simplement ré-installé en studio si visuel 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
Je suis tombé à avoir testé hier, puis a vu maintenant votre question.
Sur ma machine, un Core 2 Duo cadencés 1 fil de test, il est plus rapide d'utiliser se multiplient jusqu'à un facteur de 9. A 10, Math.pow (b, e) est plus rapide.
Cependant, même à un facteur 2, les résultats sont souvent identiques. Il y a des erreurs d'arrondi.
Certains algorithmes sont très sensibles aux erreurs d'arrondi. Je devais courir littéralement plus d'un million de tests aléatoires jusqu'à ce que je découvre cela.
J'ai vérifié, et Math.Pow()
est définie pour prendre deux doubles. Cela signifie qu'il ne peut pas faire multiplications répétées, mais doit utiliser une approche plus générale. S'il y avait un Math.Pow(double, int)
, il pourrait sans doute être plus efficace.
Cela étant dit, la différence de performance est presque certainement tout à fait banal, et vous devez donc utiliser selon le plus clair. Les micro-optimisations de ce genre sont presque toujours inutile, peut être introduit à pratiquement tout moment, et devrait être laissée à 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 passez votre effort micro-optimisation où il fait une différence.
Il en est ainsi micro que vous devriez probablement référence pour les plates-formes spécifiques, je ne pense pas que les résultats d'un Pentium Pro seront nécessairement les mêmes que pour un ARM ou Pentium II.
Dans l'ensemble, il est plus susceptible d'être totalement hors de propos.
Utilisons la convention x ^ n. Supposons n est toujours un entier.
Pour les petites valeurs de n, la multiplication creusera plus rapide, parce que Math.pow (probablement, la mise en œuvre dépendante) utilise des algorithmes de fantaisie pour permettre d'être n
non-intégrale et / ou négatif.Pour les grandes valeurs de n, Math.pow sera probablement plus rapide, mais si votre bibliothèque est pas très intelligent, il utilisera le même algorithme, ce qui est idéal si vous savez que n est toujours un entier. Pour cela, vous pouvez coder une implémentation de href="http://en.wikipedia.org/wiki/Exponentiation_by_squaring" en élevant au carré ou un autre algorithme de fantaisie.
Bien sûr les ordinateurs modernes sont très rapides et vous devriez probablement tenir à la plus simple, plus facile à lire, moins susceptibles d'être la méthode poussette jusqu'à ce que vous évaluer votre programme et sont sûrs que vous obtiendrez une accélération significative en utilisant un algorithme différent.
Je suis en désaccord que les fonctions de handbuilt sont toujours plus rapides. Les fonctions de cosinus sont de façon plus rapide et plus précis que tout ce que je pourrais écrire. En ce qui concerne pow (). Je l'ai fait un test rapide pour voir comment Math.pow () lent était en javascript, parce que Mehrdad mis en garde contre devinettes
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 essayer le programme http: //www.m0ose. com / JavaScripts / speedtests / powSpeedTest.html
Math.Pow(x, y)
est généralement calculé en interne comme Math.Exp(Math.Log(x) * y)
. Evey équation de puissance, il faut trouver un logarithme naturel, une multiplication, et d'élever e
à une puissance.
Comme je l'ai mentionné dans ma réponse précédente, seulement à une puissance de 10 ne Math.Pow()
devenir plus rapide, mais la précision sera compromise si vous utilisez une série de multiplications.