Représentation en mémoire d'une classe, assembleur

Représentation en mémoire d'une classe, assembleur - C++ - Programmation

Marsh Posté le 16-12-2009 à 23:18:48    

Bonjour.
 
Voici deux classes banales:

Code :
  1. /**Définit un vecteur en 2 dimensions.
  2. */
  3. class Vecteur2D
  4. {
  5.     //constructeurs, méthodes toussa
  6. private:
  7.     double x;/**<Coordonnée en abscisses.*/
  8.     double y;/**<Coordonnée en ordonnées.*/
  9. };
  10. /**Définit un vecteur en 3 dimensions.
  11. */
  12. class Vecteur3D: public Vecteur2D
  13. {
  14.     //constructeurs, méthodes toussa
  15. private:
  16.     double z; /**<Coordonnée en hauteur.*/
  17. };


 
Voici une méthode de vecteur2D:

Code :
  1. double Vecteur2D::produitScalaire (const Vecteur2D& vecteur) const
  2. {
  3.     //return vecteur.getX() * x + vecteur.getY() * y;
  4.     double p;
  5.     asm("movsd 8%[vecteur], %%xmm1\n" //On charge vecteur.getX
  6.         "movsd 16%[vecteur], %%xmm0\n" //On charge vecteur.getY
  7.         "unpcklpd %%xmm1, %%xmm0\n" //xmm0 = vecteur.x, vecteur.y
  8.         "movsd 8%[thisx], %%xmm2\n" //On charge x
  9.         "movsd 16%[thisx], %%xmm1\n" //On charge y
  10.         "unpcklpd %%xmm2, %%xmm1\n" //xmm1 = x, y
  11.         "mulpd %%xmm1, %%xmm0\n" //xmm0 = x*vecteur.getX, y*vecteur.getY
  12.         "haddpd %%xmm0, %%xmm0\n"//xmm0 = quelque chose, vecteur.getX() * x + vecteur.getY() * y
  13.         "movlpd %%xmm0, %[retour]\n" //copie dans retour
  14.         :
  15.         :[vecteur] "m" (vecteur), [thisx]"m" (*this), [retour] "m" (p)
  16.         :"%xmm0","%xmm1", "%xmm2"
  17.         );
  18.     return p;
  19. }


Est-ce que quelqu'un peut m'expliquer pourquoi je dois ajouter un offset de 8 octets quand je vais chercher x et y? x est sensé être "en début de classe"
 
Avant j'utilisais une seule classe Vecteur qui était en 3 dimensions donc avec 3 attributs et sans héritage. Je n'avais pas besoin de l'offset à ce moment là. Pourtant la méthode est dans Vecteur2D, elle ne connait donc logiquement pas z et il ne devrait pas interférer...
 
 
edit: Si vous aussi vous trouvez que l'assembleur avec gcc c'est vraiment casse bonbons à écrire, manifestez-vous.
edit2: titre corrigé


Message édité par ptitchep le 17-12-2009 à 12:04:13

---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 16-12-2009 à 23:18:48   

Reply

Marsh Posté le 17-12-2009 à 00:02:02    

[:pingouino]
 
sinon, a tout hasard, la vtable ?


---------------
Nos estans firs di nosse pitite patreye...
Reply

Marsh Posté le 17-12-2009 à 00:25:17    

problem de alignement :whistle: ?

Reply

Marsh Posté le 17-12-2009 à 09:40:37    

Juste un pb d'alignements effectivement  

Reply

Marsh Posté le 17-12-2009 à 10:06:38    

C'est à dire un problème d'alignement? Et comment connaitre cet alignement à l'avance parce que là j'ai galéré à tatonner pour l'offset. Si ça se trouve (même si quand même ça serait difficile) j'ai eu une malchance énorme et les cases mémoires que j'ai pointées contiennent aussi les valeurs de mes tests. Donc mon offset est complètement faux et n'a fonctionné que par chance sur les N essais que j'ai fait.


---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 17-12-2009 à 11:51:58    

attends je viens de percuter la ... tu ecris du SSE2 en assembleur dans ta methode ... tu sais que y a des intrinsic pour ca et que le compilo va se debrouilelr tt seul

Reply

Marsh Posté le 17-12-2009 à 12:02:22    

Oui, je voulais voir comment ça marche ;)


---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 17-12-2009 à 14:58:27    

ouais mais non, les intrinsic asm sont affreux a manipuler en C++ :o

Reply

Marsh Posté le 17-12-2009 à 16:37:49    

C'est à dire? Je dois faire comment en fait? Intrinsic ou non? Moi j'y arrive très bien sans... à part pour cette histoire d'offset.
D'ailleurs pas de réponse pour mon alignement?


---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 17-12-2009 à 18:52:21    

bah goto la doc quoi. En gros dans xmmintrin.h t'as une flopée de fonction pour faire ça.

 

Pour l'alignement, ce qui se passe est que pour charger une valeur dans un registre ssex son adresse doit etre aligné sur 128bits (ie 16 octets). Dans ton cas, le compilo doit ajouter du padding devant ton instance de classe pr que le movsd fonctionne.

 

Ensuite, le SIMD n'est clairement pas fait pour faire ça, t'aura 0 gain :/

 

EDIT:
ouais et Vecteur3D qui herite de Vecteur2D [:pingouino] ... c'est pas glorieux non plus


Message édité par Joel F le 17-12-2009 à 18:56:08
Reply

Marsh Posté le 17-12-2009 à 18:52:21   

Reply

Marsh Posté le 17-12-2009 à 20:13:09    

Ok donc si je comprends bien, si je lui disais d'aligner mon instance sur 128 bits je n'aurais pas d'offset?

 

ben le gain j'en ai un peu si j'ai beaucoup d'appel à cette méthode. C'est sur que sur d'autres parties j'ai gagné plus mais comme j'ai constaté une amélioration (même minime) j'ai gardé ce code.

 

Un vecteur en 3D n'est pas un vecteur en 2D avec une composante de plus?

Message cité 1 fois
Message édité par ptitchep le 17-12-2009 à 20:13:52

---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 17-12-2009 à 20:47:31    

Joel F a écrit :

Juste un pb d'alignements effectivement  


 
un double faisant 8 octets, je vois pas pourquoi il y aurait un offset de 8, ça ne corrige pas l'alignement :??:
 
ou alors il nous dit pas tout et il a un virtual dans sa classe.

Message cité 1 fois
Message édité par bjone le 17-12-2009 à 20:51:28
Reply

Marsh Posté le 17-12-2009 à 21:31:59    

ptitchep a écrit :


Ok donc si je comprends bien, si je lui disais d'aligner mon instance sur 128 bits je n'aurais pas d'offset?


 

ptitchep a écrit :


ben le gain j'en ai un peu si j'ai beaucoup d'appel à cette méthode. C'est sur que sur d'autres parties j'ai gagné plus mais comme j'ai constaté une amélioration (même minime) j'ai gardé ce code


 
Deja tu charges tes deux doubles comme un pied. T'as lu la doc de SSE2 avant de faire du frankenstein ?
En gros tu devrais faire un load sur x et hop tu charge x y cote a cote dans un vecteur, pas besoin de ce unpack et des ces movsd qui rpennent 10000 ans.
 
Et ton gain, sur cb d'instance et cb d'appel ?  
Le meilleur cas pour SSE c'ets qd meme d'iterer sur de larges tabelaux de données, pas d'optimiser un appel à 2 double ...
Ton cas doit plutot venir que tu passe pas par la pile FP, ce que tu aurais sans rien faire d emoche avec _fpmath=sse2 ...
 
Ah ouais et gcc > 4.3 et icc > 8 auto-vectorise tout seul ces trucs mieux que toi ...
 

ptitchep a écrit :


Un vecteur en 3D n'est pas un vecteur en 2D avec une composante de plus?


Non

Reply

Marsh Posté le 17-12-2009 à 21:32:18    

bjone a écrit :


 
un double faisant 8 octets, je vois pas pourquoi il y aurait un offset de 8, ça ne corrige pas l'alignement :??:
 
ou alors il nous dit pas tout et il a un virtual dans sa classe.


 
Alignement sur *16* octets ;)

Reply

Marsh Posté le 17-12-2009 à 21:40:59    

Reply

Marsh Posté le 17-12-2009 à 22:40:17    

hahaha ! :lol:  

Reply

Marsh Posté le 17-12-2009 à 22:54:05    

Le truc c'est que j'avais essayé de charger mes 2 doubles d'un coup bien sûr puisque c'est la taille du registre... Impossible d'aligner correctement (avec gcc).
J'ai utilisé  __attribute__ ((aligned (16))) en essayant toutes les combinaisons possibles (vu que ce que je pensais logique ne marchait pas) puis je chargeais avec movapd (si mes souvenirs sont bons, je n'ai pas la doc sous les yeux) ===> erreur de segmentation car non alligné sur 16 octets... Verification via le debugger en effet un coup sur 2 ce n'était pas aligné (vu que ça alignait sur 8 octets, j'avais une chance sur 2).
Ensuite j'ai donc utilisé movupd mais dans la doc d'intel j'ai vu que 2 movsd étaient plus rapides (je chercherai dans mon pdf le paragraphe si tu veux, la flemme là).

 

Le gain est en effet minime comme je l'ai dit, je parle de plusieurs milliers d'appels dans la seconde. Mais bon il est là alors je ne vais pas remettre ma fonction de base. J'ai codé avec sse juste par curiosité et j'ai gagné quelques nano secondes, je ne vais pas virer ça si?

 

Tu peux m'expliquer pour le vecteur? Moi et les math...
Pendant ce temps je vais lire ton lien.

  

(edit) retrouvé:
The MOVUPD from memory instruction performs two 64-bit loads, but requires addi-
tional μops to adjust the address and combine the loads into a single register. This
same functionality can be obtained using MOVSD XMMREG1, MEM; MOVSD
XMMREG2, MEM+8; UNPCKLPD XMMREG1, XMMREG2, which uses fewer μops and
can be packed into the trace cache more effectively.

Message cité 1 fois
Message édité par ptitchep le 17-12-2009 à 23:05:03

---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 17-12-2009 à 23:00:33    


yep effectivement, autant pour moi ;)

Reply

Marsh Posté le 17-12-2009 à 23:04:05    

ptitchep a écrit :


Le gain est en effet minime comme je l'ai dit, je parle de plusieurs milliers d'appels dans la seconde. Mais bon il est là alors je ne vais pas remettre ma fonction de base. J'ai codé avec sse juste par curiosité et j'ai gagné quelques nano secondes, je ne vais pas virer ça si?


 
Je sais pas pour qui tu code mais un code comme ça en prod, jamais je laisse passer.
C'ets typiquement le truc moche que lrosque tu part plus personne n'est capable de maintenir.
gagner 50% ou 30% c'ets significatif, gagner de la nanoseconde, c'est du bruit de mesure.
 

ptitchep a écrit :


Tu peux m'expliquer pour le vecteur? Moi et les math...


tes deux classes s'ecrivent juste :
 

Code :
  1. template<std::size_t N> struct vector
  2. {
  3.   T data[N];
  4. };


 
Pour le __attribute((aligned(16)) il n'a de sens que sur des local variable.
Si tu veut avoir des membres alignés, goto union avec boost::aligned_storage

Reply

Marsh Posté le 17-12-2009 à 23:23:35    

Alors là, désolé... Par désespoir j'ai retenté le aligned(16) et ça fonctionne. J'ai maintenant des movapd...
Il faut quand même dire qu'entre le temps ou j'ai codé cette fonction, que j'ai eu (pris) le temps de revenir sur ce problème d'offset, j'ai changé de pc, de linux et donc sûrement de version de gcc, ça a peut-être un lien. Ou alors j'ai eu de la chance pendant mes tests de ce soir et ca crashera la prochaine fois, cela dit je saurais où regarder.


---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 17-12-2009 à 23:25:39    

ok grillé
je vais regarder boost::aligned_storage
en effet mes tests étaient sur des variables locales

 

Ca je le code pour moi et je commente chaque ligne dans ce cas. Sinon ce n'est même pas quand je pars, c'est le lendemain que c'est impossible à maintenir.
Le but est simplement de voir ce que l'on peut faire dans les calculs avec des flottants, pas vraiment d'optimiser à mort une appli... C'est pour passer le temps. Sinon j'ai découvert ça en stage de fin d'études, pour de gros calculs de traitement du signal sur de gros tableaux. Là en effet le gain était de 40%.
J'ai voulu voir ce que je gagnais dans le cas de cette méthode et comme j'étais intrigué par cet offset, ben je cherche à savoir pourquoi c'est tout.

Message cité 1 fois
Message édité par ptitchep le 17-12-2009 à 23:33:25

---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 17-12-2009 à 23:51:38    

:ange: vous avancer trop vite ! .... je ne reussie pas  
a suivre . , ..... OK elle peut etre une incorrectness
de gcc , (oui !) , ... ces chose (SIMD , MMX ...) vont mieux sous
windows.
- le problem devient interressant!  , ci vous poster
un dump du stack , hein ?
 

Reply

Marsh Posté le 18-12-2009 à 00:22:59    

..... jai crois qui ont quitter....
 Des le debut le sujet etait mal proposer
 (l'example etait abstrait , manque details!
 il faut prendre la bonne direction avant ! :jap: )
.... ok alors c'est FINI.
 
 
 END. ? :sarcastic:  

Reply

Marsh Posté le 18-12-2009 à 07:07:46    

__tomjost a écrit :

:ange: vous avancer trop vite ! .... je ne reussie pas  
a suivre . , ..... OK elle peut etre une incorrectness
de gcc , (oui !) , ... ces chose (SIMD , MMX ...) vont mieux sous
windows.
- le problem devient interressant!  , ci vous poster
un dump du stack , hein ?


 
arretes de dire des conneries, ca fait des années que SSE marche parfaitement sous gcc ...

Reply

Marsh Posté le 18-12-2009 à 07:09:01    

ptitchep a écrit :


Ca je le code pour moi et je commente chaque ligne dans ce cas. Sinon ce n'est même pas quand je pars, c'est le lendemain que c'est impossible à maintenir.
Le but est simplement de voir ce que l'on peut faire dans les calculs avec des flottants, pas vraiment d'optimiser à mort une appli... C'est pour passer le temps. Sinon j'ai découvert ça en stage de fin d'études, pour de gros calculs de traitement du signal sur de gros tableaux. Là en effet le gain était de 40%.
J'ai voulu voir ce que je gagnais dans le cas de cette méthode et comme j'étais intrigué par cet offset, ben je cherche à savoir pourquoi c'est tout.


 
OK ;) J'avais peur que ca atterise dans une vrai appli.
Ensuite, self pub, check mon lien sur NT2 pour voir la tete que ca prends dans un truc plus large

Reply

Marsh Posté le 18-12-2009 à 09:56:55    

__tomjost a écrit :

..... jai crois qui ont quitter....
 Des le debut le sujet etait mal proposer
 (l'example etait abstrait , manque details!
 il faut prendre la bonne direction avant ! :jap: )
.... ok alors c'est FINI.

 


 END. ? :sarcastic:


Non ce n'est pas fini mais on a le droit d'aller se coucher...
Je fais ce que je peux quand je pose un sujet  ;)

  
Joel F a écrit :

 

OK ;) J'avais peur que ca atterise dans une vrai appli.
Ensuite, self pub, check mon lien sur NT2 pour voir la tete que ca prends dans un truc plus large


Ok je vais regarder tout ça mais là j'ai pas mal de boulot alors ça risque d'attendre un peu, je reposterai à ce moment là.

 

Quel lien en fait?


Message édité par ptitchep le 18-12-2009 à 09:57:34

---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 18-12-2009 à 10:57:55    

Reply

Marsh Posté le 18-12-2009 à 11:16:53    

Joel F a écrit :

ma signature :o


Au moins, je mérite la mienne.


---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 18-12-2009 à 18:05:37    

Joel F a écrit :


arretes de dire des conneries, ca fait des années que SSE marche parfaitement sous gcc ...


 
 :)  
c'est vrai! SSE+MMX apparu a l'age du pentiumIII
 :bounce:  
but why intel invented the SSE ?
pour repondre au requete web sur apache?
le bute etait de accelerer le operation sur vecteurs
avec 4 float [xyzw] dans un seul 'pack' on gange becaucoup
en addition , mul , et autre.
... ca est utiliser principalment pour les jeu (c'est ca l'intention d'intel)
..Pour les application multimedia! , d'abord MMX avec les integer.
puis SSE (SIMD) quit supporte les floats. , et tout les jeu presque
sont sous windows , ( quelqu'un connait TombRaider sous linux??)  
(c'est etait avant que les CarteGraphic modern apparaiss)  
 

Joel F a écrit :


Pour le __attribute((aligned(16)) il n'a de sens que sur des local variable.
Si tu veut avoir des membres alignés, goto union avec boost::aligned_storage


 
j'ai vu des struct au global scope qui avait __attribute((aligned(X)))
( je crois ) :D  
 
 
(on parle du binare et on vois du cpp seulement !)
 :sol:  
je crois que ca est la class (no vtbl) :
ADDRESS:  ??=8, x=8, y=8, z=8 ,  
.......
 
ces alignment , sont reliee au model du processeur (et le system aussi)
(code optimized for XXcpu) , ca se control par les arg du gcc
, lui va choisir quand et ou mettre le padding (apres, avant) pour le bien
du program.
 
 
NOTE:
ON following warnings :
Wpacked , Walign ['Wall' may not include them ] , ca
reporte que gcc  fait , ou si la structure (class) va etre aligner
 
NOTE:
OFF N-level optimization , empeche gcc de faire les optimization
(ex: favoriser un taille petit , et sacrifier la vitesse )
ca va resoudre cette place vide , avec un GRAND performance loss!!
 
NOTE:
pas de faute de gcc.
 
NOTE:
align16 -> le prochain membre vient apres 16 byte
align8 -> le prochain membre vient apres 8 byte
meme si member 1 a seulement 1 octet.
(OK je sais 'pack' sur msvc (windows) , jnai pas tester ca sur linux)
cela ajoute le padding apres , mais notre cas c'est padding avant!
 
 
ca control le stack (see gcc) :
-mpreferred-stack-boundary=N.   <-- option qu'ont passe a gcc.
ca align start adress (offset) to 2 pow N
ca ajoute du padding au debut et consomme le stack (pile?).
le defaut et 4 (2^4 = 16 byte) --> (testez la)
 
--> laisse comme ca. ca c'est fait explicitement pour ganger du vitesse   ...... :sleep:  
 
 
 

Reply

Marsh Posté le 18-12-2009 à 19:14:11    

__tomjost a écrit :


but why intel invented the SSE ?
pour repondre au requete web sur apache?
le bute etait de accelerer le operation sur vecteurs
avec 4 float [xyzw] dans un seul 'pack' on gange becaucoup
en addition , mul , et autre.
... ca est utiliser principalment pour les jeu (c'est ca l'intention d'intel)
..Pour les application multimedia! , d'abord MMX avec les integer.
puis SSE (SIMD) quit supporte les floats. , et tout les jeu presque
sont sous windows , ( quelqu'un connait TombRaider sous linux??)  
(c'est etait avant que les CarteGraphic modern apparaiss)  


Bullshit total ... je repete SSE2 et usp marche ausis sous linux, genre tout les codec video libre l'utilise ...
 

__tomjost a écrit :


j'ai vu des struct au global scope qui avait __attribute((aligned(X)))
( je crois ) :D  


Ca marche par hasard c'est tout :E
 

__tomjost a écrit :


--> laisse comme ca. ca c'est fait explicitement pour ganger du vitesse   ...... :sleep:  


mais tu crois m'apprendre quelque chose là ? Ca fait 10 ans que je fais du SIMD alors tes copier/coller de la MSDN ... merci d'etre venu
et de repondre a coté de la question ...
 

Reply

Marsh Posté le 18-12-2009 à 23:46:15    

[je viens d'editer .]
 
je croyer que je nvai pas du poster dautre message ici !
 
:sweat:  
c'est un forum pour discussion , rien d'autre
 
peut etre vous ete un fanatic de linux (damned windows ,... bill , logiciel-libre..)
j'ai aussi linux , tout on aime linux. :jap:  
 
1)# ci on lit bien je dit que vous avez raison .
je dit (c'est vrai! SSE+MMX apparu a l'age du pentiumIII)
je donne apres que je connait (et c'd apres intel)
ces destiner a tout (c'est ce que je pense , c't un forum , non ?)
 
3)# aligned(16) keyword , j'ai dit a la fin "je crois" ,  
mais j'etait certain .....  VOICI , ca je lai extrait
maintenant.... :sol:  
 
// from drivers/block/umem.h
//

Code :
  1. #define DMA_READ_FROM_HOST 0
  2. #define DMA_WRITE_TO_HOST 1
  3. struct mm_dma_desc {
  4. __le64 pci_addr;
  5. __le64 local_addr;
  6. __le32 transfer_size;
  7. u32 zero1;
  8. __le64 next_desc_addr;
  9. __le64 sem_addr;
  10. __le32 control_bits;
  11. u32 zero2;
  12. dma_addr_t data_dma_handle;
  13. /* Copy of the bits */
  14. __le64 sem_control_bits;
  15. } __attribute__((aligned(8)));
  16. /* bits for card->flags */
  17. #define UM_FLAG_DMA_IN_REGS  1
  18. #define UM_FLAG_NO_BYTE_STATUS  2


 
# ca c' t une grep sur le 'drivers' folder du kernel
# il ya beacoup , quel hazard ?
 

[localhost]# grep -r '((align' *
block/floppy.c:     ((aligned_sector_t - buffer_min) << 9);
block/umem.h:} __attribute__((aligned(8)));
bluetooth/btsdio.c:     u8 hdr[4] __attribute__ ((aligned(4)));
char/hvc_beat.c:                __attribute__((aligned(sizeof(unsigned long))));
dma/fsldma.h:} __attribute__((aligned(32)));
dma/fsldma.h:} __attribute__((aligned(32)));
firewire/fw-ohci.c:} __attribute__((aligned(16)));

 
SIMD SSE MMX XMM , c'est rien , ce sont des particularité.
extention pour qui existe avant , il n ya pas un nouveau science! :non:  
 
Pour le reste de ma reponse , c'est etai pour qui a fait la question
ou disons pour le question lui meme , pour tout le monde...
 
--> laisse comme ca. ca c'est fait explicitement pour ganger du vitesse  
#je dit que le problem de "ptitchep" etait n'ai qu'une optimization du compiler.
c'est tout.
-----------------------------
perte de temps. :pfff:


Message édité par __tomjost le 22-12-2009 à 23:25:24
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed