Pregunta

Antecedentes: estoy escribiendo un programa C ++ que funciona con grandes cantidades de geodatos, y deseo cargar fragmentos grandes para procesarlos de una sola vez. Estoy obligado a trabajar con una aplicación compilada para máquinas de 32 bits. La máquina en la que estoy probando ejecuta un sistema operativo de 64 bits (Windows 7) y tiene 6 gig de ram. Usando MS VS 2008.

Tengo el siguiente código:

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

Esperaba poder asignar memoria hasta que la aplicación alcanzara el límite de 4 gigabytes de direccionamiento de 32 bits. Sin embargo, cuando nBandBytes es 466,560,000, los nuevos lanzamientos std :: bad_alloc en el segundo intento. En esta etapa, el valor del conjunto de trabajo (memoria) para el proceso es 665,232 K Por lo tanto, parece que no soy capaz de asignar ni siquiera un concierto de memoria.

Se ha mencionado un límite de 2 gig para aplicaciones en Windows de 32 bits que se puede extender a 3 gig con el modificador / 3GB para win32. Este es un buen consejo en ese entorno, pero no es relevante para este caso.

¿Cuánta memoria debería poder asignar bajo el sistema operativo de 64 bits con una aplicación de 32 bits?

¿Fue útil?

Solución

Tanto como el sistema operativo quiere darte. De forma predeterminada, Windows permite que un proceso de 32 bits tenga 2 GB de espacio de direcciones. Y esto se divide en varios trozos. Se reserva un área para la pila, otras para cada ejecutable y dll que se carga. Lo que queda puede asignarse dinámicamente, pero no hay garantía de que sea una gran porción contigua. Pueden ser varios fragmentos más pequeños de un par de cientos de MB cada uno.

Si compila con el indicador LargeAddressAware, Windows de 64 bits le permitirá usar el espacio completo de direcciones de 4 GB, lo que debería ayudar un poco, pero en general,

  • no debe suponer que la memoria disponible es contigua. Debería poder trabajar con varias asignaciones más pequeñas en lugar de algunas grandes, y
  • Debe compilarlo como una aplicación de 64 bits si necesita mucha memoria.

Otros consejos

en Windows 32 bit, el proceso normal puede tomar 2 GB como máximo, pero con / 3GB puede alcanzar hasta 3 GB (para Windows 2003).

pero en su caso, creo que está asignando memoria contigua, por lo que se produjo la excepción.

Puede asignar tanta memoria como le permita su archivo de página; incluso sin el modificador / 3GB, puede asignar 4 GB de memoria sin mucha dificultad.

Leer este artículo para obtener una buena visión general sobre cómo pensar en la memoria física, la memoria virtual y el espacio de direcciones (las tres son cosas diferentes). En pocas palabras, tiene exactamente la misma memoria física que RAM, pero su aplicación realmente no tiene interacción con esa memoria física, es solo un lugar conveniente para almacenar los datos que se encuentran en su memoria virtual. Su memoria virtual está limitada por el tamaño de su archivo de paginación, y la cantidad que su aplicación puede usar está limitada por la cantidad que otras aplicaciones están usando (aunque puede asignar más, siempre que realmente no la use). Su espacio de direcciones en el mundo de 32 bits es de 4 GB. De ellos, 2 GB se asignan al núcleo (o 1 GB si usa el modificador / 3BG). De los 2 GB que quedan, algunos serán utilizados por su pila, otros por el programa que está ejecutando actualmente (y todos los dlls, etc.). Se va a fragmentar, y solo podrá obtener tanto espacio contiguo: aquí es donde falla su asignación. Pero dado que ese espacio de direcciones es solo una forma conveniente de acceder a la memoria virtual que ha asignado para usted, es posible asignar mucha más memoria y traer trozos de ella a su espacio de direcciones de a poco.

Raymond Chen tiene un ejemplo de cómo para asignar 4 GB de memoria y asignar parte de ella en una sección de su espacio de direcciones.

En Windows de 32 bits, la asignación máxima es de 16 TB y 256 TB en Windows de 64 bits.

Y si realmente le gusta cómo funciona la administración de memoria en Windows, lea este artículo .

Durante el proyecto ElephantsDream, la Fundación Blender con Blender 3D tuvo problemas similares (aunque en Mac). No se puede incluir el enlace, pero google: problema de asignación de memoria blender3d y será el primer elemento.

La solución implicó la asignación de archivos. No lo he probado, pero puede leerlo aquí: http://msdn.microsoft.com/en-us/library/aa366556 (VS.85) .aspx

Con nBandBytes en 466,560,000, está intentando asignar 1.4 GB. Una aplicación de 32 bits generalmente solo tiene acceso a 2 GB de memoria (más si arranca con / 3GB y el archivo ejecutable está marcado como espacio de direcciones grande). Es posible que le resulte difícil encontrar tantos bloques de espacio de direcciones contiguas para sus grandes fragmentos de memoria.

Si desea asignar gigabytes de memoria en un sistema operativo de 64 bits, utilice un proceso de 64 bits.

Debería poder asignar un total de aproximadamente 2 GB por proceso. Este artículo (PDF) explica los detalles. Sin embargo, es probable que no pueda obtener un solo bloque contiguo que esté incluso cerca de ese tamaño.

Incluso si asigna en fragmentos más pequeños, no podría obtener la memoria que necesita, especialmente si el programa circundante tiene un comportamiento de memoria impredecible, o si necesita ejecutarse en diferentes sistemas operativos. En mi experiencia, el espacio de almacenamiento dinámico en un proceso de 32 bits limita a alrededor de 1,2 GB.

Con esta cantidad de memoria, recomendaría escribir manualmente en el disco. Envuelva sus matrices en una clase que gestione la memoria y escriba en archivos temporales cuando sea necesario. Afortunadamente, las características de su programa son tales que podría almacenar en caché partes de esos datos sin golpear demasiado el disco.

Sysinternals VMMap es ideal para investigar la fragmentación del espacio de direcciones virtuales, lo cual probablemente limita la cantidad de memoria contigua que puede asignar. Recomiendo configurarlo para que muestre el espacio libre, luego ordenar por tamaño para encontrar las áreas libres más grandes, luego ordenar por dirección para ver qué separa las áreas libres más grandes (probablemente DLL reorganizadas, regiones de memoria compartida u otros montones).

Evitar asignaciones contiguas extremadamente grandes es probablemente lo mejor, como han sugerido otros.

La configuración de LARGE_ADDRESS_AWARE = ??YES (como se sugiere jalf) es buena, siempre y cuando las bibliotecas de las que depende su aplicación sean compatibles. Si lo hace, debe probar su código con el < code> AllocationPreference clave de registro establecida para permitir la asignación de direcciones virtuales de arriba hacia abajo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top