web-dev-qa-db-fra.com

La multiplication est-elle plus rapide que la division flottante?

En C/C++, vous pouvez configurer le code suivant:

double a, b, c;
...
c = (a + b) / 2;

Cela fait exactement la même chose que:

c = (a + b) * 0.5;

Je me demande laquelle est la meilleure à utiliser. Une opération est-elle fondamentalement plus rapide que l'autre?

69
wodesuck

La multiplication est plus rapide que la division. À l'université, on m'a appris que la division prend six fois celle de la multiplication. Les temporisations réelles dépendent de l'architecture mais en général, la multiplication ne sera jamais plus lente ni même aussi lente que la division. Optimisez toujours votre code vers l'utilisation de la multiplication si les erreurs d'arrondi le permettent.

Donc, dans un exemple, cela serait généralement plus lent ...

for (int i=0; i<arraySize; i++) {
    a[i] = b[i] / x;
}

... que ça ...

y=1/x;
for (int i=0; i<arraySize; i++) {
    a[i] = b[i] * y;
}

Bien sûr, avec des erreurs d'arrondi, vous perdrez (un peu) de précision avec la deuxième méthode, mais à moins que vous ne calculiez à plusieurs reprises x=1/x; il est peu probable que cela cause beaucoup de problèmes.

Modifier:

Juste pour référence. J'ai trouvé une comparaison tierce des horaires des opérations en effectuant une recherche sur Google.

http://gmplib.org/~tege/x86-timing.pdf

Regardez les chiffres sur MUL et DIV. Cela indique des différences entre 5 et 10 fois selon le processeur.

36
Philip Couling

La multiplication en virgule flottante prend généralement moins de cycles que la division en virgule flottante. Mais avec des opérandes littéraux, l'optimiseur est bien conscient de ce type de micro-optimisations.

25
ouah

Il est fort probable que le compilateur convertisse une division en une multiplication dans ce cas, s'il "pense" que c'est plus rapide. La division par 2 en virgule flottante peut également être plus rapide que les autres divisions flottantes. Si le compilateur ne le convertit pas, il PEUT être plus rapide d'utiliser la multiplication, mais pas certain - dépend du processeur lui-même.

Le gain de l'utilisation manuelle de la multiplication au lieu de la division peut être assez important dans les cas où le compilateur ne peut pas déterminer qu'il est "sûr" de le faire (par exemple, 0,1 ne peut pas être stocké exactement comme 0,1 dans un nombre à virgule flottante, il devient 0,0000000014149011612 ). Voir ci-dessous les chiffres sur les processeurs AMD, qui peuvent être considérés comme représentatifs de la classe.

Pour savoir si votre compilateur le fait bien ou non, pourquoi n'écrivez-vous pas un peu de code pour expérimenter. Assurez-vous de l'écrire afin que le compilateur ne calcule pas seulement une valeur constante et rejette tous les calculs dans la boucle.

Modifier:

Le guide d'optimisation d'AMD pour les processeurs Family 15h fournit des chiffres pour fdiv et fmul - 42 et 6 respectivement. SSE sont un peu plus proches, 24 (simples) ou 27 (doubles) cycles pour DIVPS, DIVPD DIVSS et DIVSD (diviser), et 6 cycles pour toutes les formes de multiplication.

De mémoire, les chiffres d'Intel ne sont pas si loin.

24
Mats Petersson