Je veux un tampon arbitrairement grand dans Linux / C / C ++

Fondamentalement, je veux une stack arbitrairement grande. Je sais que ce n’est pas possible, mais pourrais-je mettre de côté quelques téraoctets de mon espace d’adressage virtuel pour cela? Je voudrais pouvoir commencer au début et monter la mémoire tampon autant que je le souhaite, et Linux peut importer des pages de la mémoire physique selon les besoins. Est-ce que quelque chose comme ça est possible? Aurait-il les mêmes performances que la simple mise en place d’un tampon? Y aurait-il un moyen de signaler à Linux que vous avez terminé avec la mémoire une fois que vous avez créé la stack?

EDIT: Je veux cela parce que je veux optimiser un algorithme récursif / parallèle qui alloue beaucoup de mémoire à chaque appel. Malloc est trop lent pour moi et je ne veux pas que tous les fils se chevauchent à l’intérieur des serrures de malloc. Donc, en gros, ce serait ma propre stack d’exécution à côté de la stack réelle (une pour chaque thread).

En fait, tant que la stack d’exécution est suffisamment grande, cela devrait suffire. Y a-t-il un moyen de connaître / assurer la taille de la stack? Dans un espace d’adressage de 64 bits, il y a assez de place pour que plusieurs threads puissent allouer des gigaoctets de données. Est-ce faisable?

Il semblerait que pthread_attr_setstacksize pourrait fonctionner pour de nouveaux threads, mais cela n’aide pas beaucoup si vous pouvez être appelé depuis n’importe quel thread …

Vous pouvez créer une telle allocation en utilisant mmap() avec MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE Drapeaux MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE . Lorsque vous voulez le libérer sur le système, utilisez munmap() .

Notez que la seule façon de savoir si la mémoire disponible est insuffisante pour satisfaire votre utilisation réelle est que votre processus reçoit un SIGSEGV – mais cela revient à demander un mappage géant beaucoup plus grand que la mémoire disponible.

Eh bien, si vous voulez une grande stack, vous pouvez toujours changer les ulimit -s . Il peut être très volumineux, du moins sur les plates-formes 64 bits.

Si vous mmap un espace anonyme, les pages physiques ne lui seront pas réellement atsortingbuées tant que vous ne les touchez pas. Vous devrez soit définir vm_overcommit ou avoir assez de swap (à moins que vous ayez autant de RAM physique). Bien sûr, mmap espace anonyme est exactement ce que fait malloc lorsque vous demandez beaucoup de mémoire.

Vous pouvez dire à Linux que vous avez terminé avec les pages utilisant madvise . Si vous appelez MADV_DONTNEED , Linux MADV_DONTNEED les pages et celles-ci devront être remplies à zéro la prochaine fois que vous tenterez d’y accéder.

Tout d’abord, la mémoire de cette taille (ou sa création, ou sa création sur la stack) aboutira presque certainement à une erreur std::bad_alloc parce que vous essayez de tout créer dans la mémoire contiguë – et vous avez certainement n’ont pas cette mémoire ininterrompue et contiguë due à la fragmentation.

Si vous utilisez un std:: container comme un deque ou un adaptateur de conteneur comme une stack (tout ce qui ne contient pas de mémoire contiguë, c’est-à-dire pas un vecteur), il utilisera une mémoire de tas extensible. Cela vous permettra de contourner cette erreur bad_alloc .

Donc, c’est possible, mais n’essayez pas de rendre la mémoire contiguë – et si vous êtes autorisé à utiliser un std:: container / adapter.

PS: si vous avez besoin de grands espaces mémoire, vous pouvez utiliser une liste de tampons dynamicment alloués (pointeurs malloc ed) d’une taille suffisante pour être utilisable mais suffisamment petite pour ne pas déclencher une exception bad_alloc ).

N’oubliez pas que les ressources sont toujours limitées par des contraintes physiques: le nombre d’atomes dans l’univers est probablement fini … Donc des tampons arbitrairement grands ne peuvent pas ssortingcto sensu exister …

Cependant, vous pouvez utiliser l’appel système Linux mmap pour afficher une partie du fichier en tant que segment de mémoire virtuelle. Si c’est très gros (plus grand que la RAM), vous aurez des problèmes de performances. Pensez à le régler avec les appels système madvise (et peut-être readahead ).

Peut-être même que l’utilisation de la fonction GCC __bultin_prefetch pourrait être utile (mais je suis sûr que madvise est plus pertinent).

Si vous avez vraiment une stack de taille téraoctet, le réglage de votre application sera très important. Apprenez à utiliser oprofile . J’espère que vous avez une machine puissante!

Et ce n’est pas vraiment suffisant pour la stack d’appels (elle est probablement limitée, par exemple via setrlimit …) Voir aussi sigaltstack (pour la stack utilisée pour la livraison du signal).

Mais qu’est-ce que vous voulez vraiment réaliser? De très gros stacks d’appels me semblent suspectes … Ou votre stack n’est-elle pas la stack d’appels?

 Create stack using two queues in that way you can have variable length of stack, which will increase as you require. implementing stack using two queues initially q1 is full and q2 empty 1] tranfer elements from q1 to q2 till last element left in q1 2] loop till q2 is not empty deque element from q2 and again push in q2 till last element is left in q2 transfer this last element in q1 reduce size of q2 by 1 3]finally q1 contains all elements in reverse order as in stack eg 1] q1 = 1 2 3 4 q2 = 2] 3 deques till last element left in q1 q1 = 4 q2 = 1 2 3 3] deque and again queue q2 till last element left q1 = 4 q2 = 3 1 2 4] deque q2 and queue q1 q1 = 4 3 q2 = 1 2 5] again deque and queue q2 till last element left q1= 4 3 q2= 2 1 6] queue q1 q1= 4 3 2 7] queue last element of q2 to q1 q1= 4 3 2 1