Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1037 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Attention ca va faire mal : template,inlining et AltiVec en autres

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Attention ca va faire mal : template,inlining et AltiVec en autres

n°370437
Joel F
Real men use unique_ptr
Posté le 24-04-2003 à 14:20:33  profilanswer
 

Quelques questions :
 
1. Y a t il un eoption sous gcc/g++ pour obtenir les fichiers sources intermedaires dans lesquels se trouveraient toue les templates que j'ai pu utilisé mais sous forme instanciée, si vous voyez ce que je veux dire ? j'ai chercher dans le manuel mais j'ai rien trouver.
 
2. Quelles sont exactements l slimitations d'une variable register ? Je sais qu'on peut pas en prendre l'adresse mais peut on prendre un reference dessus ou tout autre moyen de la refenrencer ?
 
3. Quelles sont les conditions generales de l'inlining des meta-programmes templates ? Se deroulent ils tous ? ou partiellement ou pas du tout selon leur contenu ?
 
4.Enfin, une derniére pour les gens qui connaissent un peu AltiVec.
Quel est la difference de perf entre  
 
 

Code :
  1. register __vector float a,b,c,r;
  2. for(inti=0;i>NBVECTOR;i++)
  3. {
  4.   a = vec_ld(i,data1);
  5.   b = vec_ld(i,data2);
  6.   c = vec_ld(i,data3);
  7.    vec_st( vec_add(a,vec_add(b,c)),i,result);
  8. }

 
 
et
 

Code :
  1. register __vector float a,b,c,r;
  2. for(inti=0;i>NBVECTOR;i++)
  3. {
  4.    a = vec_ld(i,data1);
  5.    b = vec_ld(i,data2);
  6.    c = vec_ld(i,data3);
  7.    r = vec_add(b,c);
  8.    r = vec_add(a,r);
  9.    vec_st( r,i,result );
  10. }

 
 
Merci d'avance  [:joel f]

mood
Publicité
Posté le 24-04-2003 à 14:20:33  profilanswer
 

n°370489
bjone
Insert booze to continue
Posté le 24-04-2003 à 14:58:25  profilanswer
 

pour le 1) sais pas, mais pour le 2,3,4 ça dépends totallement de ton compilateur, et des options que tu as passé en paramètres ou dans le makefile.
 
la seule chose que je puisse te dire, c'est de contrôler le code asm produit en demandant au compilo de te sortir un listing.
 
ensuite pour tout ce qui est inliné, le compilo inline tout, mais si un moment tu utilises une référence sur une routine d'inlinée, le compilo produira du code inlinée et une version normale quie sera appellée (par call/ret ou brs/rts).  
(et la référence pointera sur la version normale).
 
dans les cas des templates, ça produit généralement du code inliné (le compilo fera plus facilement du inline avec une template qu'avec une classe standard).
 
pour le 4), si le compilo est au max de ses optimisations et que c'est un bon compilo, il devrait produire le même code machine dans les deux cas.
 
le mot clé register est souvant un faux-ami, car un bon compilo utilisera automatiquement les registres et ce de manière intelligente & dynamique.
 
alors que si tu forçes des variables en register, il risque de bloquer un registre pour une variable, alors que le registre aurait été plus utile pour autre chose.
 
par exemple ça c'est débile:
 

Code :
  1. register int i;
  2. for( i=0 ; i < maxi ; i++ )
  3.   for( int j=0 ; j < maxj ; j++ )
  4.   {
  5.     //innerloop de quelque chose
  6.   }


 
ça c'est cohérent d'un point de vue optimisation:
 

Code :
  1. for( int i=0 ; i < maxi ; i++)
  2. {
  3.   register int j;
  4.   for( j=0; ; j < maxj ; j++)
  5.   {
  6.      // innerloop
  7.   }
  8. }


 
mais je dirais que si le compilo optimise bien, il choisira automatiquement quand quelque chose doit être maintenu dans un registre et le fera tout le temps...
---
 
donc tout ceci est sujet à variations de compilateur à compilateur et suivant les options que tu lui passes.
 
mais je dirais, ayant codé en asm, et controlant de temps ce que produit un compilo, l'inline c'est bien pour les fonctions utilisée à haute-fréquence, mais le mot-clé register c'est soit inutile si c'est un bon compilo, soit c'est mal, soit c'est à utiliser uniquement en ayant décortiqué le code machine produit, et ayant une connaissance aigue du cpu.
 


Message édité par bjone le 24-04-2003 à 15:07:37
n°370500
bjone
Insert booze to continue
Posté le 24-04-2003 à 15:01:51  profilanswer
 

je suis persuadé (enfin quasiement), que si tu compiles les deux routines précédentes, le code machine sera le même.
et ptet même (voir très certainement) si tu fait la même routine sans le mot-clé register.

n°370506
bjone
Insert booze to continue
Posté le 24-04-2003 à 15:05:28  profilanswer
 

sinon vu que tu sembles être sur un powerpc, codewarrior ne serait-il pas à recommander ?
(en fait je sais pas quels sont les meilleurs compilos pour ppc)

n°370586
Joel F
Real men use unique_ptr
Posté le 24-04-2003 à 15:47:14  profilanswer
 

Merci bien :D
 
disons que pour l'instant je suis sur un PPC G4 avec Linux dessus (beurk) mais normalement je devrais pouvoir travailler sur un mac OS X tres bientot. Est-ce que Project Builder sera suffisant ?
 
J'ai tester effectivement avec et sans register etc ... et oui le code asm est le même donc ca me rassure.
 
Ensuite, question a deux francs, l'ordre des operations AltiVec est il important ?
 
Style
 

Code :
  1. r1 = vec_ld(0,data);
  2. r2 = vec_ld(0,data);
  3. r3 = vec_ld(0,data);
  4. r4 = vec_ld(0,data);
  5. t1 = vec_add( r1,r3);
  6. t2 = vec_add( r2,r4);


 
ou
 

Code :
  1. r1 = vec_ld(0,data);
  2. r3 = vec_ld(0,data);
  3. t1 = vec_add( r1,r3);
  4. r2 = vec_ld(0,data);
  5. r4 = vec_ld(0,data);
  6. t2 = vec_add( r2,r4);


 
Sinon voila :D merci bien ;)

n°370616
bjone
Insert booze to continue
Posté le 24-04-2003 à 15:57:27  profilanswer
 

PS: j'ai jamais codé sur ppc, et le 68k c'est scolaire, je transpose donc mes expériences d'optimisation sur pentium en asm et via des compilateurs optimiseurs (watcom rulez à l'époque du pentium 1)...
 
donc je dirais que pour ton exemple, je pense que le compilateur sera capable de réorganiser les instructions pour obtenir quelque chose d'optimal.
 
mais l'ordre en lui même peut avoir une influance sur l'éfficacité des caches et des accès mémoires. notemment en sse sur les x86, il y a des instruction qui permettent des chargement anticipés des éléments suivants.... (et de savoir si il existe des instructions de prefetch forcé)
 
je pense qu'à partir de là il faut se bouffer de la doc sur le cpu et savoir quel séquencement d'accès mémoire te donnera la meilleure efficacité...


Message édité par bjone le 24-04-2003 à 16:03:26
n°370636
bjone
Insert booze to continue
Posté le 24-04-2003 à 16:02:36  profilanswer
 

maintenant j'ai ptet dit des conneries dans mes posts, c'est pointu de savoir ce que le compilo va faire, et ce qu'il faudrait faire....
 
donc comme j'ai le ppc je le connais pas plus que "ça", mais tout ce que j'ai pu te dire c'est relativement des généralitées...

n°370809
nraynaud
lol
Posté le 24-04-2003 à 17:28:32  profilanswer
 

BJOne a écrit :

je suis persuadé (enfin quasiement), que si tu compiles les deux routines précédentes, le code machine sera le même.
et ptet même (voir très certainement) si tu fait la même routine sans le mot-clé register.


Y'as très peu de chances, mettre le mot-clef "register" colle la variable dans un registre, obligeant l'allocateur de registres à tenir compte de la contrainte, il a donc un registre de moins pour travailler. D'après les articles que j'ai lu (je me souviens plus à quelle ocasion, O'caml peut-être), c'est généralement une mauvaise idée car si la variable est active, elle sera naturellement mise en registre, mais si elle est inactive elle sera virée du registre, le rendant dispo pour les autres variables plus actives. Avec "register" elle est scotchée, active ou pas, donc les variables plus actives on moins de place dans les registres.

n°370829
bjone
Insert booze to continue
Posté le 24-04-2003 à 17:35:55  profilanswer
 

nraynaud a écrit :


Y'as très peu de chances, mettre le mot-clef "register" colle la variable dans un registre, obligeant l'allocateur de registres à tenir compte de la contrainte, il a donc un registre de moins pour travailler. D'après les articles que j'ai lu (je me souviens plus à quelle ocasion, O'caml peut-être), c'est généralement une mauvaise idée car si la variable est active, elle sera naturellement mise en registre, mais si elle est inactive elle sera virée du registre, le rendant dispo pour les autres variables plus actives. Avec "register" elle est scotchée, active ou pas, donc les variables plus actives on moins de place dans les registres.


 
je suis tout à fait d'accord, c'est ce que j'ai voulu exprimer par:
 

Citation :


le mot clé register est souvant un faux-ami, car un bon compilo utilisera automatiquement les registres et ce de manière intelligente & dynamique.  
 
alors que si tu forçes des variables en register, il risque de bloquer un registre pour une variable, alors que le registre aurait été plus utile pour autre chose.  


 
en fait ce que je voulais dire, c'est que vu le peu de variables dans son code altivec, je pensais que register était superflu car le compilo aller prendre les registres automatiquement...

n°370942
Kristoph
Posté le 24-04-2003 à 18:56:53  profilanswer
 

nraynaud a *crit :


Y'as tr*s peu de chances, mettre le mot-clef "register" colle la variable dans un registre, obligeant l'allocateur de registres * tenir compte de la contrainte, il a donc un registre de moins pour travailler. D'apr*s les articles que j'ai lu (je me souviens plus * quelle ocasion, O'caml peut-*tre), c'est g*n*ralement une mauvaise id*e car si la variable est active, elle sera naturellement mise en registre, mais si elle est inactive elle sera vir*e du registre, le rendant dispo pour les autres variables plus actives. Avec "register" elle est scotch*e, active ou pas, donc les variables plus actives on moins de place dans les registres.


 
Il me semble de toute facon que la norme prevoit deja d'ignorer completement le mot cle register. En tout cas, gcc le fait.

mood
Publicité
Posté le 24-04-2003 à 18:56:53  profilanswer
 

n°370948
Joel F
Real men use unique_ptr
Posté le 24-04-2003 à 19:04:15  profilanswer
 

Ok odnc, je peut jarter les registers et laissé le compilo faire ce qu'il peut.

n°371093
Taz
bisounours-codeur
Posté le 24-04-2003 à 22:31:38  profilanswer
 

Joel F a écrit :

Ok odnc, je peut jarter les registers et laissé le compilo faire ce qu'il peut.

surtout qu'il le fera certainement mieux que toi

n°371139
sr16
@*#%$*%§!!
Posté le 24-04-2003 à 23:12:12  profilanswer
 

nraynaud a écrit :


Y'as très peu de chances, mettre le mot-clef "register" colle la variable dans un registre, obligeant l'allocateur de registres à tenir compte de la contrainte, il a donc un registre de moins pour travailler. D'après les articles que j'ai lu (je me souviens plus à quelle ocasion, O'caml peut-être), c'est généralement une mauvaise idée car si la variable est active, elle sera naturellement mise en registre, mais si elle est inactive elle sera virée du registre, le rendant dispo pour les autres variables plus actives. Avec "register" elle est scotchée, active ou pas, donc les variables plus actives on moins de place dans les registres.


 
Ca dépends aussi du nombre de registres du CPU. C'est clair qu'un Pentium ça a pas beaucoup de registres et en bloquer un peut avoir des conséquences very nefastes. Mais un PPC je ne sait pas (Je le connait pas). Faut aussi considérer ce point.
Il est probable qu'avec un proco qui ait un tout petit peu plus de registres, la donne change radicalement
 
Le plus simple pour en avoir le coeur net, c'est encore de faire un bench en mettant le truc sous 10.000.000 d'itérations.
 


---------------
TOPIC PERMANENT Matrox Parhelia
n°371148
schnapsman​n
Zaford Beeblefect
Posté le 24-04-2003 à 23:19:09  profilanswer
 

++Taz a écrit :

surtout qu'il le fera certainement mieux que toi


 
toujours le mot aimable hein (même si ca part d'une bonne intention [:zebra33] )


Message édité par schnapsmann le 24-04-2003 à 23:19:28

---------------
From now on, you will speak only when spoken to, and the first and last words out of your filthy sewers will be "Sir!"
n°371154
Taz
bisounours-codeur
Posté le 24-04-2003 à 23:22:21  profilanswer
 

:D

n°371160
bjone
Insert booze to continue
Posté le 24-04-2003 à 23:23:54  profilanswer
 

Sr16 a écrit :


 
Ca dépends aussi du nombre de registres du CPU. C'est clair qu'un Pentium ça a pas beaucoup de registres et en bloquer un peut avoir des conséquences very nefastes. Mais un PPC je ne sait pas (Je le connait pas). Faut aussi considérer ce point.
Il est probable qu'avec un proco qui ait un tout petit peu plus de registres, la donne change radicalement
 
Le plus simple pour en avoir le coeur net, c'est encore de faire un bench en mettant le truc sous 10.000.000 d'itérations.
 
 


 
un chti itanium  [:the one]  
 
n'empêche les registres booléens de prédication c'est de la baboule quand même :D

n°371374
Joel F
Real men use unique_ptr
Posté le 25-04-2003 à 09:09:12  profilanswer
 

Le PPC avec extension AltiVec fournit  registres dédiées au calcul vectoriel.
Normalement ca devrait passer.
 
J'ai fait qqs tests et pour des calculs vectoriels "moyen" (moins de 20 sous expressions) ca passe. C'est donc largement suffisant pour mon utilisation.
 
 
Autre question :
 
J'ai une classe de vecteur template dont voila l'intitulé :
 

Code :
  1. template< class Type,int Size > class Vector;

 
 
J'aimerais bien qu'a la compilation, chaque instance de cette classe
se retrouve pourvue d'un ID numerique unique.
 
J'ai donc pensé à :
 

Code :
  1. template< class Type, int Size, int ID > class Vector;

 
 
ca marche, pas de probleme, mais :
 

Code :
  1. Vector< float,256,1> a;
  2. Vector< float,256,2 > b;

 
 
etc ... c'est lourd pour l'utilisateur.
Je pensais donc crée une espece de classe template qui me  
permettrait d'ecrire :
 

Code :
  1. template< class Type, int Size, int ID=IDGenerator() > class Vector;
  2. Vector< float,256 > a;
  3. Vector< float,256 > b;

 
 
et qui donc genererait les ID de maniére automatique à la compilation.
Manque de bol j'ai beau essayé tout et npquoi j'y arrive pas  :??:  
Suis je un boulet ? vais-je guérir ??
 
Merci d 'avance.
 
 [:joel f]

n°371923
bjone
Insert booze to continue
Posté le 25-04-2003 à 15:02:07  profilanswer
 

mmmm... porké un ID unique :??:

n°372167
Taz
bisounours-codeur
Posté le 25-04-2003 à 17:27:56  profilanswer
 

c'est pas une id unique par instance que tu voudrais, on est bien d'accord?

n°372306
LeGreg
Posté le 25-04-2003 à 20:35:49  profilanswer
 

Joel F a écrit :


Vector< float,256,1> a;
Vector< float,256,2> b;


 
tu as bien conscience que a et b seront de type
different ?
 
Si tu as besoin d'un ID unique par instance
pourquoi ne pas utiliser leur adresse en memoire ?
 
LeGreg

n°372310
bjone
Insert booze to continue
Posté le 25-04-2003 à 20:44:43  profilanswer
 

à la limite autant faire une template qui reprends ta template Vector (ou la template vector<> de la STL), et de rajouter ton attribut d'ID et de jouer avec le constructeur..
 

Code :
  1. template <class T> class supervector : public vector<T>
  2. {
  3. public:
  4. using vector<T>::vector();
  5.         int ID;
  6.         supervector()
  7.         {
  8.             // gna gna gni gni
  9.         }
  10. };

n°372322
nraynaud
lol
Posté le 25-04-2003 à 21:27:51  profilanswer
 

Code :
  1. supervector():// gna gna gni gni
  2.         {}


jouer au bon endroit bien sûr

n°372334
bjone
Insert booze to continue
Posté le 25-04-2003 à 22:13:48  profilanswer
 

c'est comme vous voulez, c'est vous qui voyez ;)

n°372339
nraynaud
lol
Posté le 25-04-2003 à 22:17:55  profilanswer
 

BJOne a écrit :

c'est comme vous voulez, c'est vous qui voyez ;)


c'est pas moi qui veut, c'est le dégarni barbu là -> http://www.research.att.com/~bs/homepage.html

n°372340
bjone
Insert booze to continue
Posté le 25-04-2003 à 22:18:45  profilanswer
 

wé mais quand je me tires dans le pied, j'aime que la jambe vienne avec  [:the one]

n°372495
Joel F
Real men use unique_ptr
Posté le 26-04-2003 à 11:16:04  profilanswer
 

certes, l'ID ne semble pas approprié ...
en fait le probléme est tout autre.
 
J'utilisela technique des 'Expressiosn templates' pour  
générer du code AltiVec inline optimisé à partir d'écriture comme :
 

Code :
  1. Vector<float,100> a,b,c;
  2. a = 2*b +c;


 
qui apres 'deroulage' des templates donne un code équivalent à :
 

Code :
  1. a = vec_madd(splat(2),b,c);


 
Mon probleme est que actuellemnt, j'effectue une simple passe sur mes templates lors de l'évaluation de ces résultats.
A la compilation (compile-time), l'expression 2*b+c est decomposé en opérateurs successifs qui chacun générent le petit bout de code necessaire à effectuer le calcul.
 
Mon probleme est que actuellement le chargement de données depuis les Vector vers les __vector AltiVec se font au fur et à mesure :
 

Code :
  1. a = vec_add(vec_ld(0,b),vec_add(vec_ld(0,c),vec_ld(0,d));


 
Ce qui n'est pas efficace du tout vu mes tests.
 
J'aimerais donc que mes templates se dépleint ainsi :
 

Code :
  1. tmp1 = vec_ld(0,b);
  2. tmp2 = vec_ld(0,c);
  3. tmp3 = vec_ld(0,d);
  4. a = vec_add(tmp1,vec_add(tmp2,tmp3));


 
Ce qui me permettrait de profiter du comportement super-scalaire de l'unité de chargement Altivec.
 
Mon idée etait donc de créer une classe template qui contiendrait des memebre statiques correspondant au 32 registres
AltiVec.
 

Code :
  1. template<class T,int ID>
  2. class RegisterPool
  3. {
  4. public:
  5. static TypeInfo<T> temp;
  6. };


 
TypeInfo<T> etant une classe permettant d'effectuer un typedef du style : __vector T. ID etant un int allant de 1 à 32.
 
Cette classe serait accessible pour chaque type AltiVec (char,short,long,float) comme "pool" de registre.
 
Ensuite lors de l'affectation de mes expressions, j'effectuerais deux passes :
 
1. la premiere passe deplierait les templates en utilisant un parcourt de l'arbre des opérateurs pour générer les vec_ld.
Chaque fois que un template arrive sur une feuille de l'arbre,il ecrit :
 

Code :
  1. Register<T,N>::temp = vec_ld(i,data);


 
2. la deuxieme passe deplie la boucle de traitement la ou y a les vec_add etc .... en utilisant non pas les données MAIS les Register<T,N>::temp correspondant.
 

Code :
  1. Register<T,P>::temp = vec_ld(i,a);
  2. Register<T,N>::temp = vec_ld(i,b);
  3. Register<T,M>::temp = vec_ld(i,c);
  4. Register<T,P>::temp = vec_add(Register<T,N>::temp,Register<T,M>::temp);


 
Le probleme est donc de :
- Assigné à un Register<T,N> UNIQUE un donnée UNIQUE.
- De retrouver lors de la deuxiéme passe kel Register<T,N> correspond a une donnée quelconque.
- De ne charger qu'une fois les données même si elles apparaisent dans plusierus feuilles de l'arbre d'expression.
 
D'ou ma premiere idée de fournir à la compilation un ID a chaque  instance de Vector et d'assigner le Register<T,ID> au Vector<T,S,ID>.
 
En clair, je dois refaire l'affectation des données vers des variables temporaires à la compilation ...
 
J'espere avoir été clair ...
Je bute vraiment sur un os là :P
Merci d'avance pour ttes idée/aide etc ..

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Attention ca va faire mal : template,inlining et AltiVec en autres

 

Sujets relatifs
[C/C++] probleme d'inliningun equivalent de HTML template en Java ...
[Resolu] [C++] template et Visual Studio 6.0Template un peu fin
Template / Pointeur de fonction[C++] Definir des contraintes pour un template
polymorphisme et template[C++] template et condition
[C/C++] template: j'ai merdé, help siouplaitQu'est ce que des template ???
Plus de sujets relatifs à : Attention ca va faire mal : template,inlining et AltiVec en autres


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR