Est-il possible d'allouer une grande quantité de mémoire virtuelle sous Linux ?
Peut-être. Mais vous devrez peut-être le configurer pour qu'il soit autorisé :
Le noyau Linux prend en charge les modes de gestion de surcharge suivants
0 - Gestion heuristique du surengagement. Les dépassements évidents d'espace d'adressage sont refusés. Utilisé pour un système typique. Il garantit l'échec d'une allocation sérieusement sauvage tout en permettant une surengagement pour réduire l'utilisation du swap. root est autorisé à allouer un peu plus de mémoire dans ce mode. C'est la valeur par défaut.
1 - Engagez toujours trop. Approprié pour certaines applications scientifiques. L'exemple classique est le code utilisant des tableaux clairsemés et s'appuyant uniquement sur la mémoire virtuelle composée presque entièrement de zéro page.
2 - Ne vous engagez pas trop. La validation totale de l'espace d'adressage pour le système ne doit pas dépasser swap + une quantité configurable (la valeur par défaut est de 50 %) de RAM physique. Selon la quantité que vous utilisez, dans la plupart des situations, cela signifie qu'un processus ne sera pas tué lors de l'accès aux pages, mais recevra des erreurs d'allocation de mémoire, le cas échéant.
Utile pour les applications qui veulent garantir que leurs allocations de mémoire seront disponibles à l'avenir sans avoir à initialiser chaque page.
La politique de surengagement est définie via le sysctl `vm.overcommit_memory'.
Donc, si vous voulez allouer plus de mémoire virtuelle que vous n'en avez de mémoire physique, alors vous voudriez :
# in shell
sysctl -w vm.overcommit_memory=1
RLIMIT_AS La taille maximale de la mémoire virtuelle du processus (espace d'adressage) en octets. Cette limite affecte les appels à brk(2), mmap(2) et mremap(2), qui échouent avec l'erreur ENOMEM lors du dépassement de cette limite. De plus, l'expansion automatique de la pile échouera (et générera un SIGSEGV qui tue le processus si aucune pile alternative n'a été rendue disponible via sigaltstack(2)). Comme la valeur est longue, sur les machines avec une longueur de 32 bits, soit cette limite est de 2 Gio au plus, soit cette ressource est illimitée.
Donc, vous voudriez :
setrlimit(RLIMIT_AS, {
.rlim_cur = RLIM_INFINITY,
.rlim_max = RLIM_INFINITY,
});
Ou, si vous ne pouvez pas autoriser le processus à le faire, vous pouvez le configurer de manière persistante dans /etc/security/limits.conf, ce qui affectera tous les processus (d'un utilisateur/groupe).
Ok, donc mmap semble prendre en charge ... mais cela nécessite un descripteur de fichier. ... pourrait être une victoire mais pas s'ils doivent être soutenus par un fichier ... Je n'aime pas l'idée de joindre à un fichier
Vous n'avez pas besoin d'utiliser un fichier mmap sauvegardé. Il y a MAP_ANONYMOUS pour ça.
Je ne savais pas quel numéro mettre pour demander
Ensuite, utilisez null. Exemple :
mmap(nullptr, 256*GB, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
Cela dit, si vous avez configuré le système comme décrit, alors new
devrait fonctionner aussi bien que mmap
. Il utilisera probablement malloc
qui utilisera probablement mmap
pour les grosses allocations comme celle-ci.
Astuce bonus :vous pouvez bénéficier de l'utilisation des pages HugeTLB.
La valeur de 256*GB
ne rentre pas dans une plage de type entier 32 bits. Essayez uint64_t
comme type de GB
:
constexpr uint64_t GB = 1024*1024*1024;
ou, alternativement, forcer la multiplication 64 bits :
char* p = new char[256ULL * GB];
OT :Je préférerais cette définition de GB
:
constexpr uint64_t GB = 1ULL << 30;
En ce qui concerne la limite de mémoire virtuelle, consultez cette réponse.