Question

Contexte: j'écris un programme C ++ utilisant de grandes quantités de géodonnées et souhaite charger de gros morceaux à traiter en une seule fois. Je suis contraint de travailler avec une application compilée pour les machines 32 bits. La machine sur laquelle je teste fonctionne sous un système d'exploitation 64 bits (Windows 7) et dispose de 6 Go de RAM. Utilisation de MS VS 2008.

J'ai le code suivant:

byte* pTempBuffer2[3];
try
{
    //size_t nBufSize = nBandBytes*m_nBandCount;
    pTempBuffer2[0] = new byte[nBandBytes];
    pTempBuffer2[1] = new byte[nBandBytes];
    pTempBuffer2[2] = new byte[nBandBytes];
}
catch (std::bad_alloc)
{
    // If we didn't get the memory just don't buffer and we will get data one
    // piece at a time.
    return;
}

J'espérais pouvoir allouer de la mémoire jusqu'à ce que l'application atteigne la limite d'adressage 32 bits de 4 gigaoctets. Cependant, lorsque nBandBytes est 466 560 000, le nouveau jette std :: bad_alloc à la deuxième tentative. À ce stade, la valeur de l'ensemble de travail (mémoire) pour le processus est de 665 232 Ko. Donc, il semble que je ne puisse pas obtenir même un gig de mémoire allouée.

Il a été fait mention d'une limite de 2 Go pour les applications Windows 32 bits pouvant être étendue à 3 Go avec le commutateur / 3GB pour win32. C’est un bon conseil dans ce contexte, mais n’est pas pertinent en l’espèce.

Combien de mémoire devriez-vous pouvoir allouer sous un système d'exploitation 64 bits avec une application 32 bits?

Était-ce utile?

La solution

Autant que l'OS veut vous en donner. Par défaut, Windows permet à un processus 32 bits de disposer de 2 Go d'espace d'adressage. Et ceci est divisé en plusieurs morceaux. Une zone est réservée à la pile, d'autres à chaque exécutable et à une dll chargée. Tout ce qui reste peut être alloué dynamiquement, mais rien ne garantit qu'il s'agira d'un gros morceau contigu. Il peut s'agir de plusieurs petits morceaux de quelques centaines de Mo chacun.

Si vous compilez avec l'indicateur LargeAddressAware, Windows 64 bits vous permettra d'utiliser l'intégralité de l'espace d'adressage de 4 Go, ce qui devrait vous aider un peu, mais en général,

  • vous ne devriez pas supposer que la mémoire disponible est contiguë. Vous devriez pouvoir travailler avec plusieurs petites allocations plutôt que quelques grandes, et
  • Vous devez le compiler en tant qu’application 64 bits si vous avez besoin de beaucoup de mémoire.

Autres conseils

Sous Windows 32 bits, le processus normal peut prendre 2 Go au maximum, mais avec / 3GB , il peut atteindre 3 Go (pour Windows 2003).

mais dans votre cas, je pense que vous allouez de la mémoire contiguë et que l’exception s’est produite.

Vous pouvez allouer autant de mémoire que votre fichier de page vous le permet. Même sans le commutateur / 3GB, vous pouvez allouer 4 Go de mémoire sans trop de difficulté.

Lire cet article pour un bon aperçu de la réflexion sur la mémoire physique, la mémoire virtuelle et l'espace d'adressage (les trois sont des éléments différents). En résumé, vous avez exactement la même quantité de mémoire physique que de RAM, mais votre application n’a vraiment aucune interaction avec cette mémoire physique. C’est un endroit pratique pour stocker les données dans votre mémoire virtuelle. Votre mémoire virtuelle est limitée par la taille de votre fichier d'échange et la quantité d'utilisation que votre application peut utiliser est limitée par celle des autres applications (bien que vous puissiez en allouer plus, à condition de ne pas l'utiliser). Votre espace d'adressage dans le monde 32 bits est de 4 Go. Parmi ceux-ci, 2 Go sont alloués au noyau (ou 1 Go si vous utilisez le commutateur / 3BG). Parmi les 2 Go restants, certains vont être utilisés par votre pile, d'autres par le programme que vous exécutez actuellement (et toutes les dll, etc.). Cela va se fragmenter et vous ne pourrez obtenir qu'un espace aussi contigu - c'est là que votre allocation échoue. Mais comme cet espace d'adressage n'est qu'un moyen pratique d'accéder à la mémoire virtuelle que vous avez allouée, il est possible d'allouer beaucoup plus de mémoire et d'en importer des fragments à la fois dans votre espace d'adressage.

Raymond Chen a un exemple de comment pour allouer 4 Go de mémoire et en mapper une partie dans une partie de votre espace d'adressage.

Sous Windows 32 bits, l’allocation maximale est de 16 To et 256 To dans Windows 64 bits.

Et si vous connaissez vraiment le fonctionnement de la gestion de la mémoire dans Windows, lisez cet article .

Au cours du projet ElephantsDream, Blender Foundation avec Blender 3D rencontrait des problèmes similaires (bien que sur Mac). Impossible d'inclure le lien mais google: problème d'allocation de mémoire de blender3d et ce sera le premier élément.

La solution impliquait le mappage de fichiers. Je n'ai pas essayé moi-même, mais vous pouvez en lire plus ici: http://msdn.microsoft.com/en-us/library/aa366556 (VS.85) .aspx

Avec nBandBytes à 466 560 000, vous essayez d’allouer 1,4 Go. Une application 32 bits n'a généralement accès qu'à 2 Go de mémoire (davantage si vous démarrez avec / 3GB et que l'exécutable est marqué comme compatible avec un grand espace d'adressage). Vous aurez peut-être du mal à trouver autant de blocs d'espace d'adressage contigu pour vos gros morceaux de mémoire.

Si vous souhaitez allouer des gigaoctets de mémoire sur un système d'exploitation 64 bits, utilisez un processus 64 bits.

Vous devriez pouvoir allouer un total d'environ 2 Go par processus. les détails. Cependant, vous ne pourrez probablement pas obtenir un seul bloc contigu qui soit même proche de cette taille.

Même si vous allouez par petits morceaux, vous ne pourrez pas obtenir la mémoire dont vous avez besoin, en particulier si le programme environnant a un comportement de mémoire imprévisible ou si vous devez exécuter un système d'exploitation différent. D'après mon expérience, l'espace de mémoire d'un processus 32 bits est limité à environ 1,2 Go.

Avec cette quantité de mémoire, je vous recommande d’écrire manuellement sur le disque. Enveloppez vos tableaux dans une classe qui gère la mémoire et écrit dans des fichiers temporaires lorsque cela est nécessaire. Espérons que les caractéristiques de votre programme sont telles que vous pouvez effectivement mettre en cache des parties de ces données sans trop frapper le disque.

La carte VMMap de Sysinternals est idéale pour étudier la fragmentation d'espace d'adressage virtuel, ce qui limite probablement la quantité de mémoire contiguë que vous pouvez allouer. Je recommande de le configurer pour qu'il affiche l'espace libre, puis trie par taille pour trouver les zones libres les plus grandes, puis par adresse pour voir ce qui sépare les zones libres les plus grandes (probablement DLL redéfinies, régions de mémoire partagée ou autres segments).

Éviter les allocations extrêmement grandes contiguës est probablement préférable, comme d'autres l'ont suggéré.

La définition de LARGE_ADDRESS_AWARE = ??YES (comme suggéré par Jalf) est bonne, à condition que les bibliothèques dont dépend votre application soient compatibles avec celle-ci. Dans ce cas, vous devez tester votre code avec le < code> AllocationPreference défini dans la clé de registre pour permettre l'allocation d'adresses virtuelles de haut en bas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top