Pregunta

Estoy haciendo ejercicios de algunos Proyecto Euler y me he topado con un escenario en el I he quieren matrices que son mayores que 2147483647 (el límite superior de int en C #).

Por supuesto estos son grandes conjuntos, pero, por ejemplo, no pueden hacer esto

// fails
bool[] BigArray = new BigArray[2147483648];

// also fails, cannot convert uint to int
ArrayList BigArrayList = new ArrayList(2147483648); 

Por lo tanto, puedo tener matrices más grandes?

EDIT: Era para una tamiz de Atkin , ya sabes, así que sólo quería uno realmente grande: D

¿Fue útil?

Solución

En cualquier momento se está trabajando con una variedad tan grande, que probablemente debería tratar de encontrar una mejor solución al problema. Pero eso se dice que voy a seguir intentando responder a su pregunta.

Como se ha mencionado en este artículo existe es un límite de 2 GB en cualquier objeto en .NET. Para todos x86, x64 e IA64.

  

Al igual que con operativo Windows de 32 bits   sistemas, hay un límite de 2 GB en el   tamaño de un objeto puede crear mientras   ejecutar una aplicación administrada de 64 bits   en un sistema operativo Windows de 64 bits.

Además, si se define una matriz demasiado grande en la pila, tendrá un desbordamiento de pila. Si se define la matriz en el montón, intentará asignar todo en un solo bloque continuo grande. Sería mejor utilizar un ArrayList que tiene la asignación dinámica implícita en el montón. Esto no le permitirá conseguir más allá de los 2 GB, pero es probable que pueda estar más cerca de él.

Creo que el límite de tamaño de la pila será más grande sólo si está utilizando un x 64 o la arquitectura IA64 y sistema operativo. El uso de x64 o IA64 que tendrá la memoria asignable de 64 bits en lugar de 32 bits.

Si usted no es capaz de asignar la lista de arreglo de una sola vez, es probable que pueda asignarlo en partes.

El uso de una lista de arreglo y la adición de 1 objeto a la vez en una máquina x64 de Windows 2008 con 6 GB de RAM, lo máximo que se puede conseguir el ArrayList de tamaño es: 134217728. Así que realmente creo que hay que encontrar una mejor solución para su problema que no utiliza tanta memoria. Tal vez escribir en un archivo en lugar de utilizar la memoria RAM.

Otros consejos

El límite de matriz se, que yo sepa, fijado como int32 incluso en 64 bits. Hay un límite en el tamaño máximo de un único objeto. Sin embargo, usted podría tener una agradable gran matriz escalonada con bastante facilidad.

Peor; porque las referencias son más grandes en x64, para las matrices de tipo ref que en realidad obtener menor en una sola matriz.

aquí :

  

He recibido una serie de consultas,   a por qué la versión de 64 bits de la 2,0   tiempo de ejecución .Net todavía tiene array máximo   tamaños limitado a 2 GB. Teniendo en cuenta que se   parece ser un tema candente en los últimos tiempos me   descubierto un poco de historia y una   discusión de las opciones para conseguir   esta limitación estaba en orden.

     

En primer lugar algunos antecedentes; en el 2,0   versión del tiempo de ejecución .Net (CLR) que   tomado una decisión consciente para el diseño   mantener el tamaño máximo permitido objeto   en el GC Montón a 2 GB, incluso en el   versión de 64 bits del tiempo de ejecución. Esto es   el mismo que el actual 1.1   implementación del CLR de 32 bits,   sin embargo, sería difícil para   En realidad gestionar asignar un 2 GB   objeto sobre el CLR de 32 bits porque el   espacio de direcciones virtuales es simplemente demasiado   fragmentada de encontrar una manera realista 2GB   agujero. En general, la gente no está   particularmente preocupados con la creación   tipos que serían> 2 GB cuando   instancia (o en cualquier lugar cerca),   sin embargo, desde las matrices son sólo una   tipo especial de tipo administrado que son   creado dentro del montón administrado se   también sufren de esta limitación.


Cabe señalar que en .NET 4.5 el tamaño de la memoria límite se elimina opcionalmente por el gcAllowVeryLargeObjects bandera, sin embargo, esto no cambia el máximo dimensión tamaño. El punto clave es que si usted tiene matrices de un tipo personalizado, o matrices multidimensionales, entonces ahora se puede ir más allá de 2 GB de tamaño de memoria.

No es necesario un conjunto tan grande en absoluto.

Cuando el método se encuentra con problemas de recursos, no sólo buscar la forma de ampliar los recursos, mirar el método también. :)

Esta es una clase que utiliza un buffer de 3 MB para calcular números primos utilizando el criba de Eratóstenes. La clase mantiene un registro de los números primos hasta qué punto se han calculado, y cuando el rango debe ser ampliado crea un buffer para probar otros 3 millones de números.

Mantiene los números primos que se encuentran en una lista, y cuando se expande el rango de los números primos Previos se utilizan para descartar los números en la memoria intermedia.

he hecho algunas pruebas, y un tampón alrededor de 3 MB es más eficiente.

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;
   }

}

Creo que incluso dentro de un CLR de 64 bits, hay un límite de 2 GB (o, posiblemente, 1 GB - No puedo recordar exactamente) por objeto. Que impediría la creación de un conjunto más amplio. El hecho de que sólo toma Array.CreateInstance argumentos Int32 para tamaños sugiere también.

En una nota más amplia, sospecho que si necesita arreglos tan grande que realmente debe cambiar la forma en que está enfocando el problema.

Estoy en gran medida un novato con C # (es decir, el aprendizaje durante esta semana), así que no estoy seguro de los detalles exactos de cómo se implementa ArrayList. Sin embargo, yo supongo que como no se ha definido un tipo para el ejemplo ArrayList, entonces la matriz sería asignado como una serie de referencias a objetos. Esto bien podría significar que en realidad se está asignando 4-8GB de memoria dependiendo de la arquitectura.

Según MSDN , el índice de matriz de bytes no puede ser mayor que 2147483591. para .NET antes de 4.5 era también un límite de memoria para una matriz. En .NET 4.5 de este máximo es el mismo, pero para otros tipos que puede ser de hasta 2146435071.

Este es el código para la ilustración:

    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;
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top