OVH Cloud OVH Cloud

Contigüité memoire ?

43 réponses
Avatar
May
Bonjour,

J'utilise une classe de base tres simple :

struct donne
{
double Int;
double Ext;
double IntExt;
}

puis un tableau aloué statiquement pour le moment

donne Tab[1024];

Ma question est assez simple, dans quel ordre en memoire, sont les données ?
Est-ce que je peux faire un truc du genre :

double *ptr=&Tab[0].Int;
for (int i=0;i<256;i++,ptr+=3)
{
*ptr=1.0;
}

Afin d'initialiser tous les champ Int de toutes les classes du tableau ?
Et si oui est-ce que ca reste valable si je fait un tableau dynamique à la C
(new/delete) ? ou avec std::vector<donne> ?

Merci
May

10 réponses

1 2 3 4 5
Avatar
May
"Gabriel Dos Reis" a écrit dans le message de
news:
"May" writes:

| "Samuel Krempp" a écrit dans
le

| message de news:3f70953b$0$20634$
| > le Tuesday 23 September 2003 20:29, écrivit
:

| > > | #include <cassert>
| > > | double *ptr=&Tab[0].Int;
| > > | assert(sizeof(donnee) % sizeof(double) == 0);
| > > | for (int i=0;i<256;i++,ptr+= sizeof(donnee)/sizeof(double))
| > >
| > > Pourquoi ne pas simplement mettre la taille de Tab utilisée dans sa
| > > déclaration ?
| >
| > parceque je pensais plus à ce 256 et que j'ai copier-collé :)
| >
| > --
| > Sam
|
| Au temps pour moi, c'est effectivement pas 256 dan sla boucle mais 1024
(la

| taille de mon tableau).
|
| A cause de la future utilisation de la MKL, il me faut tester ce que va
| faire la MKL pour copier.
| Pour etre plus claire, j'ai ceci :
|
| struct donne
| {
| double Int;
| double Ext;
| double IntExt;
| };
|
| double Int[1024];
| donne Tab[1024]; //puis a remplacer par std::vector<donne> Tab(1024);
|
| Je veux maintenant copier le tableau Int dans les champs Tab[x].Int
| Mais pour des problemes de performances, je doit utiliser la MKL.
| Or la MKL est codée en C et pas en C++ ou je ne sais trop quoi ....
| Donc sa facon d'acceder a la memoire est par pointeur. Donc exit, les
tests

| (oui oui je teste ce que va faire la MKL) du type :
| for (...)
| {
| Tab[i].Int=1.0;
| }
| ou ptr->Int=1.0;
| Je ne doit pas utiliser l'interface de classe mais un acces memoire
direct.


Là je ne te suis pas. En entrée tu as le tableau « Int » à copier
dans le tableau « Tab », en ne touchant que les champs .Int et le type
« donne » est complet au moment où tu écris ta boucle; c'est bien cela
? Si oui, pourquoi est-ce que ce qui t'a été proposé est exit ?

C'est bien cela. Tout n'est pas "exit".

Mais je ne peux pas utiliser les accesseurs ->Int et .Int.
En fait je cherche, dans un premier temps, à faire comme ce que ferai la
MKL, c'est a dire à n'utiliser que des pointeurs et pas d'acces aux données
de la structure par ses champs (.Int .Ext .IntExt).
Car dans un deuxieme temps, j'aimerai utiliser la MKL mais il faut pour cela
que j'arrive a determiner un offset memoire entre chaque champ "Int" de
chaque objet "donne" du tableau Tab.

donc en gros si j'arrive à acceder a chaque champ Int de mon tableau avec ce
que ma proposé Samuel Krempp, alors c'est que je peux utiliser la MKL pour
faire une copie. Si les données ne sont pas contigües et que l'offset (entre
2 champ Int) change au cours du tableau, alors je ne pourrais pas utiliser
la MKL qui est trés nettement plus rapide qu'une boucle for.

Je ne cherche pas a programmer lisible et beau, j'ai besoin de performance
car c'est un passage critique dans mon appli... Je fait du traitement de
l'image et seules les perfs comptent (enfin presque)

| Donc pour m'assurer que la MKL copie au bon endroit dans la memoire, il
faut

| lui donner l'offset entre 2 Champs Int dans le tableau Tab (ie
| offset=&(Tab[1].Int)-&(Tab[0].Int))

ne vas pas sur ce terrain et ne te complique pas la vie.

-- Gaby


Avatar
Samuel Krempp
le Wednesday 24 September 2003 15:09, écrivit :

Mais je ne peux pas utiliser les accesseurs ->Int et .Int.
En fait je cherche, dans un premier temps, à faire comme ce que ferai la
MKL, c'est a dire à n'utiliser que des pointeurs et pas d'acces aux
données de la structure par ses champs (.Int .Ext .IntExt).
Car dans un deuxieme temps, j'aimerai utiliser la MKL mais il faut pour
cela que j'arrive a determiner un offset memoire entre chaque champ "Int"
de chaque objet "donne" du tableau Tab.


d'accord, et bien pour cela la structure Donnee que j'ai indiqué fonctionne
(en utilisant comme offset sizeof(Donnee)/sizeof(double))

Laisse cependant au début de ton code pour vérifier que tout va bien :
assert(sizeof(Donnee) % sizeof(double) ==0);
comme ça si ça ne marche pas comme prévu, ça se verra.

donc en gros si j'arrive à acceder a chaque champ Int de mon tableau avec
ce que ma proposé Samuel Krempp, alors c'est que je peux utiliser la MKL
pour faire une copie.


oui, c'est bien le cas, ce que j'ai proposé est bon, et ça te permet
d'utiliser la MKL.

Si les données ne sont pas contigües et que l'offset
(entre 2 champ Int) change au cours du tableau, alors je ne pourrais pas
utiliser la MKL qui est trés nettement plus rapide qu'une boucle for.


tu peux utiliser plusieurs sortes de tableaux qui garantissent la contigüité
et la technique fonctionne. précisément :
std::vector<double> Tab;
double Tab[1024];
double * Tab = new double[1024];
dans chaque cas la même boucle marchera.

Je ne cherche pas a programmer lisible et beau, j'ai besoin de performance
car c'est un passage critique dans mon appli... Je fait du traitement de
l'image et seules les perfs comptent (enfin presque)


ah tiens ! et dans quel labo travailles-tu ?

--
Sam

Avatar
Gabriel Dos Reis
Samuel Krempp writes:

| le Wednesday 24 September 2003 15:30, écrivit :
|
| > "May" writes:
| >
| > Je comprends que tu cherches la perf -- et dans ma jeunesse, dans le
| > labo où j'ai été formé, j'ai eu a regarder et écrire certains codes
| > pour le traitement d'image. Globablement, l'impression que j'ai gardé
| > de cette pratique est qu'on croit souvent à tord que performant
| > implique nécessairement pas beau, et surtout pas portable
| > (hein, Samy, que penses-tu du code produit et utilisé par xxxxxve ? ;-)
|
| t'as oublié un x non, mexxxxve ?

oui et oui.

| bah j'en pense le moins possible, je ny' touche guère..

t'as comme vocation de faire diplomate français à Washington ? ;-)

| du reste, je sais pas si c'est particulièrement par souci de performance que
| c'est pas portable, impossible à utiliser comme bibliothèreque, etc..
| Je crois que c'est juste que les auteurs ne savaient pas vraiment quoi faire
| d'autre..

ah...

| Enfin pour le fond, je suis bien d'accord : on peut obtenir la performance
| en écrivant son code le plus joliment possible, tant qu'on fait les bons
| choix algorithmiques dans la boucle la plus importante. ensuite il n'y a
| qu'à profiler si on veut accèlerer.
| (et je ne sais pas pourquoi, je n'ai jamais vu personne utiliser de profiler
| au labo. il n'y a que de l'optimisation à priori. premature optimisation
| is the root of all evil ? connais pas ! :)

Un jour, CL m'a appris qu'il y en avait qui faisaient tourner des
programmes qui prenaient des semaines et des ressources
inconsidérables tout simplement prace qu'ils ne savaient pas que les
compilateurs qu'ils utilisent ont des options d'optimisation. Tu vois
bien que de là à imaginer profiler ... :-)
Mais, c'était un an avant que je parte...

-- Gaby
Avatar
May
"Gabriel Dos Reis" a écrit dans le message de
news:
"May" writes:


[...]

| > | Je veux maintenant copier le tableau Int dans les champs Tab[x].Int
| > | Mais pour des problemes de performances, je doit utiliser la MKL.
| > | Or la MKL est codée en C et pas en C++ ou je ne sais trop quoi ....
| > | Donc sa facon d'acceder a la memoire est par pointeur. Donc exit,
les

| tests
| > | (oui oui je teste ce que va faire la MKL) du type :
| > | for (...)
| > | {
| > | Tab[i].Int=1.0;
| > | }
| > | ou ptr->Int=1.0;
| > | Je ne doit pas utiliser l'interface de classe mais un acces memoire
| direct.
| >
| > Là je ne te suis pas. En entrée tu as le tableau « Int » à copier
| > dans le tableau « Tab », en ne touchant que les champs .Int et le type
| > « donne » est complet au moment où tu écris ta boucle; c'est bien cela
| > ? Si oui, pourquoi est-ce que ce qui t'a été proposé est exit ?
| >
| C'est bien cela. Tout n'est pas "exit".
| Mais je ne peux pas utiliser les accesseurs ->Int et .Int.

c'est bien là je ne comprends pas pourquoi les accesseurs ->Int et
.Int ne peuvent pas être utilisés. Ton MKL, il a bien la structure
donne comme présentés ci-haut ?
La MKL n'est pas une librairie C++. Les structures, elle connait pôô.



| En fait je cherche, dans un premier temps, à faire comme ce que ferai la
| MKL, c'est a dire à n'utiliser que des pointeurs et pas d'acces aux
données

| de la structure par ses champs (.Int .Ext .IntExt).
| Car dans un deuxieme temps, j'aimerai utiliser la MKL mais il faut pour
cela

| que j'arrive a determiner un offset memoire entre chaque champ "Int" de
| chaque objet "donne" du tableau Tab.
|
| donc en gros si j'arrive à acceder a chaque champ Int de mon tableau
avec ce

| que ma proposé Samuel Krempp, alors c'est que je peux utiliser la MKL
pour

| faire une copie.

il manque un connecteur ici. Quelle est l'API du machin MKL qui faitt
la copie ?


???


| Si les données ne sont pas contigües et que l'offset (entre
| 2 champ Int) change au cours du tableau, alors je ne pourrais pas
utiliser

| la MKL qui est trés nettement plus rapide qu'une boucle for.

je crois qu'aller sur le terrain de l'offset compliquera la tâche
inutilement.

non c 'est obligatoire


| Je ne cherche pas a programmer lisible et beau, j'ai besoin de
performance

| car c'est un passage critique dans mon appli... Je fait du traitement de
| l'image et seules les perfs comptent (enfin presque)

Je comprends que tu cherches la perf -- et dans ma jeunesse, dans le
labo où j'ai été formé, j'ai eu a regarder et écrire certains codes
pour le traitement d'image. Globablement, l'impression que j'ai gardé
de cette pratique est qu'on croit souvent à tord que performant
implique nécessairement pas beau, et surtout pas portable
(hein, Samy, que penses-tu du code produit et utilisé par xxxxxve ? ;-)

ouais mais c'est quand meme ma boucle principale, j'aimerai que tout y soit

rapide

-- Gaby


Avatar
May
"Samuel Krempp" a écrit dans le
message de news:3f719f24$0$13305$
le Wednesday 24 September 2003 15:09, écrivit :

Mais je ne peux pas utiliser les accesseurs ->Int et .Int.
En fait je cherche, dans un premier temps, à faire comme ce que ferai la
MKL, c'est a dire à n'utiliser que des pointeurs et pas d'acces aux
données de la structure par ses champs (.Int .Ext .IntExt).
Car dans un deuxieme temps, j'aimerai utiliser la MKL mais il faut pour
cela que j'arrive a determiner un offset memoire entre chaque champ
"Int"


de chaque objet "donne" du tableau Tab.


d'accord, et bien pour cela la structure Donnee que j'ai indiqué
fonctionne

(en utilisant comme offset sizeof(Donnee)/sizeof(double))

Laisse cependant au début de ton code pour vérifier que tout va bien :
assert(sizeof(Donnee) % sizeof(double) ==0);
comme ça si ça ne marche pas comme prévu, ça se verra.

donc en gros si j'arrive à acceder a chaque champ Int de mon tableau
avec


ce que ma proposé Samuel Krempp, alors c'est que je peux utiliser la MKL
pour faire une copie.


oui, c'est bien le cas, ce que j'ai proposé est bon, et ça te permet
d'utiliser la MKL.

Si les données ne sont pas contigües et que l'offset
(entre 2 champ Int) change au cours du tableau, alors je ne pourrais pas
utiliser la MKL qui est trés nettement plus rapide qu'une boucle for.


tu peux utiliser plusieurs sortes de tableaux qui garantissent la
contigüité

et la technique fonctionne. précisément :
std::vector<double> Tab;
double Tab[1024];
double * Tab = new double[1024];
dans chaque cas la même boucle marchera.


Merci j'ai peas encore eu le temps de tester --> demain certainement

Je ne cherche pas a programmer lisible et beau, j'ai besoin de
performance


car c'est un passage critique dans mon appli... Je fait du traitement de
l'image et seules les perfs comptent (enfin presque)


ah tiens ! et dans quel labo travailles-tu ?


Le labo Odyssee de l'INRIA.


--
Sam


Merci encore pour ce deferlement de reponses
May


Avatar
Gabriel Dos Reis
"May" writes:

| Le labo Odyssee de l'INRIA.

de Sophia Antipolis donc ? Pourquoi ne vas-tu pas discuter avec Théo ?

-- Gaby
Avatar
Gabriel Dos Reis
"May" writes:

| > c'est bien là je ne comprends pas pourquoi les accesseurs ->Int et
| > .Int ne peuvent pas être utilisés. Ton MKL, il a bien la structure
| > donne comme présentés ci-haut ?
| La MKL n'est pas une librairie C++. Les structures, elle connait pôô.

c'est du C, non ?

[...]

| ouais mais c'est quand meme ma boucle principale, j'aimerai que tout y soit
| rapide

Oui, elle le sera et tu peux l'avoir propre -- surtout si tu fais
confiance au système de type.

-- Gaby
Avatar
May
"Gabriel Dos Reis" a écrit dans le message de
news:
"May" writes:

| Le labo Odyssee de l'INRIA.

de Sophia Antipolis donc ? Pourquoi ne vas-tu pas discuter avec Théo ?


Quelqu'un du CMLA, le connais forcement !!! :o)
Mais je suis dans la branche Parisienne du projet Odyssee.

Par contre j'ai fait mon dea au CMLA : Dea MVA

May


-- Gaby


Avatar
Gabriel Dos Reis
"May" writes:

| "Gabriel Dos Reis" a écrit dans le message de
| news:
| > "May" writes:
| >
| > | Le labo Odyssee de l'INRIA.
| >
| > de Sophia Antipolis donc ? Pourquoi ne vas-tu pas discuter avec Théo ?
|
| Quelqu'un du CMLA, le connais forcement !!! :o)

je ne sais pas :-) Je le connais autrement que par le CMLA, depuis un
temps certain. Je me suis intéressé au traitement d'image par pure
curiosité, lorsque j'étais jeune.

Mais tu devrais quand même discuter avec Théo -- même par mail.
Il fait pas mal de choses pour le traitement d'images en C++.

| Mais je suis dans la branche Parisienne du projet Odyssee.

okay, okay.

| Par contre j'ai fait mon dea au CMLA : Dea MVA

donc tu dois connaître Samy, je suppose.

-- Gaby
Avatar
Arnaud Debaene
May wrote:
"Gabriel Dos Reis" a écrit dans le
message de news:
"May" writes:

"Samuel Krempp" a écrit
dans le message de news:3f70953b$0$20634$
le Tuesday 23 September 2003 20:29,
écrivit

#include <cassert>
double *ptr=&Tab[0].Int;
assert(sizeof(donnee) % sizeof(double) == 0);
for (int i=0;i<256;i++,ptr+= sizeof(donnee)/sizeof(double))


Pourquoi ne pas simplement mettre la taille de Tab utilisée dans
sa déclaration ?


parceque je pensais plus à ce 256 et que j'ai copier-collé :)

--
Sam


Au temps pour moi, c'est effectivement pas 256 dan sla boucle mais
1024 (la taille de mon tableau).

A cause de la future utilisation de la MKL, il me faut tester ce
que va faire la MKL pour copier.
Pour etre plus claire, j'ai ceci :

struct donne
{
double Int;
double Ext;
double IntExt;
};

double Int[1024];
donne Tab[1024]; //puis a remplacer par std::vector<donne>
Tab(1024);

Je veux maintenant copier le tableau Int dans les champs Tab[x].Int
Mais pour des problemes de performances, je doit utiliser la MKL.
Or la MKL est codée en C et pas en C++ ou je ne sais trop quoi ....
Donc sa facon d'acceder a la memoire est par pointeur.
Le code que l'on t'a montré est parfaitement valide en C : Les structures



existent en C et tu as le droit d'accéder à leur champs par . ou ->.

Mais je ne peux pas utiliser les accesseurs ->Int et .Int.
En fait je cherche, dans un premier temps, à faire comme ce que ferai
la MKL, c'est a dire à n'utiliser que des pointeurs et pas d'acces
aux données de la structure par ses champs (.Int .Ext .IntExt).


C'est quoi exactement la MKL? C'est écrit en C ou en C++ non? Dans ce cas ca
comprendra parfaitement les structures et les accès aux champs de
structures.

Je ne cherche pas a programmer lisible et beau, j'ai besoin de
performance car c'est un passage critique dans mon appli... Je fait
du traitement de l'image et seules les perfs comptent (enfin presque)
Sauf que là, le code par arithmétique de pointeur "à la main" ou par les

champs de la structure sera aussi rapide : ca ne m'étonnerai pas que sur la
plupart des compilateurs, le binaire généré soit exactement le même dans les
2 cas.

Arnaud






1 2 3 4 5