Est-il possible de rouler une version nettement plus rapide de sqrt
-
26-09-2019 - |
Question
Dans une application je profilage, je trouve que dans certains scénarios cette fonction est en mesure de prendre plus de 10% du temps total d'exécution.
J'ai vu la discussion au cours des années de mises en œuvre plus rapide sqrt utilisant la ruse sournoise à virgule flottante, mais je ne sais pas si ces choses sont obsolètes sur les processeurs modernes.
MSVC ++ 2008 compilateur est utilisé, pour référence ... mais je suppose que sqrt ne va pas ajouter de frais généraux bien.
Voir aussi ici pour discussion similaire sur cette est une méthode largement utilisée, mais est-il réellement beaucoup plus rapide? Combien de cycles est de toute façon RACINE ces jours-ci?
La solution
Oui, il est possible même sans supercherie:
1) précision de sacrifice pour la vitesse:. L'algorithme de sqrt est itérative, re-mettre en œuvre avec moins d'itérations
2) tables de recherche:. Soit juste pour le point de départ de l'itération, ou combiné avec interpolation pour vous aider à tout le chemin
3) la mise en cache: êtes-vous sqrting toujours le même ensemble limité de valeurs? le cas échéant, la mise en cache peut bien fonctionner. J'ai trouvé cela utile dans les applications graphiques où la même chose est calculée pour beaucoup de formes de la même taille, de sorte que les résultats peuvent être utilement mises en cache.
Autres conseils
Il y a une grande table de comparaison ici: http://assemblyrequired.crashworks.org/timing-square-root/
Longue histoire courte, les ssqrts de SSE2 est d'environ 2x plus rapide que FPU fsqrt, et une approximation + itération est d'environ 4x plus rapide que celle (8x globale).
En outre, si vous essayez de prendre une sqrt simple précision, assurez-vous que est en fait ce que vous obtenez. Je l'ai entendu parler d'au moins un compilateur qui transformerait l'argument flottant à un double, appelez sqrt double précision, puis reconvertir à flotter.
Vous êtes très probablement d'obtenir des améliorations plus rapides en changeant votre algorithmes qu'en changeant leur implémentations : Essayez d'appel sqrt()
moins au lieu de faire des appels plus rapidement. (Et si vous pensez que cela est impossible - les améliorations pour sqrt()
que vous mentionnez ne sont que: l'amélioration de la algorithme utilisé pour calculer une racine carrée.)
Comme il est utilisé très souvent, il est probable que votre mise en œuvre de la bibliothèque standard de sqrt()
est presque optimale pour le cas général. Sauf si vous avez un domaine restreint (par exemple, si vous avez besoin moins de précision) où l'algorithme peut prendre des raccourcis, il est très peu probable que quelqu'un arrive avec une implémentation qui est plus rapide.
Notez que, puisque cette fonction utilise 10% de votre temps d'exécution, même si vous parvenez à trouver une mise en œuvre qui ne prend 75% du temps de std::sqrt()
, ce encore apportera seulement votre temps d'exécution par 2,5% . Pour la plupart des applications utilisateurs ne remarquent même pas cela, sauf si elles utilisent une montre pour mesurer.
Quelle précision besoin de votre sqrt
-vous être? Vous pouvez obtenir une approximation raisonnable très rapidement: voir l'excellent Quake3 inverse fonction racine carrée d'inspiration (notez que le code sous GPL, vous voudrez peut-être pas intégrer directement).