Pourquoi mon C ++ app plus rapide que mon application C (en utilisant la même bibliothèque) sur un Core i7

StackOverflow https://stackoverflow.com/questions/2054477

Question

J'ai une bibliothèque écrite en C et j'ai 2 applications écrites en C ++ et C. Cette bibliothèque est une bibliothèque de communication, de sorte que l'un des appels API ressemble à ceci:

int source_send( source_t* source, const char* data );

Dans l'application du code C fait quelque chose comme ceci:

source_t* source = source_create();
for( int i = 0; i < count; ++i )
    source_send( source, "test" );

Où que l'application C ++ fait ceci:

struct Source
{
    Source()
    {
        _source = source_create();
    }

    bool send( const std::string& data )
    {
        source_send( _source, data.c_str() );
    }

    source_t* _source;
};

int main()
{
    Source* source = new Source();
    for( int i = 0; i < count; ++i )
        source->send( "test" );
}

Sur un processeur Intel Core i7 le code C ++ produit presque exactement 50% plus de messages par seconde .. Alors que sur un processeur Intel Core 2 Duo, il produit presque exactement la même quantité de messages par seconde. (Core i7 a 4 noyaux avec 2 fils de traitement chacun)

Je suis curieux de savoir ce genre de magie le matériel effectue pour retirer ceci. J'ai quelques théories mais je pensais que je recevrais une vraie réponse:)

Modifier: Informations complémentaires des commentaires

compilateur Visual C ++ est, de sorte que ceci est une boîte de fenêtres (les deux)

La mise en œuvre de la bibliothèque de communication crée un nouveau thread pour envoyer des messages sur. Le source_create est ce qui crée ce fil.

Était-ce utile?

La solution

De l'examen seul votre code source, je ne vois aucune raison pour laquelle le code C ++ devrait être plus rapide.

La prochaine chose que je voudrais faire est de vérifier le code de montage qui est généré. Si vous utilisez un GNU toolchain, vous avez deux façons de le faire.

Vous pouvez demander gcc et g ++ pour la sortie du code assembleur via l'argument de ligne de commande -S. Assurez-vous que d'autres puis en ajoutant cet argument, vous utilisez exactement les mêmes arguments de ligne de commande que vous faites pour une compilation régulière.

Une deuxième option consiste à charger votre programme avec gdb et utilisez la commande disas.

Bonne chance.

Mise à jour

Vous pouvez faire la même chose avec la suite Microsoft.

Pour obtenir le compilateur à l'assemblage de sortie, vous pouvez utiliser / FA ou / les autorités fédérales. Le premier ensemble de sortie doit seulement tandis que le second mélangera l'assemblage et la source (qui devrait le rendre plus facile à suivre).

En ce qui concerne l'utilisation du débogueur, une fois que vous avez le débogueur démarré dans Visual Studio, accédez à. "Debug | Fenêtres | désassemblage" (vérifié sur Visual Studio 2005, d'autres versions peuvent varier)

Autres conseils

Sans voir le code complet ou de l'ensemble de mon mieux conjecture est que le compilateur C ++ est inline pour vous. L'une des beautés de c ++ compilateurs est la capacité à inline à peu près tout pour la vitesse, et les compilateurs de Microsoft sont bien connus en ligne presque à titre gratuit du point de executables de fin sans raison ballonnements.

La première chose que je recommande de faire est le profil des deux versions et voir s'il y a des différences noticable.

Est-ce quelque chose de copie de la version C inutilement (il pourrait être une optimisation subtile ou pas si subtiles comme l'optimisation de la valeur de retour).

Cela devrait apparaître dans un bon profileur, si vous avez une plus fin VS SKU le profileur à base d'échantillonnage est là bon, si vous êtes à la recherche d'un bon profileur gratuitement l'analyseur de performances de Windows est incroyablement puissant pour Vista et jusqu'à < a href = "http://msdn.microsoft.com/en-us/library/dd871254.aspx" rel = "nofollow noreferrer"> voici une procédure pas à pas sur l'utilisation de l'option stackwalking

La première chose que je serais probablement moi-même est briser dans le débogueur et inspecter le démontage pour chaque pour voir si elles sont noticably différentes. Notez qu'il est une option du compilateur pour cracher le asm dans un fichier texte.

Je suivrai cela avec un profil s'il n'y avait pas quelque chose saute aux yeux (comme une copie supplémentaire).

Une autre chose, si vous êtes inquiet au sujet des discussions hyper obtenir de la manière, le processus dure affinitize à un noyau non HT. Vous pouvez le faire soit via le gestionnaire des tâches dans l'interface graphique ou via SetThreadAffinityMask.

-Rick

Core i7 sont de hyper-thread - Avez-vous activé HT

?

Peut-être que le code C ++ est en quelque sorte compilé pour tirer parti du HT alors que le code C ne fonctionne pas. Qu'est-ce que le gestionnaire de tâches ressembler lorsque vous utilisez votre code? Répartir la charge sur le nombre de cœurs, ou quelques noyaux maxed?

Juste une supposition sauvage: Si vous compilez la source de la bibliothèque ainsi que votre application, et les fonctions de l'API C ne sont pas déclarés extern « C », alors peut-être la version C ++ utilise une convention différente et en quelque sorte d'appeler plus vite? ?

En outre, si vous compilez la source de la bibliothèque ainsi que votre application, alors peut-être le compilateur C ++ est la compilation de votre source de la bibliothèque en C ++, et est en quelque sorte mieux à l'optimisation de votre compilateur C?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top