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

 


Dernière réponse
Sujet : Forcer la defragmentation de la RAM...
Taz j'ai pas OSX. Et je ne vois pas comment un remplissage de la pile haut vers le bas peut etre plus efficace en fait ... à part gacher des ressources. Mais bon on s'en fout, je pense pas qu'un OS9 qui utilisait un modèle préemptif collaboratif a apportait quelque chose niveau performance. À la trappe.

Votre réponse
Nom d'utilisateur    Pour poster, vous devez être inscrit sur ce forum .... si ce n'est pas le cas, cliquez ici !
Le ton de votre message                        
                       
Votre réponse


[b][i][u][strike][spoiler][fixed][cpp][url][email][img][*]   
 
   [quote]
 

Options

 
Vous avez perdu votre mot de passe ?


Vue Rapide de la discussion
Taz j'ai pas OSX. Et je ne vois pas comment un remplissage de la pile haut vers le bas peut etre plus efficace en fait ... à part gacher des ressources. Mais bon on s'en fout, je pense pas qu'un OS9 qui utilisait un modèle préemptif collaboratif a apportait quelque chose niveau performance. À la trappe.
el muchacho Il me semble que sur mac, auparavant, le remplissage de la pile se faisait "à l'envers", du haut vers le bas. C'était plus chiant pour le progueux, mais plus efficace niveau gestion des ressources. Mais sur OSX...
Taz voilà, j'ai appris un truc. En fait sur ppc, la configuration par défaut est CONFIG_TASK_SIZE=0x80000000, d'où mon adresse de base de pile relativement haute. Reste à savoir pourquoi maintenant :P
el muchacho Ok, merci, c'est très clair, cette fois-ci. :jap:
Taz 1) oui, changer d'algo. changer d'allocateur oui mais toujours avec les mêmes limites. Si t'es en C++ et que tu mmap un fichier, tu peux planquer ça dans un fichier et mapper une région à la demande. Découpe en plusieurs processus (c'est une technique courante).
 
2) tu n'as pas regarder pmap. Sur une machine 32bits, quelque soit le nombre de Go que peux adresser le noyau (avec des mécanismes d'indirections), côté utilisateur -- dans ton programme -- l'adressage mémoire est plat. Ça correspond à toute valeur stockage dans un pointeur. Donc tu comprends bien que sur 32 bits, t'es limités à 32bits. En fait moins que ça : linux partage l'espace d'adressage utilisateur en 2. Classiquement 1G noyau / 3G utilisateur. Par noyau, c'est à dire mémoire utilisé par le noyau pour un processus donné. Déjà tu n'as plus que 3G d'espace d'adressage. Ensuite, les différents segments d'un processus commencent à des offsets distincts (souvent quasi fixes(ici des exemples bidons)) : par exemple la pile va démarré à partir de la fin (on va dire 0xf......), les tas (lui d'une capacité max de 896M) à partir de 0x3......, le texte à partir de 0x08......, les mappings mémoire à partir de 0xc......., etc
 
Donc quand tu démarres ton processus, dès le départ, il y a de fragmentation inhérente. Elle est structurelle et voulue, puisque l'adressage dans un processus est directe. Ta pile a besoin d'espace réservé pour grandir (même si non alloué), idem pour le tas, etc.
 
Je suis sur que si tu fais des tests, avec un programme bidon, tu n'arriveras pas à mapper plus de 1,5G. Parce que sur l'espace d'adressage, aucune plage disponible ne fait cette taille. Donc avec un processus déjà gourmand en mémoire, c'est encore plus dur. D'où de fréquents échecs.
 
 
Là je travail sur mon ppc. Un truc m'intrigue c'est l'adresse de base de la pile qui restreint un peu plus l'espace d'adressage. Avec le programme suivant
 

Code :
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <errno.h>
  5. void * my_xmalloc(size_t n)
  6. {
  7.         char *p = malloc(n);
  8.         if (!p) {
  9.                 fprintf(stderr, "Failed to allocated %lu bytes : %s\n",
  10.                         (unsigned long)n, strerror(errno));
  11.                 exit(42);
  12.         }
  13.         p[0] = p[n/2] = p[n-1] = 'X';
  14.         return p;
  15. }
  16. int main(int argc, char **argv)
  17. {
  18.         unsigned long n, size;
  19.         unsigned long long total;
  20.         unsigned i;
  21.         void **p;
  22.         if (argc != 3)
  23.                 return 1;
  24.         n    = strtoul(argv[1], NULL, 0);
  25.         size = strtoul(argv[2], NULL, 0);
  26.         total = ((unsigned long long)n) * size;
  27.         printf("%lu * %lu = %llu (%lluM)\n", n, size, total, total >> 20);
  28.         p = my_xmalloc(n * sizeof *p);
  29.         for (i = 0; i < n; ++i)
  30.                 p[i] = my_xmalloc(size);
  31.         puts("alloc OK" );
  32.         getchar();
  33.         for (i = 0; i < n; ++i)
  34.                 free(p[i]);
  35.         free(p);
  36.         return 0;
  37. }


 
j'arrive au maximum a occuper


[16:28:06][pts/4][/tmp][#58]
benoit@ibook >>> ./a.out 18 100000000
18 * 100000000 = 1800000000 (1716M)
alloc OK
 
 
[16:28:33][pts/4][/tmp][#59]
benoit@ibook >>> ./a.out 19 100000000
19 * 100000000 = 1900000000 (1811M)
Failed to allocated 100000000 bytes : Cannot allocate memory


 
et ce, en utilisant des morceaux de 100M.
 
Par contre, le plus gros mappage mémoire possible est plus petit
 

[16:29:31][pts/4][/tmp][#66] ? 130
benoit@ibook >>> ./a.out 1 1300000000
1 * 1300000000 = 1300000000 (1239M)
alloc OK
 
 
[16:29:34][pts/4][/tmp][#67] ? 130
benoit@ibook >>> ./a.out 1 1400000000
1 * 1400000000 = 1400000000 (1335M)
Failed to allocated 1400000000 bytes : Cannot allocate memory


 
 
Bref : rien à avoir avec la mémoire du système, qui peut atteindre plusieurs G sur un système 32bits (avec des histoires de HIMEM, indirection au niveau du noyau, VM, etc). Le problème c'est que tes processus ont un adressage plat de 32bits, "fragmenté" exprès.
 
 
Anecdote : un système 64bits ça arrange tout. Sauf si t'as un OS pourri genre OSX, qui a un noyau 64bits, mais garde des process avec espace d'adressage 32bits. Résultat, apple t'explique que pour tirer partie de tout ça, il faut apprendre des techniques haut-niveau de répartition en processus. Minable

el muchacho

Taz a écrit :

pour être plus précis : si tu veux avoir un aperçu simple ->
 
/proc/<pid>/maps ça va te donner une idée de la répartition. <edit>ou bien la commande pmap, voire gnome-system-monitor->carto mémoire</edit>. Ça n'a rien à avoir avec un manque de mémoire physique contigüe. C'est numérique : y a pas la place de caser en VM un zone aussi grande (côté utilisateur j'entends)


Pourquoi ca ? La machine a 2Gig de RAM et probableemtn autant de swap.

el muchacho

Taz a écrit :

mais ça c'est en mode utilisateur ton problème. Ton espace d'adressage fait 3G et rien de plus. Si tu fragmentes ta mémoire utilisateur, un trop gros mmap échoue.
 
edit : comprendre, ce n'est pas un problème du noyau.
 
le seul moyen de défragmenter ta mémoire utilisateur, c'est de le faire toi même, à la main, y a pas d'adressage virtuel de ton côté. Donc t'es dans un bordel incomensurable. Commence par utiliser des allocateurs type pool pour réduire ça. Si t'es vraiment bloqué : t'es pas obligé de mmap'er tout d'un coup. Et tu peux aussi diviser ton programme en plusieurs processus. Où achète une machine 64bits :)


Ok, merci Taz.
Effectivement, si j'etais l'auteur du code en question, je n'aurais jamais essaye de mmapper 900 Mo d'un coup. Enfin comme d'hab, c'est historique, au depart, les fichiers en question etaient plutot 100 fois plus petits donc le pb ne se posait pas. Sinon, le prog est deja divise en plusieurs processus, et le portage en 64 bits est en cours aussi. ;~)
Mais c'est pour les produits futurs, et les produits actuels sont livres sur des machines 32 bits et la le probleme se pose de facon assez cruciale. Donc si je comprends bien, la solution au pb est: soit il faut changer les algos, soit il faut ecrire son propre allocateur ?

Taz pour être plus précis : si tu veux avoir un aperçu simple ->
 
/proc/<pid>/maps ça va te donner une idée de la répartition. <edit>ou bien la commande pmap, voire gnome-system-monitor->carto mémoire</edit>. Ça n'a rien à avoir avec un manque de mémoire physique contigüe. C'est numérique : y a pas la place de caser en VM un zone aussi grande (côté utilisateur j'entends)
Taz mais ça c'est en mode utilisateur ton problème. Ton espace d'adressage fait 3G et rien de plus. Si tu fragmentes ta mémoire utilisateur, un trop gros mmap échoue.
 
edit : comprendre, ce n'est pas un problème du noyau.
 
le seul moyen de défragmenter ta mémoire utilisateur, c'est de le faire toi même, à la main, y a pas d'adressage virtuel de ton côté. Donc t'es dans un bordel incomensurable. Commence par utiliser des allocateurs type pool pour réduire ça. Si t'es vraiment bloqué : t'es pas obligé de mmap'er tout d'un coup. Et tu peux aussi diviser ton programme en plusieurs processus. Où achète une machine 64bits :)
Mjules sur lwn, j'avais vu passer un patch noyau qui tentait de régler ce problème mais c'était pas très concluant non plus il me semble
 
en fait peut-être que si :
Yet another approach to memory fragmentation
Patch: Fragmentation Avoidance V16
Kernel Summit 2005: Virtual memory topics.
 
par contre, si tu cherches un soft qui fait ça maintenant, ça doit pas exister
black_lord le noyau est en 2.6 actuellement (je n'ai pas ouïe dire que la branche 2.7 était lancée).
 
J'ai jeté un oeil à gauche et à droite (kerneltrap notamment) mais rien de concluant
el muchacho ... sous Linux (kernel 2.7.qq chose). Est-ce possible ?
 
Autrement dit, est-il possible d'appeler une fonction du noyau, ou p-e d'un demon (kswapd ?) pour qu'il reorganise la RAM/swap afin de permettre une grosse allocation memoire (genre 900 Mo sur 2Go de RAM) ?
Le pb que j'ai, c'est que meme s'il y a >900 Mo de libre, un appel a la fonction C mmap() echoue quasi systematiquement a cause de la fragmentation, semble-t'il, et malheureusement, il n'est pas pratique de demander de plus petites allocations (probleme de design).
 
Merci.
 :jap:

Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)