2010-05-21 15 views
2

J'écris un ray tracer. Récemment, j'ai ajouté un thread au programme pour exploiter les cœurs supplémentaires sur mon i5 Quad Core.Pourquoi mon code s'exécute-t-il plus lentement avec plusieurs threads qu'avec un seul thread lorsqu'il est compilé pour le profilage (-pg)?

Dans un étrange tour d'événements, la version de débogage de l'application s'exécute maintenant plus lentement, mais la version optimisée s'exécute plus rapidement qu'avant d'ajouter le thread.

Je passe les drapeaux "-g -pg" à gcc pour la construction de débogage et le drapeau "-O3" pour la construction optimisée.

Système hôte: Ubuntu Linux 10.4 AMD64.

Je sais que les symboles de débogage ajoutent une surcharge significative au programme, mais les performances relatives ont toujours été maintenues. C'est à dire. un algorithme plus rapide s'exécutera toujours plus vite dans les versions de débogage et d'optimisation.

Une idée de pourquoi je vois ce comportement?

La version de débogage est compilée avec "-g3 -pg". Version optimisée avec "-O3".

Optimized no threading:  0m4.864s 
Optimized threading:   0m2.075s 

Debug no threading:   0m30.351s 
Debug threading:    0m39.860s 
Debug threading after "strip": 0m39.767s 

Debug no threading (no-pg): 0m10.428s 
Debug threading (no-pg):  0m4.045s 

Cela me convainc que « -g3 » n'est pas à blâmer pour le delta de la performance étrange, mais qu'il est plutôt le commutateur « -pg ». Il est probable que l'option "-pg" ajoute une sorte de mécanisme de verrouillage pour mesurer la performance du fil.

Comme "-pg" est brisé sur les applications filetées de toute façon, je vais juste l'enlever.

+1

'strip' votre version de débogage, mesurez les performances de la version de débogage supprimée et ajoutez cette information à votre question. –

+0

Je vais y aller, merci. – fluffels

+1

'-pg' n'ajoute pas de symboles de débogage, donc votre question est erronée. La réponse à la question "Pourquoi les symboles de débogage affectent-ils négativement les performances" est "ils ne le font pas". –

Répondre

8

Qu'est-ce que vous obtenez sans le drapeau -pg? Ce ne sont pas des symboles de débogage (qui n'affectent pas la génération de code), c'est pour le profilage (ce qui est le cas).

Il est tout à fait plausible que le profilage dans un processus multithread nécessite un verrouillage supplémentaire qui ralentit la version multithread, même au point de la rendre plus lente que la version non multithread.

+0

C'est une bonne idée, je vais tester ça. – fluffels

+2

-pg active le profilage gprof et, comme le suggère la réponse, ralentira le code. –

2

Vous parlez de deux choses différentes ici. Symboles de débogage et optimisation du compilateur. Si vous utilisez les paramètres d'optimisation les plus puissants que le compilateur a à offrir, vous le faites à la suite de la perte de symboles utiles au débogage.

Votre application ne s'exécute pas plus lentement en raison des symboles de débogage, son exécution est ralentie en raison d'une optimisation moindre effectuée par le compilateur.

Les symboles de débogage ne sont pas des «frais généraux» au-delà du fait qu'ils occupent plus d'espace disque. Le code compilé à l'optimisation maximale (-O3) ne doit pas être l'ajout de symboles de débogage. C'est un drapeau que vous définiriez lorsque vous n'avez pas besoin de ces symboles.

Si vous avez besoin de symboles de débogage, vous les gagnez au détriment de l'optimisation du compilateur. Cependant, encore une fois, ce n'est pas un «overhead», c'est juste l'absence d'optimisation du compilateur.

+0

Je sais quelle est la différence entre les symboles de débogage et l'optimisation. Le problème que je vois est que les performances relatives de deux algorithmes sont différentes dans la version optimisée et la version de débogage. – fluffels

+0

@fluffels - Je ne vois pas pourquoi c'est inattendu? –

+0

Je m'attendais à ce que les symboles/optimisations de débogage aient plus ou moins le même effet sur les deux algorithmes, maintenant les performances relatives entre eux. Rétrospectivement, cela semble naïf. Mais puisque le deuxième algorithme est threadé et que le problème est très parallèle, je m'attendais toujours à ce que la performance relative reste la même. Je veux juste savoir * pourquoi * j'avais tort;) – fluffels

2

Le code de profil qui insère des appels d'instrumentation a-t-il suffisamment de fonctions pour vous blesser?
Si vous faites un seul pas au niveau de la langue d'assemblage, vous le découvrirez assez rapidement.

+0

Bonne idée, merci. Je vais y jeter un coup d'œil. – fluffels

0

Le temps d'exécution du code multithread n'est pas toujours mesuré comme prévu par gprof. Vous devez synchroniser votre code avec un autre minuteur en plus de gprof pour voir la différence.

Mon exemple: Exécution du benchmark LULESH CORAL sur un nœud de 2NUMA Pont de sable INTEL (8 cœurs + 8 cœurs) de taille 50 et 20 itérations -i, compile avec gcc 6.3.0, -O3, j'ai:

avec 1 fil conducteur: ~ sans -pg 3,7- et ~ avec elle 3,8, mais selon l'analyse gprof le code a couru seulement pour 3,5.

de 16 fils en cours d'exécution: ~ 0,6 sans -pg et ~ 0,8 avec elle, mais selon l'analyse gprof le code a couru pour ~ 4,5 ...

Le temps dans gras a été mesurée gettimeofday, en dehors de la région parallèle (début et fin de la fonction principale). Par conséquent, peut-être que si vous auriez mesuré le temps de votre application de la même manière, vous auriez vu le même speeduo avec et sans -pg. C'est juste la mesure gprof qui est fausse en parallèle. En LULESH version openmp de toute façon.