Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

std::vector/std::list

8 réponses
Avatar
pasde.hcyrano.spam
bonsoir,

je vais (tenter) d'implementer une unorderer_map assez volumineuse
environ 100 000 entrées. je ne pose des question sur l'occupation
memoire.

une entrée = key + data

la key est de taille fixe, mais les data de taille variable
(possede un membre vector)

ce vector sera composé de un (cas general) a quelques elements (une
dizaine)

la question que je me pose est :

std::vector<maClass) list; ne reserve pas pas souci d'optimisation un
nombre d'element minimun?

une std::list serait elle plus approprié?
--
Bruno Causse
http://perso.wanadoo.fr/othello

8 réponses

Avatar
Fabien LE LEZ
On Mon, 23 Oct 2006 22:36:26 +0200, (Bruno
Causse):

std::vector<maClass) list; ne reserve pas pas souci d'optimisation un
nombre d'element minimun?


Si.

une std::list serait elle plus approprié?


Pas forcément.

Assure-toi de mettre des typedef partout, et essaie différentes
possibilités, s'il s'avère que ton programme prend effectivement trop
de place en mémoire avec la solution la plus simple.

Avatar
Jean-Marc Bourguet
(Bruno Causse) writes:

bonsoir,

je vais (tenter) d'implementer une unorderer_map assez volumineuse
environ 100 000 entrées. je ne pose des question sur l'occupation
memoire.

une entrée = key + data

la key est de taille fixe, mais les data de taille variable
(possede un membre vector)

ce vector sera composé de un (cas general) a quelques elements (une
dizaine)


Ça m'est arrivé d'implémenter des conteneurs avec une interface de type SL
mais une implémentation moins gourmande en mémoire. C'est quelque chose
que tu peux faire dans un second temps une fois que l'application marche.
Ce qu'il a intérêt à faire directement, c'est de prévoir le changement en
utilisant des typedef et une classe ne fournissant que l'interface
nécessaire... comme ça personne n'utilisera operator[] alors qu'il est
envisagé de pouvoir passer à une liste.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Marc Boyer
Le 24-10-2006, Fabien LE LEZ a écrit :
On Mon, 23 Oct 2006 22:36:26 +0200, (Bruno
Causse):

std::vector<maClass) list; ne reserve pas pas souci d'optimisation un
nombre d'element minimun?


Si.


Sur ?
Et avec reserve(), on peut pas le contraindre ?

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. Paul Éluard)


Avatar
Marc Boyer
Le 23-10-2006, Bruno Causse a écrit :
je vais (tenter) d'implementer une unorderer_map assez volumineuse
environ 100 000 entrées. je ne pose des question sur l'occupation
memoire.

une entrée = key + data

la key est de taille fixe, mais les data de taille variable
(possede un membre vector)

ce vector sera composé de un (cas general) a quelques elements (une
dizaine)

la question que je me pose est :

std::vector<maClass) list; ne reserve pas pas souci d'optimisation un
nombre d'element minimun?


Il y a reserve() qui devrait permettre d'influer sur cette
optimisation il me semble.

une std::list serait elle plus approprié?


Attention: deviner l'usage mémoire est difficile. Si on prend
une list, on va surement avoir une liste chainée de cellules,
chaque cellule contenant deux pointeurs vers les deux autres,
en plus de la taille de ton objet.

Ensuite, les allocateurs habituels allouent souvent des
blocs de quantité mémoire en puissance de 2. Donc, si par
malchance tu demande (2^n)+1 octets, tu en utilises réellement
2^(n+1)...

Heureusement, les conteneurs de la STL te permettent de
spécifier ton propre allocateur, qui peut être optimisé
pour l'objet maClasse.

Donc, le conseil global, c'est de faire un code le plus
indépendant possible de vector ou list, avec le plus de typedef
possible, et puis de faire des essais ensuite ;-)


Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. Paul Éluard)

Avatar
kanze
Marc Boyer wrote:
je vais (tenter) d'implementer une unorderer_map assez volumineuse
environ 100 000 entrées. je ne pose des question sur l'occupation
memoire.

une entrée = key + data

la key est de taille fixe, mais les data de taille variable
(possede un membre vector)

ce vector sera composé de un (cas general) a quelques elements (une
dizaine)

la question que je me pose est :

std::vector<maClass) list; ne reserve pas pas souci d'optimisation un
nombre d'element minimun?


Il y a reserve() qui devrait permettre d'influer sur cette
optimisation il me semble.


La norme est assez vague là-dessus, mais dans les
implémentations que je connais :

-- rien ne serait reservé avant le premier push_back ou insert,
et
-- si on sait d'avance combien d'éléments il y aura, et qu'on
fait un reserve d'autant, il n'y aurait jamais ni plus ni
moins d'alloué.

une std::list serait elle plus approprié?


Attention: deviner l'usage mémoire est difficile. Si on prend
une list, on va surement avoir une liste chainée de cellules,
chaque cellule contenant deux pointeurs vers les deux autres,
en plus de la taille de ton objet.

Ensuite, les allocateurs habituels allouent souvent des
blocs de quantité mémoire en puissance de 2. Donc, si par
malchance tu demande (2^n)+1 octets, tu en utilises réellement
2^(n+1)...


Le multiplicateur varie selon les implémentations ; je crois
qu'aujourd'hui, 1.5 est plus courant que 2.

Note que si tu laisses croître le vector de cette façon, tu
risques beaucoup de pertes suite à la fragmentation de la
mémoire aussi : si ton implémentation utilise un multiplicateur
de 2, tu risques fort qu'après (2^n)+1 allocations, tu as
utiliser de la mémoire pour 2^(n+2), dont la moitié serait
disponible pour d'autres objets (mais il faut l'avoir eu).

Heureusement, les conteneurs de la STL te permettent de
spécifier ton propre allocateur, qui peut être optimisé
pour l'objet maClasse.


Mais qui ne peut pas modifier la stratégie de croissance du
vector.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Marc Boyer
Le 24-10-2006, kanze a écrit :
Attention: deviner l'usage mémoire est difficile. Si on prend
une list, on va surement avoir une liste chainée de cellules,
chaque cellule contenant deux pointeurs vers les deux autres,
en plus de la taille de ton objet.

Ensuite, les allocateurs habituels allouent souvent des
blocs de quantité mémoire en puissance de 2. Donc, si par
malchance tu demande (2^n)+1 octets, tu en utilises réellement
2^(n+1)...


Le multiplicateur varie selon les implémentations ; je crois
qu'aujourd'hui, 1.5 est plus courant que 2.

Note que si tu laisses croître le vector de cette façon, tu
risques beaucoup de pertes suite à la fragmentation de la
mémoire aussi : si ton implémentation utilise un multiplicateur
de 2, tu risques fort qu'après (2^n)+1 allocations, tu as
utiliser de la mémoire pour 2^(n+2), dont la moitié serait
disponible pour d'autres objets (mais il faut l'avoir eu).


Je crois que nous ne nous comprenons pas: je ne dis pas que
vector croît en 2^n, je dis que l'allocateur mémoire qui
donne la mémoire à vector alloue des blocs en puissance de 2.
C'était par exemple le cas du malloc de la glibc sous Linux
la dernière fois que j'ai regardé, et il me semble que c'est
assez commun comme stratégie.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. Paul Éluard)


Avatar
James Kanze
Marc Boyer wrote:
Attention: deviner l'usage mémoire est difficile. Si on prend
une list, on va surement avoir une liste chainée de cellules,
chaque cellule contenant deux pointeurs vers les deux autres,
en plus de la taille de ton objet.

Ensuite, les allocateurs habituels allouent souvent des
blocs de quantité mémoire en puissance de 2. Donc, si par
malchance tu demande (2^n)+1 octets, tu en utilises réellement
2^(n+1)...


Le multiplicateur varie selon les implémentations ; je crois
qu'aujourd'hui, 1.5 est plus courant que 2.

Note que si tu laisses croître le vector de cette façon, tu
risques beaucoup de pertes suite à la fragmentation de la
mémoire aussi : si ton implémentation utilise un multiplicateur
de 2, tu risques fort qu'après (2^n)+1 allocations, tu as
utiliser de la mémoire pour 2^(n+2), dont la moitié serait
disponible pour d'autres objets (mais il faut l'avoir eu).


Je crois que nous ne nous comprenons pas: je ne dis pas que
vector croît en 2^n, je dis que l'allocateur mémoire qui
donne la mémoire à vector alloue des blocs en puissance de 2.
C'était par exemple le cas du malloc de la glibc sous Linux
la dernière fois que j'ai regardé, et il me semble que c'est
assez commun comme stratégie.


En effet, j'avais mal compris. Je connaissais des versions de
malloc qui fonctionnaient comme ça dans le temps, mais je crois
qu'elles ne servaient plus, et qu'on savait faire mieux depuis.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34



Avatar
Marc Boyer
Le 24-10-2006, James Kanze a écrit :
Marc Boyer wrote:
Je crois que nous ne nous comprenons pas: je ne dis pas que
vector croît en 2^n, je dis que l'allocateur mémoire qui
donne la mémoire à vector alloue des blocs en puissance de 2.
C'était par exemple le cas du malloc de la glibc sous Linux
la dernière fois que j'ai regardé, et il me semble que c'est
assez commun comme stratégie.


En effet, j'avais mal compris. Je connaissais des versions de
malloc qui fonctionnaient comme ça dans le temps, mais je crois
qu'elles ne servaient plus, et qu'on savait faire mieux depuis.


Peut-être que mes informations datent plus que les tiennes.
Quoi qu'il en soit, pour l'OP, cela ne change pas grand-chose:
commencer par faire un code qui permette dans le futur de
choisir comme conteneur soit list soit vector (soit dequeu qu'on
oublie souvent), et de proposer sont propre allocateur.

Ensuite, regarder de plus prêt la consommation mémoire.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. Paul Éluard)