Était-ce utile?

La solution

Chaque fois que vous travaillez avec un tableau ce grand, vous devriez probablement essayer de trouver une meilleure solution au problème. Mais cela étant dit, je vais encore tenter de répondre à votre question.

Comme mentionné dans cette article il est une limite de 2 Go sur un objet dans .NET. Pour tous x86, x64 et IA64.

  

Comme 32 bits d'exploitation Windows   systèmes, il y a une limite de 2 Go sur la   la taille d'un objet que vous pouvez créer en   l'exécution d'une application gérée 64 bits   sur un système d'exploitation Windows 64 bits.

Aussi, si vous définissez un tableau trop grand sur la pile, vous aurez un débordement de pile. Si vous définissez le tableau sur le tas, il essaiera d'allouer tout dans un grand bloc continu. Il serait préférable d'utiliser une ArrayList qui a l'allocation dynamique implicite sur le tas. Cela ne vous permettra pas de dépasser les 2 Go, mais vous permettra sans doute de se rapprocher de lui.

Je pense que la limite de taille de la pile sera plus grand que si vous utilisez un x64 ou de l'architecture IA64 et système d'exploitation. L'utilisation x64 ou IA64 vous aurez la mémoire allouable 64 bits au lieu de 32 bits.

Si vous n'êtes pas en mesure d'allouer la liste de tableau à la fois, vous pouvez probablement l'affecter dans certaines régions.

Utilisation d'une liste de tableau et en ajoutant 1 objet à la fois sur une machine Windows x64 2008 avec 6 Go de RAM, le plus que je peux obtenir le ArrayList est de taille: 134217728. Je pense vraiment que vous devez trouver une meilleure solution pour votre problème ne pas utiliser autant de mémoire. Peut-être écrire dans un fichier au lieu d'utiliser la RAM.

Autres conseils

La limite de tableau est, autant que je sache, fixé comme int32 même sur 64 bits. Il y a un plafond sur la taille maximale d'un seul objet. Cependant, vous pourriez avoir une belle grande gamme en dents de scie assez facilement.

Pire encore; parce que les références sont plus grandes en x64, pour les tableaux de type ref vous obtenez en fait moins dans un seul tableau.

Voir :

  

J'ai reçu un certain nombre de questions que   pourquoi la version 64 bits du 2.0   runtime .Net a encore un maximum de tableau   tailles limitées à 2 Go. Étant donné que   semble être un sujet de fin I   un peu de fond compris et   discussion des options pour obtenir   cette limitation était en ordre.

     

Tout d'abord quelques arrière-plan; dans le 2,0   version du moteur d'exécution .Net (CLR) nous   pris une décision de conception consciente de   maintenir la taille de l'objet maximum autorisé   dans le GC Heap à 2 Go, même sur la   version 64 bits de l'exécution. C'est   le même que le courant 1.1   la mise en œuvre du CLR 32 bits,   mais vous serait difficile à   gérer effectivement d'allouer un 2 Go   objet sur le CLR 32 bits car la   l'espace d'adressage virtuel est tout simplement trop   fragmenté pour trouver une façon réaliste de 2 Go   trou. Généralement, les gens ne sont pas   particulièrement préoccupé par la création   types qui seraient> 2 Go lorsque   instancié (ou ailleurs à proximité),   cependant, puisque les tableaux ne sont que   type particulier de type managé qui sont   créé au sein du tas managé ils   souffrent également de cette limitation.


Il convient de noter que dans .NET 4.5 taille de la mémoire limite est éventuellement retiré par le gcAllowVeryLargeObjects drapeau, cependant, cela ne change pas le maximum dimension taille. Le point clé est que si vous avez des tableaux d'un type personnalisé, ou des tableaux multidimensionnels, vous pouvez maintenant aller au-delà de 2 Go en taille de la mémoire.

Vous n'avez pas besoin d'un tableau que tout grand.

Lorsque votre méthode se heurte à des problèmes de ressources, ne regardez pas seulement à la façon d'accroître les ressources, regardez la méthode aussi. :)

Voici une classe qui utilise un tampon de 3 Mo pour calculer les nombres premiers en utilisant le tamis d'Eratosthène. La classe conserve la trace de la distance que vous avez calculé les nombres premiers, et lorsque la plage doit être élargi, il crée un tampon pour tester un autre 3 millions de numéros.

Il maintient les nombres premiers trouvés dans une liste, et lorsque la plage est étendu les nombres premiers previos sont utilisés pour écarter des numéros dans la mémoire tampon.

Je fait quelques tests, et un tampon d'environ 3 Mo est la plus efficace.

public class Primes {

   private const int _blockSize = 3000000;

   private List<long> _primes;
   private long _next;

   public Primes() {
      _primes = new List<long>() { 2, 3, 5, 7, 11, 13, 17, 19 };
      _next = 23;
   }

   private void Expand() {
      bool[] sieve = new bool[_blockSize];
      foreach (long prime in _primes) {
         for (long i = ((_next + prime - 1L) / prime) * prime - _next;
            i < _blockSize; i += prime) {
            sieve[i] = true;
         }
      }
      for (int i = 0; i < _blockSize; i++) {
         if (!sieve[i]) {
            _primes.Add(_next);
            for (long j = i + _next; j < _blockSize; j += _next) {
               sieve[j] = true;
            }
         }
         _next++;
      }
   }

   public long this[int index] {
      get {
         if (index < 0) throw new IndexOutOfRangeException();
         while (index >= _primes.Count) {
            Expand();
         }
         return _primes[index];
      }
   }

   public bool IsPrime(long number) {
      while (_primes[_primes.Count - 1] < number) {
         Expand();
      }
      return _primes.BinarySearch(number) >= 0;
   }

}

Je crois que même dans un CLR 64 bits, il y a une limite de 2 Go (1 Go ou peut-être - je ne me souviens pas exactement) par objet. Cela vous empêcher de créer un ensemble plus grand. Le fait que Array.CreateInstance ne prend arguments Int32 pour les tailles suggère aussi.

Sur une note plus générale, je pense que si vous avez besoin que des tableaux grand, vous devriez vraiment changer la façon dont vous vous approchez le problème.

Je suis très bien un débutant avec C # (à savoir l'apprendre cette semaine), donc je ne suis pas sûr des détails exacts de la façon dont ArrayList est mis en œuvre. Cependant, je suppose que vous n'avez pas défini un type pour l'exemple ArrayList, alors le tableau serait réparti comme un tableau de références d'objets. Cela pourrait signifier que vous allouez effectivement 4-8Gb de la mémoire en fonction de l'architecture.

Selon MSDN , l'index de tableau d'octets ne peut pas être supérieure à 2147483591. pour .NET avant 4.5, il était aussi une limite de mémoire pour un tableau. Dans .NET 4.5 ce maximum est le même, mais pour d'autres types, il peut être jusqu'à 2.146.435.071.

Voici le code d'illustration:

    static void Main(string[] args)
    {
        // -----------------------------------------------
        // Pre .NET 4.5 or gcAllowVeryLargeObjects unset
        const int twoGig = 2147483591; // magic number from .NET

        var type = typeof(int);          // type to use
        var size = Marshal.SizeOf(type); // type size
        var num = twoGig / size;         // max element count

        var arr20 = Array.CreateInstance(type, num);
        var arr21 = new byte[num];

        // -----------------------------------------------
        // .NET 4.5 with x64 and gcAllowVeryLargeObjects set
        var arr451 = new byte[2147483591];
        var arr452 = Array.CreateInstance(typeof(int), 2146435071);
        var arr453 = new byte[2146435071]; // another magic number

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