pehache <
peha...@gmail.com> writes:
[...]
> Je me demandais donc si utiliser des (très gros) fichiers memory
> mapped, sur lesquels on ferait pointer les (très gros) tableaux,
> serait une solution. Ca permettrait en tous cas de ne pas toucher à
> toute la partie algo.. Je ne connais pas vraiment, et en plus le C
> moins j'en fais mieux je me porte habituellement...
>
> J'ai fait quelques tests avec des petits exemples trouvés sur le web,
> et je vois que les flag utilisés dans la commande mmap() ont vraiment
> une grosse influence sur ce qu'on peut faire et les performances.
>
> MAP_NORESERVE : je n'ai pas compris exactement ce qu'il faisait, mais
> sans lui on ne peut apparemment pas mapper un volume plus grand que la
> taille RAM+swap. J'en ai donc besoin à priori.
C'est juste le contraire : MAP_NORESERVE est une façon de dire que tu es
sûr qu'il y aura de la place (RAM ou swap), et que ce n'est pas la peine
de s'en assurer au moment du mmap. Si j'ai bien compris ce que tu
expliques plus haut, tu es sûr qi'il n'y aura pas de place. Donc, ton
programme va crasher (avec SIGSEGV) au premier accès au-delà de la
quantité RAM+swap disponible.
> MAP_SHARED : ça m'a l'air d'être exactement comme si on
> écrivait/lisait directement dans le fichier, avec le cache RAM usuel.
> Les perfs sont moyennes.
C'est le cas. Si ton mapping est basé sur un fichier existant, c'est ce
fichier qui sera utilisé pour le swap-out, et pas la zone de swap
(partition ou fichier) habituel.
> MAP_PRIVATE : perfs meilleures, mais les écritures donnent visiblement
> lieu à de l'allocation de RAM, qui n'est ensuite pas libérée. Donc une
> fois qu'on a écrit le volume correspondant à la taille de la RAM dans
> le tableau, ça swappe (et quand on atteint le volume RAM+swap ça
> coince). Une solution semble être de démapper/remapper de temps en
> temps pour forcer la RAM allouée à se vider dans le fichier et à se
> libérer.
Attention, un map private n'est pas synchronisé avec le disque (en
général il n'y a pas de fichier associé, et s'il y en a un il est juste
utilisé pour l'initialisation -- c'est pour cela que "les perfs sont
meilleures"). Donc le swap-out se fait dans la zone de swap habituelle,
donc tu es limité en taille. Ce genre de mapping est utilisé pour la
zone de données des bibliothèques partagées par exemple : en début
d'exécution on crée un map private de la section de données du ELF, et
chaque écriture provoque une copie privée pour le processus.
> L'option MAP_NORESERVE + MAP_PRIVATE me semble préférable pour mon
> cas, mais il y a peut-être mieux à faire, et je n'ai peut-être pas
> tout compris...
Avec NORESERVE+PRIVATE il te faut un espace suffisant dans RAM+swap, ce
qui ne semble pas être ton cas.
Ce que tu peux essayer est un mmap MAP_SHARED d'un fichier (existant)
qui a la taille de la mémoire dont tu as besoin. Tu fais un mmap de la
totalité, et tu laisses le système gérer le swap-in/-out (dans le
fichier donc). Puisque tu fournis l'espace de swap (le fichier), tu
n'auras pas de problème autre que les perfs (pendant le swap, qui sera
plus au moins fréquent selon le schéma des accès).
Le seul problème que tu pourrais avoir est de ne pas disposer dans
l'espace d'adressage de ton processus d'une plage assez grande. L'espace
d'adressage est en théorie de 2^64 octets, en pratique de 2^48 octets =
256 To, mais il est déjà un peu occupé par le texte, la pile, le tas,
les bibliothèques etc.
Le tout dépend de la taille des données. Si tu envisages vraiment plus
que ce qui peut tenir dans ton espace d'adresssage, il faudra gérer à la
main le swap-in/-out (ça s'appelle "out-of-core computation" en général,
et les techniques dépendent vraiment des algorithmes).
-- Alain.