1

dans le programme sur lequel je travaille J'ai des tableaux à 3 éléments, que j'utilise comme vecteurs mathématiques à toutes fins pratiques.Efficacité des boucles écrites manuellement par rapport aux surcharges d'opérateur

Tout au long de l'écriture de mon code, je suis tenté de simplement rouler ma propre Vector classe avec des surcharges arithmétiques simples (+, -, * /) donc je peux simplifier les déclarations comme:

// old: 
for (int i = 0; i < 3; i++) 
    r[i] = r1[i] - r2[i]; 

// new: 
r = r1 - r2; 

qui devrait être plus ou moins identiques dans le code généré. Mais quand il s'agit de choses plus compliquées, est-ce que cela pourrait vraiment affecter ma performance? Un exemple que j'ai dans mon code est le suivant:

Version manuelle écrite:

for (int j = 0; j < 3; j++) 
{ 
    p.vel[j] = p.oldVel[j] + (p.oldAcc[j] + p.acc[j]) * dt2 + (p.oldJerk[j] - p.jerk[j]) * dt12; 
    p.pos[j] = p.oldPos[j] + (p.oldVel[j] + p.vel[j]) * dt2 + (p.oldAcc[j] - p.acc[j]) * dt12; 
} 

Utilisation de la Vector classe avec surcharge opérateur:

p.vel = p.oldVel + (p.oldAcc + p.acc) * dt2 + (p.oldJerk - p.jerk) * dt12; 
p.pos = p.oldPos + (p.oldVel + p.vel) * dt2 + (p.oldAcc - p.acc) * dt12; 

Je cherche à optimiser mon code pour la vitesse , puisque ce genre de code s'exécute à l'intérieur des boucles internes. Est-ce que l'utilisation des opérateurs surchargés pour ces choses affectera les performances? Je fais une intégration numérique d'un système de n corps mutuellement gravitaires. Ces opérations vectorielles sont extrêmement courantes, il est donc important d'avoir une exécution rapide.

Toute idée serait appréciée, comme le feraient tous les idiomes ou astuces que je ne connais pas.

+2

Vous pouvez regarder dans les modèles d'expression. Mais gardez à l'esprit pour obtenir des réponses précises dont vous aurez besoin pour profiler toutes les solutions que vous essayez. – GManNickG

+0

En outre, certains compilateurs non seulement pour vous, ils déroulent aussi des boucles courtes qui ont un nombre défini d'exécutions (comme 3). Vous pourriez regarder le démontage et voir si c'est vrai, ou vous pourriez faire ce que d'autres ont suggéré, et faire un benchmarking pour voir si les opérateurs de surcharge est beaucoup plus rapide. –

+0

Xavier, j'ai compilé l'opérateur surchargé et la version écrite manuellement avec les fichiers .asm d'assemblage + source. La plupart des boucles étaient extrêmement similaires. Certains, comme celui que j'ai posté ci-dessus, avaient de très longues chaînes d'assemblage pour l'opérateur basé sur une surcharge, et des chaînes beaucoup plus courtes avec mes boucles manuelles. Encore, comme je l'ai commenté ci-dessous, ma version Vector était encore plus rapide. –

Répondre

2

Si les opérations sont bien intégrées et optimisées par votre compilateur, vous ne devriez généralement pas voir de différence entre l'écriture correcte du code (en utilisant des opérateurs pour le rendre lisible et maintenable) et manuellement tout. Manuel inlining augmente également considérablement le risque de bogues, car vous ne réutiliserez pas un seul morceau de code bien testé, vous écrivez le même code encore et encore. Je recommande d'écrire le code avec les opérateurs, puis si vous pouvez prouver que vous pouvez l'accélérer en insérant manuellement, dupliquer le code et manuellement en ligne la deuxième version. Ensuite, vous pouvez exécuter les deux variantes du code les unes contre les autres pour prouver (a) que le mode manuel est efficace, et (b) que le code lisible et manuellement introduit le même résultat. Cependant, avant de commencer manuellement, il existe un moyen simple de répondre à votre question: Écrivez quelques cas de test simples dans les deux sens, puis exécutez quelques millions d'itérations et voyez quelle approche s'exécute plus rapidement. Cela vous apprendra beaucoup sur ce qui se passe et vous donnera une réponse précise pour votre implémentation particulière et compilateur que vous n'obtiendrez jamais des réponses théoriques que vous recevrez ici.

+0

Merci, je suis allé de l'avant et jonché mon code avec quelques #ifdefs pour tester les versions manuelles écrites vs opérateurs. Le code vectoriel était en fait légèrement plus rapide (quelques centaines de millisecondes plus vite). Pas beaucoup comparé à la durée d'exécution de plusieurs minutes, mais c'est certainement quelque chose de considérable. –

2

Je voudrais regarder dans l'autre sens; en commençant par la classe Vector, et si vous rencontrez des problèmes de performances avec cela, vous pouvez voir si l'introduction manuelle des calculs est plus rapide. En plus des performances, vous mentionnez également que les calculs doivent être précis. Avoir les calculs spécifiques au vecteur dans une classe signifie qu'il est plus facile de les tester individuellement, et aussi que le code utilisant la classe devient plus court et plus facile à maintenir.