IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Performance d'un memcpy


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 65
    Par défaut Performance d'un memcpy
    Bonjour,

    J'ai entendu dire qu'un memcpy était plus performant à partir de la copie de 2 ou 3 octets qu'un assignement (struct A = struct B). J'aimerais avoir votre avis.

    Imaginons que j'ai un buffer d'octets et que dans un cas, je veuille y mettre un entier. Vaut-il mieux faire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    char buffer[256];
    int value = 0;
    memcpy(buffer, &value, sizeof(value));
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    char buffer[256];
    int value = 0;
    (int)buffer[0] = value;
    Personnellement, la deuxième solution me pique les yeux, mais peut-être qu'elle serait plus efficace niveau performance, non ?

    Julien.

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Bonjour,

    La réponse est assez simple, la deuxième méthode ne compile pas :
    Citation Envoyé par g++
    main.cpp: In function ‘int main()’:
    main.cpp:6:18: error: lvalue required as left operand of assignment
    Ensuite il ne me semble pas qu'on puisse faire sans définir un opérateur d'affectation ou un opérateur de conversion.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 65
    Par défaut
    Oui effectivement, je n'ai rien pour tester la compil sur place, mais c'est juste pour le principe. Ou alors, le code suivant peut-être compilerait:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    char *buffer = NULL;
    int value = 0;
     
    buffer = (char *)malloc(256 * sizeof(char));
    if(buffer != NULL)
    {
       ((int *)buffer)[0] = value;
    }
    Enfin bref, je sais qu'en cast, cela est possible. Mais personnellement, je n'aime vraiment pas caster, je ne trouve pas cela "safe". Qu'en penses-tu ? Est-ce vraiment choquant de faire un memcpy pour un int ?

  4. #4
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Khan34 Voir le message
    Bonjour,

    J'ai entendu dire qu'un memcpy était plus performant à partir de la copie de 2 ou 3 octets qu'un assignement (struct A = struct B). J'aimerais avoir votre avis.
    Ma réponse est : meh ?

    Avant de dire ce genre de chose, un bon conseilleur (ah bon ? c'est un mot ça ?) se doit de bien connaître son sujet. Il semblerait que là, tu sois tombé sur des personnes dont les connaissances en la matière sont douteuses. Et notamment sur ce point : si tu peux utiliser memcpy() pour copier une structure autre part, alors le compilateur le sait - et à la place de ta copie de structure, il mettra un memcpy() (la forme intrinsic, c'est à dire la même forme que toi).

    Ensuite, memcpy ne peut pas être plus rapide à partir de 2 ou 3 octets - il faut au moins 2 opérations pour copier 3 octets, il en faut une pour en copier 4.

    La où memcpy() gagne par rapport à l'opérateur d'affectation, c'est lorsque tu as une bonne quantité de données à copier. Le nombre exact dépends de plein de choses, et ne peut s'obtenir que par des mesures.

    Par contre, tu peux être sûr d'une chose : tu n'arriveras pas à battre memcpy(). Beaucoup de gens, chacun bien plus intelligent que toi et moi réunis, ont passé des années et des années à optimiser cette fonction sur les différentes architectures processeur. Le résultat est un code très complexe (ou plutôt très subtil) et très, très rapide.

    Citation Envoyé par Khan34 Voir le message
    Oui effectivement, je n'ai rien pour tester la compil sur place, mais c'est juste pour le principe. Ou alors, le code suivant peut-être compilerait:
    Un truc de pro (enfin presque) : http://www.compileonline.com/compile_cpp_online.php

    Je rajoute que là, tu ne fais pas une copie - tu fait une initialisation (donc le pendant de memset()). Ceci dit, c'est une fonction aussi bien optimisée que memcpy().

    Pour info : la version Apple de memset (en assembleur) : http://www.opensource.apple.com/sour...tring/memset.s
    On y entrevoit l'utilisation de SSE, la gestion de l'alignement des accès mémoire, et, en lisant attentivement le code, le travail alternatif sur les deux pipelines parallèle du x86 (une instruction sur deux va dans le premier pipeline, l'autre va dans le second pipeline ; et oui, le x86 est superscalaire, et peut exécuter deux instructions par cycle sous certaines conditions).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 65
    Par défaut
    Merci pour ta réponse.

    Très sympas le site, je ne connaissais pas.

    Pour ce qui est de l'exemple, il s'agit d'une initialisation parce que j'ai pris comme exemple une valeur égale à 0. Mais ce n'est qu'un exemple.

    En bref, le memcpy est très efficace et très rapide. Et du coup, petite question toute bête (enfin je crois): si tu dois copier un "int" dans un buffer type "char []", comment ferais-tu ? Avec ou sans memcpy ?

    Julien.

  6. #6
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Khan34 Voir le message
    Merci pour ta réponse.

    Très sympas le site, je ne connaissais pas.

    Pour ce qui est de l'exemple, il s'agit d'une initialisation parce que j'ai pris comme exemple une valeur égale à 0. Mais ce n'est qu'un exemple.

    En bref, le memcpy est très efficace et très rapide. Et du coup, petite question toute bête (enfin je crois): si tu dois copier un "int" dans un buffer type "char []", comment ferais-tu ? Avec ou sans memcpy ?

    Julien.
    Avec memcpy, pour une bonne raison : c'est 20 fois plus lisible, et il y a 20 fois moins de chances d'erreurs (de plus, au cas où les adresses ne sont pas alignées, ça ne va pas générer de SIGBUS sur les architecture nécessitant des accès alignées pour les opérations affectant 32 bits - même si ce type d'architecture matérielle est de plus en plus rare).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 65
    Par défaut
    Ok, merci !

    Julien.

  8. #8
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 391
    Par défaut
    Généralement si je dois copier un int dans un buffer de type char[], il y a des chances que je doives me soucier de l'endianness, auquel cas je ferais le boulot manuellement, octet par octet. Puis je regrouperai tout ça dans une fonction serialize_int().
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Membre émérite
    Avatar de Kirilenko
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    234
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 234
    Par défaut
    Bonsoir,

    Je rejoins Emmanuel Deloget sur l'ensemble de sa réponse ; memcpy est aujourd'hui un built-in sur le compilateur typique et décent, en fonction d'un tas de paramètres dans les appels dont seul le compilateur est au courant. D'ailleurs, ce qui est assez drôle, c'est qu'il n'y a pas d'instruction toute faite pour l'affectation de structures. Du coup, un compilateur intelligence a de fortes chances de privilégier une solution... à base de memcpy. Ce à quoi le code inliné ressemble dépendra fortement des hypothèses que le compilateur aura confirmé ou infirmé.

    • La taille à copier. Si on a une instruction (qui peut être vectorisée) qui permet de faire des copies d'une taille donnée, on peut faire quelques déroulements de boucle et analyse d'aliasing pour savoir si ça vaut le coup. Ce genre de copies dépend également du deuxième facteur. Si on a une taille première, on peut s'amuser à faire des copies de tailles multiples décroissantes.
    • L'alignement de la zone. Le problème sur les architectures un peu laxistes comme x86, c'est que les accès non alignés sont autorisés ; il faudra donc gérer tous les cas.


    Bref, ça donnera le plus souvent beaucoup de conditions compliquées, que les concepteurs de compilateur n'ont pas forcément l'envie d'intégrer (disons, sur les vieux modules rouillés des non-optimisants, type PCC).

    Bonne soirée !
    Récursivité en C : épidémie ou hérésie ?

    "Pour être un saint dans l'Église de l'Emacs, il faut vivre une vie pure. Il faut se passer de tout logiciel propriétaire. Heureusement, être célibataire n'est pas obligé. C'est donc bien mieux que les autres églises" - Richard Stallman

Discussions similaires

  1. memcpy performances ?
    Par Jérôme_C dans le forum Bibliothèque standard
    Réponses: 3
    Dernier message: 24/05/2012, 09h27
  2. [maintenance][performance] Que faire comme maintenance ?
    Par woodwai dans le forum PostgreSQL
    Réponses: 5
    Dernier message: 06/11/2003, 15h39
  3. [ POSTGRESQL ] Problème de performance
    Par Djouls64 dans le forum PostgreSQL
    Réponses: 6
    Dernier message: 26/05/2003, 16h18
  4. [JDBC][connexion persistante] performances avec JDBC
    Par nawac dans le forum Connexion aux bases de données
    Réponses: 6
    Dernier message: 06/05/2003, 10h37
  5. performance entre 3DS, ase, asc ...
    Par amaury pouly dans le forum OpenGL
    Réponses: 3
    Dernier message: 24/03/2003, 11h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo