Fabien LE LEZ wrote:On Tue, 22 Mar 2005 16:09:43 +0100, "Bernie" :soit une variable short* toto[4], qqsoit i toto[i] (short*)malloc(64);
Je ne comprends pas bien comment tu te retrouves avec ce genre
de code dans un programme en C++.
Disons que la discussions qui s'en sont suivi, c'est un sacré
argument en faveur de std::vector:-).
Fabien LE LEZ wrote:
On Tue, 22 Mar 2005 16:09:43 +0100, "Bernie" <a.buisson@nextamp.com>:
soit une variable short* toto[4], qqsoit i toto[i] (short*)malloc(64);
Je ne comprends pas bien comment tu te retrouves avec ce genre
de code dans un programme en C++.
Disons que la discussions qui s'en sont suivi, c'est un sacré
argument en faveur de std::vector:-).
Fabien LE LEZ wrote:On Tue, 22 Mar 2005 16:09:43 +0100, "Bernie" :soit une variable short* toto[4], qqsoit i toto[i] (short*)malloc(64);
Je ne comprends pas bien comment tu te retrouves avec ce genre
de code dans un programme en C++.
Disons que la discussions qui s'en sont suivi, c'est un sacré
argument en faveur de std::vector:-).
* Pour des questions de performances (appli video tps-reelles ou "pseudo"
tps-reelles), j'utilise du C et de l'asm(MMX/SSE2) à bas niveau.
Enfin, pour finir, au contraire, je tente de limiter autant que faire ce peu
l'usage des container std, car si il sont simple et rapide à utiliser pour
implémenter un algo, il faut à postériori reprendre le code, pour que
celui-ci ne soit pas trop gourmand en tps et ressources.
* Pour des questions de performances (appli video tps-reelles ou "pseudo"
tps-reelles), j'utilise du C et de l'asm(MMX/SSE2) à bas niveau.
Enfin, pour finir, au contraire, je tente de limiter autant que faire ce peu
l'usage des container std, car si il sont simple et rapide à utiliser pour
implémenter un algo, il faut à postériori reprendre le code, pour que
celui-ci ne soit pas trop gourmand en tps et ressources.
* Pour des questions de performances (appli video tps-reelles ou "pseudo"
tps-reelles), j'utilise du C et de l'asm(MMX/SSE2) à bas niveau.
Enfin, pour finir, au contraire, je tente de limiter autant que faire ce peu
l'usage des container std, car si il sont simple et rapide à utiliser pour
implémenter un algo, il faut à postériori reprendre le code, pour que
celui-ci ne soit pas trop gourmand en tps et ressources.
On Thu, 24 Mar 2005 08:26:07 +0100, "Bernie" :
[...]
Enfin, pour finir, au contraire, je tente de limiter autant que faire ce peu
l'usage des container std, car si il sont simple et rapide à utiliser pour
implémenter un algo, il faut à postériori reprendre le code, pour que
celui-ci ne soit pas trop gourmand en tps et ressources.
Dans ce cas, il faut prendre le problème dans le bon sens : créer des
conteneurs qui répondent à tes critères.
std::vector<> est un conteneur à accès très rapide, mais qui utilise
plus de mémoire que nécessaire (c'est le prix de push_back), et
initialise systématiquement les variables contenues.
Le fichier <http://perso.edulang.com/fclc++/tableau.bricolage.zip>
contient un exemple de conteneur qui pourrait de convenir. J'ai mis le
mot "bricolage" dans le nom car son bon fonctionnement est loin d'être
garanti, et je n'ai pas le temps de tester. Mais normalement, son
usage devrait être aussi rapide et efficace que tes malloc(). Tu peux
même remplacer new[] et delete[] par malloc() et free() si ça te
chante, tant que tu n'utilises que des types de base.
On Thu, 24 Mar 2005 08:26:07 +0100, "Bernie" <a.buisson@nextamp.com>:
[...]
Enfin, pour finir, au contraire, je tente de limiter autant que faire ce peu
l'usage des container std, car si il sont simple et rapide à utiliser pour
implémenter un algo, il faut à postériori reprendre le code, pour que
celui-ci ne soit pas trop gourmand en tps et ressources.
Dans ce cas, il faut prendre le problème dans le bon sens : créer des
conteneurs qui répondent à tes critères.
std::vector<> est un conteneur à accès très rapide, mais qui utilise
plus de mémoire que nécessaire (c'est le prix de push_back), et
initialise systématiquement les variables contenues.
Le fichier <http://perso.edulang.com/fclc++/tableau.bricolage.zip>
contient un exemple de conteneur qui pourrait de convenir. J'ai mis le
mot "bricolage" dans le nom car son bon fonctionnement est loin d'être
garanti, et je n'ai pas le temps de tester. Mais normalement, son
usage devrait être aussi rapide et efficace que tes malloc(). Tu peux
même remplacer new[] et delete[] par malloc() et free() si ça te
chante, tant que tu n'utilises que des types de base.
On Thu, 24 Mar 2005 08:26:07 +0100, "Bernie" :
[...]
Enfin, pour finir, au contraire, je tente de limiter autant que faire ce peu
l'usage des container std, car si il sont simple et rapide à utiliser pour
implémenter un algo, il faut à postériori reprendre le code, pour que
celui-ci ne soit pas trop gourmand en tps et ressources.
Dans ce cas, il faut prendre le problème dans le bon sens : créer des
conteneurs qui répondent à tes critères.
std::vector<> est un conteneur à accès très rapide, mais qui utilise
plus de mémoire que nécessaire (c'est le prix de push_back), et
initialise systématiquement les variables contenues.
Le fichier <http://perso.edulang.com/fclc++/tableau.bricolage.zip>
contient un exemple de conteneur qui pourrait de convenir. J'ai mis le
mot "bricolage" dans le nom car son bon fonctionnement est loin d'être
garanti, et je n'ai pas le temps de tester. Mais normalement, son
usage devrait être aussi rapide et efficace que tes malloc(). Tu peux
même remplacer new[] et delete[] par malloc() et free() si ça te
chante, tant que tu n'utilises que des types de base.
std::vector<> est un conteneur à accès très rapide, mais qui utilise
plus de mémoire que nécessaire (c'est le prix de push_back), et
initialise systématiquement les variables contenues.
Je ne comprend pas ces deux affirmations. Pourquoi plus de mémoire que
nécessaire ?
Et si le vector contient des variables, comment celles-ci
pourraient-être non initialisées ?
J'y ai jeté rapidement un oeil et il me semble que cette implémentation
initialise systématiquement les variables contenues
Et je n'ai pas compris l'interêt des Resize.
Je pense que l'utilisation de vector serait plus efficace.
std::vector<> est un conteneur à accès très rapide, mais qui utilise
plus de mémoire que nécessaire (c'est le prix de push_back), et
initialise systématiquement les variables contenues.
Je ne comprend pas ces deux affirmations. Pourquoi plus de mémoire que
nécessaire ?
Et si le vector contient des variables, comment celles-ci
pourraient-être non initialisées ?
J'y ai jeté rapidement un oeil et il me semble que cette implémentation
initialise systématiquement les variables contenues
Et je n'ai pas compris l'interêt des Resize.
Je pense que l'utilisation de vector serait plus efficace.
std::vector<> est un conteneur à accès très rapide, mais qui utilise
plus de mémoire que nécessaire (c'est le prix de push_back), et
initialise systématiquement les variables contenues.
Je ne comprend pas ces deux affirmations. Pourquoi plus de mémoire que
nécessaire ?
Et si le vector contient des variables, comment celles-ci
pourraient-être non initialisées ?
J'y ai jeté rapidement un oeil et il me semble que cette implémentation
initialise systématiquement les variables contenues
Et je n'ai pas compris l'interêt des Resize.
Je pense que l'utilisation de vector serait plus efficace.
On Thu, 24 Mar 2005 20:40:35 +0100, Bertrand Motuelle
:std::vector<> est un conteneur à accès très rapide, mais qui utilise
plus de mémoire que nécessaire (c'est le prix de push_back), et
initialise systématiquement les variables contenues.
Je ne comprend pas ces deux affirmations. Pourquoi plus de mémoire que
nécessaire ?
Si un vector<> a alloué de la place pour 1000 éléments, et que tu
insères un 1001è élément, il va devoir allouer plus de mémoire, puis
transférer les éléments contenus vers le nouveau bloc alloué. Pour
éviter que ça n'arrive trop souvent, il va allouer tout de suite assez
de place pour 1414 éléments, histoire de voir venir.
Et si le vector contient des variables, comment celles-ci
pourraient-être non initialisées ?
On parle ici de tableaux contenant des types de base (cf sujet du
thread).
J'y ai jeté rapidement un oeil et il me semble que cette implémentation
initialise systématiquement les variables contenues
Si les valeurs contenues sont des short, non.
Je pense que l'utilisation de vector serait plus efficace.
Mon code (qui, je le rappelle, n'est pour l'instant guère plus qu'un
vague bricolage) a au moins un avantage sur vector<> : il alloue
exactement la mémoire nécessaire, pas plus. Quand tu as un tableau
dont la taille représente une proportion importante de la quantité de
RAM, ce n'est pas négligeable.
Bien sûr, il faut connaître à l'avance le nombre d'éléments.
On Thu, 24 Mar 2005 20:40:35 +0100, Bertrand Motuelle
<tib.motuelle@laposte.net>:
std::vector<> est un conteneur à accès très rapide, mais qui utilise
plus de mémoire que nécessaire (c'est le prix de push_back), et
initialise systématiquement les variables contenues.
Je ne comprend pas ces deux affirmations. Pourquoi plus de mémoire que
nécessaire ?
Si un vector<> a alloué de la place pour 1000 éléments, et que tu
insères un 1001è élément, il va devoir allouer plus de mémoire, puis
transférer les éléments contenus vers le nouveau bloc alloué. Pour
éviter que ça n'arrive trop souvent, il va allouer tout de suite assez
de place pour 1414 éléments, histoire de voir venir.
Et si le vector contient des variables, comment celles-ci
pourraient-être non initialisées ?
On parle ici de tableaux contenant des types de base (cf sujet du
thread).
J'y ai jeté rapidement un oeil et il me semble que cette implémentation
initialise systématiquement les variables contenues
Si les valeurs contenues sont des short, non.
Je pense que l'utilisation de vector serait plus efficace.
Mon code (qui, je le rappelle, n'est pour l'instant guère plus qu'un
vague bricolage) a au moins un avantage sur vector<> : il alloue
exactement la mémoire nécessaire, pas plus. Quand tu as un tableau
dont la taille représente une proportion importante de la quantité de
RAM, ce n'est pas négligeable.
Bien sûr, il faut connaître à l'avance le nombre d'éléments.
On Thu, 24 Mar 2005 20:40:35 +0100, Bertrand Motuelle
:std::vector<> est un conteneur à accès très rapide, mais qui utilise
plus de mémoire que nécessaire (c'est le prix de push_back), et
initialise systématiquement les variables contenues.
Je ne comprend pas ces deux affirmations. Pourquoi plus de mémoire que
nécessaire ?
Si un vector<> a alloué de la place pour 1000 éléments, et que tu
insères un 1001è élément, il va devoir allouer plus de mémoire, puis
transférer les éléments contenus vers le nouveau bloc alloué. Pour
éviter que ça n'arrive trop souvent, il va allouer tout de suite assez
de place pour 1414 éléments, histoire de voir venir.
Et si le vector contient des variables, comment celles-ci
pourraient-être non initialisées ?
On parle ici de tableaux contenant des types de base (cf sujet du
thread).
J'y ai jeté rapidement un oeil et il me semble que cette implémentation
initialise systématiquement les variables contenues
Si les valeurs contenues sont des short, non.
Je pense que l'utilisation de vector serait plus efficace.
Mon code (qui, je le rappelle, n'est pour l'instant guère plus qu'un
vague bricolage) a au moins un avantage sur vector<> : il alloue
exactement la mémoire nécessaire, pas plus. Quand tu as un tableau
dont la taille représente une proportion importante de la quantité de
RAM, ce n'est pas négligeable.
Bien sûr, il faut connaître à l'avance le nombre d'éléments.
Si un vector<> a alloué de la place pour 1000 éléments, et que tu
insères un 1001è élément, il va devoir allouer plus de mémoire, puis
transférer les éléments contenus vers le nouveau bloc alloué. Pour
éviter que ça n'arrive trop souvent, il va allouer tout de suite assez
de place pour 1414 éléments, histoire de voir venir.
On parle ici de tableaux contenant des types de base (cf sujet du
thread).
Or, un type de base n'a ni constructeur, ni valeur par défaut. En
d'autres termes, le code
short n;
est parfaitement valide, mais il n'est pas possible de prévoir la
valeur de n. L'avantage (rarement sensible, mais ça semble important
ici) est qu'on évite une écriture en mémoire.
Si un vector<> a alloué de la place pour 1000 éléments, et que tu
insères un 1001è élément, il va devoir allouer plus de mémoire, puis
transférer les éléments contenus vers le nouveau bloc alloué. Pour
éviter que ça n'arrive trop souvent, il va allouer tout de suite assez
de place pour 1414 éléments, histoire de voir venir.
On parle ici de tableaux contenant des types de base (cf sujet du
thread).
Or, un type de base n'a ni constructeur, ni valeur par défaut. En
d'autres termes, le code
short n;
est parfaitement valide, mais il n'est pas possible de prévoir la
valeur de n. L'avantage (rarement sensible, mais ça semble important
ici) est qu'on évite une écriture en mémoire.
Si un vector<> a alloué de la place pour 1000 éléments, et que tu
insères un 1001è élément, il va devoir allouer plus de mémoire, puis
transférer les éléments contenus vers le nouveau bloc alloué. Pour
éviter que ça n'arrive trop souvent, il va allouer tout de suite assez
de place pour 1414 éléments, histoire de voir venir.
On parle ici de tableaux contenant des types de base (cf sujet du
thread).
Or, un type de base n'a ni constructeur, ni valeur par défaut. En
d'autres termes, le code
short n;
est parfaitement valide, mais il n'est pas possible de prévoir la
valeur de n. L'avantage (rarement sensible, mais ça semble important
ici) est qu'on évite une écriture en mémoire.
Si un vector<> a alloué de la place pour 1000 éléments, et
que tu insères un 1001è élément, il va devoir allouer plus
de mémoire, puis transférer les éléments contenus vers le
nouveau bloc alloué. Pour éviter que ça n'arrive trop
souvent, il va allouer tout de suite assez de place pour
1414 éléments, histoire de voir venir.
Il peut allouer ce qu'il veut, tant que ça suit une croissance
géométrique, le coefficient ne vaut pas forcément sqrt(2)
[...]On parle ici de tableaux contenant des types de base (cf
sujet du thread). Or, un type de base n'a ni constructeur,
ni valeur par défaut. En d'autres termes, le code
short n;
est parfaitement valide, mais il n'est pas possible de
prévoir la valeur de n.
Si un vector<> a alloué de la place pour 1000 éléments, et
que tu insères un 1001è élément, il va devoir allouer plus
de mémoire, puis transférer les éléments contenus vers le
nouveau bloc alloué. Pour éviter que ça n'arrive trop
souvent, il va allouer tout de suite assez de place pour
1414 éléments, histoire de voir venir.
Il peut allouer ce qu'il veut, tant que ça suit une croissance
géométrique, le coefficient ne vaut pas forcément sqrt(2)
[...]
On parle ici de tableaux contenant des types de base (cf
sujet du thread). Or, un type de base n'a ni constructeur,
ni valeur par défaut. En d'autres termes, le code
short n;
est parfaitement valide, mais il n'est pas possible de
prévoir la valeur de n.
Si un vector<> a alloué de la place pour 1000 éléments, et
que tu insères un 1001è élément, il va devoir allouer plus
de mémoire, puis transférer les éléments contenus vers le
nouveau bloc alloué. Pour éviter que ça n'arrive trop
souvent, il va allouer tout de suite assez de place pour
1414 éléments, histoire de voir venir.
Il peut allouer ce qu'il veut, tant que ça suit une croissance
géométrique, le coefficient ne vaut pas forcément sqrt(2)
[...]On parle ici de tableaux contenant des types de base (cf
sujet du thread). Or, un type de base n'a ni constructeur,
ni valeur par défaut. En d'autres termes, le code
short n;
est parfaitement valide, mais il n'est pas possible de
prévoir la valeur de n.
Loïc Joly wrote:Il peut allouer ce qu'il veut, tant que ça suit une croissance
géométrique, le coefficient ne vaut pas forcément sqrt(2)
Il me semble avoir lu cependant que selon certains critères,
sqrt(2) est le facteur idéal. Ce qui est certain, c'est qu'avec
un facteur de 2 (qui était le facteur le plus fréquent au
début), la somme des tailles des blocs libérés ne suffirait
jamais à une nouvelle allocation ; pour tout multiple
strictement inférieur à 2, on y arrivera éventuellement.
À vrai dire, je ne vois pas l'intérêt de sqrt(2) quand 1,5 se
calcule beaucoup plus facilement (n += n >> 1), et a à peu près
le même comportement.
Loïc Joly wrote:
Il peut allouer ce qu'il veut, tant que ça suit une croissance
géométrique, le coefficient ne vaut pas forcément sqrt(2)
Il me semble avoir lu cependant que selon certains critères,
sqrt(2) est le facteur idéal. Ce qui est certain, c'est qu'avec
un facteur de 2 (qui était le facteur le plus fréquent au
début), la somme des tailles des blocs libérés ne suffirait
jamais à une nouvelle allocation ; pour tout multiple
strictement inférieur à 2, on y arrivera éventuellement.
À vrai dire, je ne vois pas l'intérêt de sqrt(2) quand 1,5 se
calcule beaucoup plus facilement (n += n >> 1), et a à peu près
le même comportement.
Loïc Joly wrote:Il peut allouer ce qu'il veut, tant que ça suit une croissance
géométrique, le coefficient ne vaut pas forcément sqrt(2)
Il me semble avoir lu cependant que selon certains critères,
sqrt(2) est le facteur idéal. Ce qui est certain, c'est qu'avec
un facteur de 2 (qui était le facteur le plus fréquent au
début), la somme des tailles des blocs libérés ne suffirait
jamais à une nouvelle allocation ; pour tout multiple
strictement inférieur à 2, on y arrivera éventuellement.
À vrai dire, je ne vois pas l'intérêt de sqrt(2) quand 1,5 se
calcule beaucoup plus facilement (n += n >> 1), et a à peu près
le même comportement.
wrote:Loïc Joly wrote:Il peut allouer ce qu'il veut, tant que ça suit une croissance
géométrique, le coefficient ne vaut pas forcément sqrt(2)
Il me semble avoir lu cependant que selon certains critères,
sqrt(2) est le facteur idéal. Ce qui est certain, c'est qu'avec
un facteur de 2 (qui était le facteur le plus fréquent au
début), la somme des tailles des blocs libérés ne suffirait
jamais à une nouvelle allocation ; pour tout multiple
strictement inférieur à 2, on y arrivera éventuellement.
Je crois qu'il faut pour cela que le facteur soit inférieur au
"nombre d'or" (1 + sqrt(5))/2 == 1.618... mais je me ne souviens
plus des détails.
À vrai dire, je ne vois pas l'intérêt de sqrt(2) quand 1,5 se
calcule beaucoup plus facilement (n += n >> 1), et a à peu près
le même comportement.
Effectivement !
kanze@gabi-soft.fr wrote:
Loïc Joly wrote:
Il peut allouer ce qu'il veut, tant que ça suit une croissance
géométrique, le coefficient ne vaut pas forcément sqrt(2)
Il me semble avoir lu cependant que selon certains critères,
sqrt(2) est le facteur idéal. Ce qui est certain, c'est qu'avec
un facteur de 2 (qui était le facteur le plus fréquent au
début), la somme des tailles des blocs libérés ne suffirait
jamais à une nouvelle allocation ; pour tout multiple
strictement inférieur à 2, on y arrivera éventuellement.
Je crois qu'il faut pour cela que le facteur soit inférieur au
"nombre d'or" (1 + sqrt(5))/2 == 1.618... mais je me ne souviens
plus des détails.
À vrai dire, je ne vois pas l'intérêt de sqrt(2) quand 1,5 se
calcule beaucoup plus facilement (n += n >> 1), et a à peu près
le même comportement.
Effectivement !
wrote:Loïc Joly wrote:Il peut allouer ce qu'il veut, tant que ça suit une croissance
géométrique, le coefficient ne vaut pas forcément sqrt(2)
Il me semble avoir lu cependant que selon certains critères,
sqrt(2) est le facteur idéal. Ce qui est certain, c'est qu'avec
un facteur de 2 (qui était le facteur le plus fréquent au
début), la somme des tailles des blocs libérés ne suffirait
jamais à une nouvelle allocation ; pour tout multiple
strictement inférieur à 2, on y arrivera éventuellement.
Je crois qu'il faut pour cela que le facteur soit inférieur au
"nombre d'or" (1 + sqrt(5))/2 == 1.618... mais je me ne souviens
plus des détails.
À vrai dire, je ne vois pas l'intérêt de sqrt(2) quand 1,5 se
calcule beaucoup plus facilement (n += n >> 1), et a à peu près
le même comportement.
Effectivement !
wrote:
Loïc Joly wrote:
Il peut allouer ce qu'il veut, tant que ça suit une
croissance géométrique, le coefficient ne vaut pas forcément
sqrt(2)
Il me semble avoir lu cependant que selon certains critères,
sqrt(2) est le facteur idéal. Ce qui est certain, c'est
qu'avec un facteur de 2 (qui était le facteur le plus
fréquent au début), la somme des tailles des blocs libérés ne
suffirait jamais à une nouvelle allocation ; pour tout
multiple strictement inférieur à 2, on y arrivera
éventuellement.
Je crois qu'il faut pour cela que le facteur soit inférieur au
"nombre d'or" (1 + sqrt(5))/2 == 1.618... mais je me ne
souviens plus des détails.
kanze@gabi-soft.fr wrote:
Loïc Joly wrote:
Il peut allouer ce qu'il veut, tant que ça suit une
croissance géométrique, le coefficient ne vaut pas forcément
sqrt(2)
Il me semble avoir lu cependant que selon certains critères,
sqrt(2) est le facteur idéal. Ce qui est certain, c'est
qu'avec un facteur de 2 (qui était le facteur le plus
fréquent au début), la somme des tailles des blocs libérés ne
suffirait jamais à une nouvelle allocation ; pour tout
multiple strictement inférieur à 2, on y arrivera
éventuellement.
Je crois qu'il faut pour cela que le facteur soit inférieur au
"nombre d'or" (1 + sqrt(5))/2 == 1.618... mais je me ne
souviens plus des détails.
wrote:
Loïc Joly wrote:
Il peut allouer ce qu'il veut, tant que ça suit une
croissance géométrique, le coefficient ne vaut pas forcément
sqrt(2)
Il me semble avoir lu cependant que selon certains critères,
sqrt(2) est le facteur idéal. Ce qui est certain, c'est
qu'avec un facteur de 2 (qui était le facteur le plus
fréquent au début), la somme des tailles des blocs libérés ne
suffirait jamais à une nouvelle allocation ; pour tout
multiple strictement inférieur à 2, on y arrivera
éventuellement.
Je crois qu'il faut pour cela que le facteur soit inférieur au
"nombre d'or" (1 + sqrt(5))/2 == 1.618... mais je me ne
souviens plus des détails.