Je voudrais comparer la fonction GCC intégrée memcpy code> contre celui de libc. Cependant, toutes les itérations de
-fno-intégrées code> ou
-fno-intégrées-memcpy code> semblent être ignorées.
//g++ -O3 foo.cpp -S or
//g++ -O3 -fno-builtin foo.cpp -S
#include <string.h>
int main() {
volatile int n = 1000;
//int n = 1000;
float *x = new float[1000];
float *y = new float[1000];
memcpy(y,x,sizeof(float)*n);
//__builtin_memcpy(y,x,sizeof(float)*n);
}
3 Réponses :
REMARQUE: parce que vous compilez le code C ++, je ne suis pas sûr à 100% si cela s'applique si cela s'applique.
La norme C nécessite toutes les fonctions de la bibliothèque (sauf indication contraire explicite) avoir une adresse et peut être l'opérande de la Cela force l'utilisation de la fonction réelle, qui doit éviter tout type de définition macro intégrée. P> C'est aussi possible (Lire: probablement) que le & code> Opérateur d'adresse. En effet, il permet de mettre en œuvre certaines fonctions / la plupart des fonctions en tant que macro fonctionnelle, mais devraient toujours se comporter comme une variable / fonction réelle dans certains cas. Pour éviter la version macro de celui-ci, vous avez juste besoin de quelque chose entre le jeton code> memcpy code> et le jeton
( code> (comme @ZACH a fait remarquer, WhitSpace est insuffisant): P>
-O3 code> optimisation analyse pour certains appels de fonction (tels que
memcpy code>) et les remplace par des appels intégrés, quel que soit le
-fno-in-inseditin code>. p> p>
Une version macro de memcpy code> sera toujours étendue avec WhitSpace entre
Memcpy code> et
( code>. Mettre des parenthèses autour du jeton
memcpy code> Cependant, cependant, se comporte comme vous le décrivez.
De plus, je peux dire autorité que -fno-intégré code> est supposé i> pour faire ce que l'OP attend, à tous les niveaux d'optimisation. GCC.GNU. org / onlinedocs / GCC-4.8.1 / GCC / ...
J'ai essayé vos deux suggestions avec GCC et G ++ (ce code compile tout simplement bien en C, donc je ne suis pas sûr que la balise C ++ est meilleure) et ils n'ont pas fait de différence. C'est comme si -O3 code> l'emporte sur tout.
@Zboson Nouveau code> est C ++, pas c; Ce programme devrait I> vous donner une erreur de compilation si elle est placée dans un fichier avec une extension de code code> et compilée avec la commande
gcc code> au lieu de < Code> g ++ code>.
@Zack, oui, tu es correct. J'aurais dû utiliser Malloc pour éviter toute confusion.
@Zack uniquement si c'est une macro d'objet, pas une macro de fonction. La norme C indique explicitement qu'une invocation macro fonctionnelle nécessite non i> espace entre le nom de la macro et la parenthèse d'ouverture
@Trewmcgowen Vous envisagez de macro fonctionnelle Définition i>, pas d'utilisation. N1570 (approximation la plus proche de C2011 disponible sans Payer pour cela): 6.10.3p3 Plus les règles de la grammaire en 6.10.3p {9,10} exigent que les macros fonctionnelles sont définies i> sans espace entre le nom de la macro et la parenthèse ouverte. (1/2)
@Trewmcgowen Toutefois, la prose en 6.10.3p10 (en particulier la phrase commençant par chaque instance ultérieure du nom de macro de type fonction suivie d'un ( code> comme le prochain jeton de prétraitement i > "(Accenseignement mine: WhitSpace n'est pas un jeton de prétraitement)) clairement (Eh bien, si vous êtes habitué à la normale) indique que les macros fonctionnelles sont développés i> même s'il y a une quantité de blancheur de quelque nature que ce soit entre le nom de la macro et le
( code>. (2/2)
Temps de confession: j'ai écrit environ 40% du préprocesseur actuel de GCC. C'était il y a plus de dix ans, mais je suppose que j'ai toujours à peu près la section 6.10 mémorisée.
@Zack impressionnant! Je travaille sur mon propre compilateur C - alors maintenant je suppose que je sais qui se déranger quand je suis coincé;)
J'ai changé de nouveau à Malloc et j'ai modifié le nom du fichier en .C et j'ai essayé vos suggestions. Ils n'ont pas fait de différence. Étrangement sans -Fno-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-intuitin, produit un montage simple sans memcpy et avec celui-ci, il produisit un résultat similaire à g ++ sans
-Fno-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-in-nodal. Donc, l'interrupteur a un effet, mais il a toujours produit du code intégré qui n'appelle pas MEMCY.
Notez que le compilateur est dans ses droits pour optimiser votre programme vers P> -fno-intégré code> et
-fno-intégré-memcpy code> Les deux ont l'effet que vous attendiez avec GCC 4.9.1. Ceci est probablement juste un bogue dans la GCC 4.8.2; Cette combinaison particulière d'options n'est pas largement utilisée.
-ffreestanding code> est un interrupteur associé qui peut avoir l'effet que vous souhaitez avec 4.8.2.
int main() { return 0; }
J'ai essayé -ffreestanding code>. Cela n'a fait aucune différence. Je vais devoir installer GCC 4.9.1 pour vérifier votre réponse.
J'ai regardé la sortie de l'assembly à http://gcc.godbolt.org/ code> et je peux confirmer que
-fno-intégré code> fonctionne comme prévu dans GCC 4.9 et non dans GCC 4.8.1.
J'ai vérifié GCC 4.4 à 4.9 et 4.9 est le seul qui le convient correct.
La CPI le fait-elle correctement aussi. Lorsque je passe -fno-intégré code> utilise
memcpy code> et sans qu'elle utilise
_intel_fast_memcpy code>.
Juste pour être clair, le compilateur n'a pas optimisé le code de code. Il est clair de regarder le code de l'assembleur.
@Zboson oui. Je disais juste que c'est aurait pu avoir i>. De plus, Clang fait i>. J'ai déposé un bug sur GCC: gcc.gnu.org/bugzilla/show_bug.cgi ? id = 62112
BTW, je ne sais toujours pas comment supprimer le code intégré dans GCC 4.8. Est-ce que ma seule option de mise à niveau vers GCC 4.9?
@Zboson il ressemble à ça. Je doute que les personnes du GCC considèrent que cela soit un bogue assez important pour corriger la série 4.8.x, bien que vous puissiez certainement essayer de le signaler ( GCC.GNU.ORG/BUGZILLA ).
Si vous voulez savoir pourquoi je me soucie de cela, il s'agit de Optimisation du manuel C ++ . Voir la section 2.6 "Comparaison des bibliothèques de fonction". Il affirme que MemCy de GCC de GCC intégré et de glibc sous-performance (et que ce sont les pires). En utilisant son asmlib, je peux le voir fonctionner beaucoup mieux que MemCy de Glibc. Je n'ai pas encore comparé à la fonction intégrée. Il recommande d'utiliser -fno-intégré code>.
@Zboson Dans la mesure où ce document est correct, signaler que i> comme un bogue dans GCC et / ou glibc et c'est i> sera pris au sérieux. Cependant, des travaux substantiels sont entrés dans une optimisation des fonctions de chaîne dans GCC 4.9 et GLIBC 2.19; Je ne serais pas surpris si ce document était maintenant inexact.
J'ai comparé le memcpy intégré de GCC 4.8 et 4.9 (que j'ai installé aujourd'hui) et ils semblent l'efficacité maintenant. Cependant, Glibc 2.19 est toujours assez lent que l'asmlib. Je pense que l'asmlib utilise des magasins non temporels ( _mm_stream_ps code>) pour les grandes tailles. Mais le code intégré doit être une constante de temps de compilation et inférieure ou égale à 8192. Donc, j'ai donc loin autour du bogue code> -Fno-in-in-in-in-in-in-in-in-in-in-in-in-in (code> pour GCC 4.8.
Désolé de Belabor Ce point, mais je viens de télécharger glibc 2.19, l'a compilée et l'a installée et il est maintenant aussi rapide que l'asmlib que vous avez dit. Ce que j'ai comparé au début, c'était Eglibc 2.19 qui est la valeur par défaut sur Ubuntu / Debian (jusqu'à la prochaine version). Cela fait une énorme différence.
Une partie probable de votre problème est avec GLIBC, pas GCC. Vous n'avez pas spécifié, mais vous utilisez probablement Ubuntu, qui définit -d_fortify_source = 2 code> par défaut. Ceci invite les en-têtes GLIBC à fournir une définition inline de
memcpy code> qui transmet à
__ memcpy_chk code>. P>.
Je viens de remarquer que dans cette question et vos commentaires, vous avez mal orthographié
-fno-intégré code> plusieurs façons différentes. Vérifiez que cela ne jette pas vos résultats. L'orthographe correcte est "b u je suis je n".
@Zack, merci d'avoir trouvé les orthographes. J'espère que je les ai tous réparés. J'ai vraiment été un peu trop bâclé (j'ai aussi utilisé
nouveau code> quand j'aurais dû utiliser Malloc dans mon exemple de test - dans mon propre code, j'utilise
_mm_malloc code> quand même). Mais GCC se plaint si j'utilise l'une des distinctions. Mais si vous souhaitez vérifier vous-même, déposez-vous le code ci-dessus (Supprimer le volatil) dans gcc.godbolt.org et Changer de GCC 4.8 ou 4.9, ajoutez
-fno-intégré code> et regardez le code de montage.
@Zack, assurez-vous d'ajouter
-O3 code> aussi.