Comme vous l'avez probablement compris, le problème est que vous essayez d'allouer un gros bloc de mémoire contigu, qui ne fonctionne pas en raison de la fragmentation de la mémoire. Si j'avais besoin de faire ce que vous faites, je ferais ce qui suit:
int sizeA = 10000,
sizeB = 10000;
double sizeInMegabytes = (sizeA * sizeB * 8.0) / 1024.0 / 1024.0; //762 mb
double[][] randomNumbers = new double[sizeA][];
for (int i = 0; i < randomNumbers.Length; i++)
{
randomNumbers[i] = new double[sizeB];
}
Ensuite, pour obtenir un index particulier que vous utiliseriez randomNumbers[i / sizeB][i % sizeB]
.
Une autre option si vous accédez toujours aux valeurs dans l'ordre peut être d'utiliser le constructeur surchargé pour spécifier la valeur de départ. De cette façon, vous obtiendrez un nombre semi-aléatoire (comme le DateTime.Now.Ticks
) stockez-le dans une variable, puis chaque fois que vous commencez à parcourir la liste, vous créez une nouvelle instance aléatoire en utilisant la graine d'origine:
private static int randSeed = (int)DateTime.Now.Ticks; //Must stay the same unless you want to get different random numbers.
private static Random GetNewRandomIterator()
{
return new Random(randSeed);
}
Il est important de noter que si le blog lié à la réponse de Fredrik Mörk indique que le problème est généralement dû à un manque d' espace d'adressage, il ne répertorie pas un certain nombre d'autres problèmes, comme la limite de taille d'objet CLR de 2 Go (mentionnée dans un commentaire de ShuggyCoUk sur le même blog), passe sous silence la fragmentation de la mémoire et ne mentionne pas l'impact de la taille du fichier d'échange (et comment il peut être résolu avec l'utilisation de la CreateFileMapping
fonction ).
La limitation de 2 Go signifie qu'elle randomNumbers
doit être inférieure à 2 Go. Puisque les tableaux sont des classes et ont eux-mêmes une surcharge, cela signifie qu'un tableau de double
devra être plus petit que 2 ^ 31. Je ne sais pas à quel point la longueur devrait être inférieure à 2 ^ 31, mais les frais généraux d'un tableau .NET?indique 12 à 16 octets.
La fragmentation de la mémoire est très similaire à la fragmentation du disque dur. Vous pouvez avoir 2 Go d'espace d'adressage, mais lorsque vous créez et détruisez des objets, il y aura des écarts entre les valeurs. Si ces espaces sont trop petits pour votre gros objet et qu'un espace supplémentaire ne peut pas être demandé, vous obtiendrez leSystem.OutOfMemoryException
. Par exemple, si vous créez 2 millions d'objets de 1 024 octets, vous utilisez 1,9 Go. Si vous supprimez chaque objet dont l'adresse n'est pas un multiple de 3, vous utiliserez 0,6 Go de mémoire, mais il sera réparti dans l'espace d'adressage avec des blocs ouverts de 2024 octets entre les deux. Si vous avez besoin de créer un objet de 0,2 Go, vous ne pourrez pas le faire car il n'y a pas de bloc assez grand pour le ranger et un espace supplémentaire ne peut pas être obtenu (en supposant un environnement 32 bits). Les solutions possibles à ce problème sont des choses comme l'utilisation d'objets plus petits, la réduction de la quantité de données que vous stockez en mémoire ou l'utilisation d'un algorithme de gestion de la mémoire pour limiter / empêcher la fragmentation de la mémoire. Il convient de noter qu'à moins que vous ne développiez un programme volumineux qui utilise une grande quantité de mémoire, cela ne sera pas un problème. Aussi,
Étant donné que la plupart des programmes demandent de la mémoire de travail au système d'exploitation et ne demandent pas de mappage de fichiers, ils seront limités par la RAM du système et la taille du fichier d'échange. Comme indiqué dans le commentaire de Néstor Sánchez (Néstor Sánchez) sur le blog, avec du code géré comme C #, vous êtes bloqué sur la limitation RAM / fichier de page et l'espace d'adressage du système d'exploitation.
C'était beaucoup plus long que prévu. Espérons que cela aide quelqu'un. Je l'ai posté parce que je suis tombé sur l' System.OutOfMemoryException
exécution d'un programme x64 sur un système avec 24 Go de RAM, même si mon tableau ne contenait que 2 Go de contenu.