32 votes

Code C ++ accéléré

Je suis en train d’écrire une application de calcul de chiffres C ++, où le goulot d’étranglement est une fonction qui doit calculer pour double:

  template<class T> inline T sqr(const T& x){return x*x;}
 

et un autre qui calcule

 Base   dist2(const Point& p) const
       { return sqr(x-p.x) + sqr(y-p.y) + sqr(z-p.z); }
 

Ces opérations prennent 80% du temps de calcul. Je me demande si vous pouvez suggérer des approches pour accélérer les choses, même en cas de perte de précision

Merci

14voto

guesser Points 599

Tout d'abord, assurez-vous que dist2 peut être incorporé (il n'est pas clair à partir de votre post si c'est le cas), après avoir défini dans un fichier d'en-tête si nécessaire (généralement vous aurez besoin de faire cela - mais si votre compilateur génère du code au moment de la liaison, alors ce n'est pas nécessairement le cas).

En supposant architecture x86, assurez-vous de laisser votre compilateur pour générer le code à l'aide d'instructions SSE2 (un exemple d'un jeu d'instructions SIMD) s'ils sont disponibles sur l'architecture cible. Pour donner le compilateur la meilleure opportunité pour optimiser ces, vous pouvez essayer de votre lot sqr l'ensemble des opérations (instructions SSE2 devrait être en mesure de faire jusqu'à 4 float ou 2 double d'opérations à la fois selon l'instruction.. mais bien sûr, il ne peut le faire que si vous avez les entrées à plus d'une opération sur le prêt). Je ne voudrais pas être trop optimiste quant à la capacité du compilateur de comprendre qu'il peut leur lot.. mais vous pouvez au moins configurer votre code de façon à ce qu'il serait possible, en théorie.

Si vous n'êtes toujours pas satisfait de la vitesse et vous n'avez pas confiance en votre compilateur est de le faire le mieux, vous devriez regarder dans l'aide du compilateur intrinsèques qui va vous permettre d'écrire le potentiel parallèle des instructions explicitement.. ou sinon, vous pouvez aller de l'avant et d'écriture spécifique à l'architecture de l'assemblée de code pour profiter de SSE2 ou selon les instructions sont les plus appropriées à votre architecture. (Avertissement: si vous à la main le code de l'assemblée, soit de prendre des précautions supplémentaires qu'il obtient toujours inline, ou de le mettre dans une grande opération de traitement)

Pour aller encore plus loin, (et comme glowcoder l'a déjà mentionné), vous pouvez effectuer ces opérations sur un GPU. Pour votre cas particulier, gardez à l'esprit que le GPU est souvent ne prennent pas en charge en virgule flottante double précision.. si si c'est un bon ajustement pour ce que vous faites, vous allez obtenir des ordres de grandeur de meilleures performances de cette façon. Google pour le GPGPU, ou autre chose et de voir ce qui est le mieux pour vous.

10voto

Stephen Points 16714

Qu'est - Base?

C'est une classe avec un non-explicite du constructeur? Il est possible que vous êtes en train de créer une bonne quantité de temporaire Base objets. Ça pourrait être un gros CPU porc.

template<class T> inline T sqr(const T& x){return x*x;}
Base   dist2(const Point& p) const {
  return sqr(x-p.x) + sqr(y-p.y) + sqr(z-p.z);
}

Si p's variables membres sont de type Base, vous pourrait être l'appel de sqr sur les objets de Base, qui sera la création d'temporaires pour la soustraction des coordonnées, en sqr, puis pour chaque composant ajouté.

(Nous ne pouvons pas dire sans les définitions de classe)

Vous pourriez probablement accélérer en forçant le sqr appels sur primitves et de ne pas utiliser Base jusqu'à ce que vous obtenez pour le type de retour d' dist2.

D'autres possibilités d'amélioration de la performance sont les suivants:

  • L'utilisation non d'opérations en virgule flottante, si vous êtes ok avec moins de précision.
  • Utiliser des algorithmes qui n'ont pas besoin d'appeler dist2 tellement, éventuellement, la mise en cache ou à l'aide de la propriété transitive.
  • (c'est sans doute évident, mais) assurez-vous que vous compilez avec l'optimisation activée.

8voto

Salgar Points 4803

Je pense que l'optimisation de ces fonctions peut être difficile, vous feriez mieux d'optimiser le code qui appelle ces fonctions pour les appeler moins ou pour faire les choses différemment.

8voto

Glen Points 13521

Vous ne dites pas si les appels à dist2 peuvent être mis en parallèle ou non. S'ils le peuvent, vous pouvez créer un pool de threads et scinder ce travail en morceaux plus petits par thread.

Qu'est-ce que votre profileur vous dit se passe dans dist2 . Utilisez-vous réellement 100% de la totalité du temps ou cachez-vous et attendez-vous le chargement des données?

Pour être honnête, nous avons vraiment besoin de plus de détails pour vous donner une réponse définitive.

6voto

Fred Larson Points 27404

Si sqr() est utilisé uniquement sur des types primitifs, vous pouvez essayer de prendre l'argument par valeur plutôt que par référence. Cela vous éviterait un indirection.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X