Comme vous l'avez probablement compris, le problème est que vous essayez d'allouer un grand bloc contigu de mémoire, ce 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 indice particulier, il faut utiliser randomNumbers[i / sizeB][i % sizeB]
.
Une autre option si vous accédez toujours aux valeurs dans l'ordre pourrait être d'utiliser le constructeur surchargé pour spécifier la graine. De cette façon, vous obtiendrez un nombre semi-aléatoire (comme la fonction DateTime.Now.Ticks
) la stocker dans une variable, puis, lorsque 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 dont le lien figure dans la réponse de Fredrik Mörk indique que le problème est généralement dû à un manque de espace adresse il n'énumère pas un certain nombre d'autres problèmes, comme la limitation de la taille des objets CLR à 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 des fichiers de page (et la façon dont il peut être traité avec l'utilisation de l'option de contrôle de la taille de la page). CreateFileMapping
fonction ).
La limitation à 2 Go signifie que randomNumbers
doit être inférieure à 2 Go. Comme les tableaux sont des classes et qu'ils ont eux-mêmes une certaine surcharge, cela signifie qu'un tableau de double
devra être inférieure à 2^31. Je ne suis pas sûr de combien plus petite que 2^31 la longueur devrait être, mais Surcharge 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 disposer de 2 Go d'espace d'adressage, mais lorsque vous créez et détruisez des objets, il y a des écarts entre les valeurs. Si ces espaces sont trop petits pour votre gros objet et qu'il est impossible de demander de l'espace supplémentaire, vous obtiendrez le message suivant System.OutOfMemoryException
. Par exemple, si vous créez 2 millions d'objets de 1024 octets, vous utilisez 1,9 Go. Si vous supprimez tous les objets dont l'adresse n'est pas un multiple de 3, vous utiliserez 0,6 Go de mémoire, mais celle-ci sera répartie dans l'espace d'adressage avec des blocs ouverts de 2024 octets entre les deux. Si vous deviez créer un objet de 0,2 Go, vous ne pourriez pas le faire parce qu'il n'y a pas de bloc assez grand pour l'accueillir et qu'il est impossible d'obtenir de l'espace supplémentaire (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/prévenir la fragmentation de la mémoire. Il convient de noter qu'à moins que vous ne développiez un gros programme qui utilise une grande quantité de mémoire, ce problème ne se posera pas. En outre, ce problème peut se poser sur les systèmes 64 bits, car Windows est principalement limité par la taille du fichier de page et la quantité de RAM sur le système.
É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 fichier, ils seront limités par la RAM du système et la taille du fichier de page. Comme indiqué dans le commentaire de Néstor Sánchez (Néstor Sánchez) sur le blog, avec un code géré comme C#, vous êtes limité par la RAM/le fichier de page et l'espace d'adressage du système d'exploitation.
C'était beaucoup plus long que prévu. J'espère que ça aidera quelqu'un. Je l'ai posté parce que j'ai rencontré le System.OutOfMemoryException
Exécution d'un programme x64 sur un système doté de 24 Go de RAM, alors que mon tableau ne contenait que 2 Go de matériel.
6 votes
Je vous recommande de réarchitecturer votre application afin de ne pas avoir à utiliser autant de mémoire. Que faites-vous pour avoir besoin de cent millions de chiffres en mémoire en même temps ?
2 votes
Vous n'avez pas désactivé votre pagefile ou quelque chose de stupide comme ça, n'est-ce pas ?
0 votes
@EricLippert, je rencontre ce problème en travaillant sur le problème P vs NP ( claymath.org/millenium-problems/p-vs-np-problem ). Avez-vous une suggestion pour réduire l'utilisation de la mémoire de travail (par exemple, en sérialisant et en stockant des blocs de données sur le disque dur, en utilisant le type de données C++, etc.)
0 votes
@bosit c'est un site de questions et réponses. Si vous avez une question technique spécifique sur le code actuel, posez-la en tant que question.
0 votes
@bostIT le lien pour le problème P vs NP dans votre commentaire n'est plus valide.
0 votes
Lien mis à jour : Problème P vs NP