2012-05-24 13 views
8

Tengo 8 GB de RAM, pero los programas Haskell aparentemente solo pueden usar 1.3 GB.haciendo uso de toda la memoria RAM disponible en un programa Haskell?

estoy usando este programa simple para determinar la cantidad de memoria un programa GHC puede asignar:

import System.Environment 
import Data.Set as Set 

main = do 
     args <- getArgs 
     let n = (read $ args !! 0) :: Int 
      s = Set.fromList [0..n] 
     do 
      putStrLn $ "min: " ++ (show $ findMin s) 
      putStrLn $ "max: " ++ (show $ findMax s) 

Esto es lo que estoy encontrando:

  • corriendo ./mem.exe 40000000 +RTS -s tiene éxito y los informes 1113 MB total memory in use
  • ejecución ./mem.exe 42000000 +RTS -s falla con out of memory error
  • ejecución ./mem.exe 42000000 +RTS -s -M4G errores hacia fuera con -M4G: size outside allowed range
  • corriendo ./mem.exe 42000000 +RTS -s -M3.9G falla con out of memory error

Seguimiento del proceso a través del Administrador de tareas de Windows muestra que el uso de memoria máxima es de alrededor de 1,2 GB.

Mi sistema: Win7, 8 GB de RAM, Haskell Platform 2011.04.0.0, ghc 7.0.4.

Estoy compilando con: ghc -O2 mem.hs -rtsopts

¿Cómo puedo hacer uso de toda mi RAM disponible? ¿Me estoy perdiendo algo obvio?

+2

Actualiza a una versión más reciente de GHC. ¿Tiene un límite de proceso máximo establecido en su máquina de Windows? GHC no tiene límites de almacenamiento dinámico, por lo que es probable que el sistema operativo limite el espacio de direcciones de su proceso. –

+0

Si no desea abandonar la zona de comodidad de utilizar la plataforma Haskell, tenga en cuenta que la próxima versión se lanzará este mes; La última vez que lo revisé iba a incluir GHC 7.4.1. – dave4420

Respuesta

8

Actualmente, en Windows, GHC es un GHC de 32 bits; creo que se supone que un GHC de 64 bits para Windows estará disponible cuando llegue 7.6.

Una consecuencia de ello es que en Windows, no se puede utilizar más de 4G - 1BLOCK de la memoria, ya que el máximo permitido como un parámetro de tamaño es HS_WORD_MAX:

decodeSize(rts_argv[arg], 2, BLOCK_SIZE, HS_WORD_MAX)/BLOCK_SIZE; 

con palabras de 32 bits, HS_WORD_MAX = 2^32-1 .

que explica

corriendo ./mem.exe 42000000 + RTS -s errores -M4G a cabo con -M4G: tamaño fuera del rango permitido

desde decodeSize() decodifica 4G como 2^32.

Esta limitación se mantendrá también después de actualizar su GHC, hasta que finalmente se libere un GHC de 64 bits para Windows.

Como un proceso de 32 bits, el espacio de direcciones virtuales en modo de usuario está limitado a 2 o 4 GB (según el estado de la bandera IMAGE_FILE_LARGE_ADDRESS_AWARE), cf Memory limits for Windows Releases.

Ahora, intenta construir un Set que contiene 42 millones de 0 bytes Int s. Un Data.Set.Set tiene cinco palabras de sobrecarga por elemento (constructor, tamaño, puntero del subárbol izquierdo y derecho, puntero al elemento), por lo que el Set ocupará aproximadamente 0,94 GiB de memoria (1,008 'métrico' GB). Pero el proceso utiliza aproximadamente el doble o más (necesita espacio para la recolección de basura, al menos el tamaño del montón dinámico).

Ejecutar el programa en mi Linux de 64 bits, con entrada de 21 millones (para compensar el doble de grande Int s y punteros), consigo

$ ./mem +RTS -s -RTS 21000000 
min: 0 
max: 21000000 
    31,330,814,200 bytes allocated in the heap 
    4,708,535,032 bytes copied during GC 
    1,157,426,280 bytes maximum residency (12 sample(s)) 
     13,669,312 bytes maximum slop 
      2261 MB total memory in use (0 MB lost due to fragmentation) 

            Tot time (elapsed) Avg pause Max pause 
    Gen 0  59971 colls,  0 par 2.73s 2.73s  0.0000s 0.0003s 
    Gen 1  12 colls,  0 par 3.31s 10.38s  0.8654s 8.8131s 

    INIT time 0.00s ( 0.00s elapsed) 
    MUT  time 12.12s (13.33s elapsed) 
    GC  time 6.03s (13.12s elapsed) 
    EXIT time 0.00s ( 0.00s elapsed) 
    Total time 18.15s (26.45s elapsed) 

    %GC  time  33.2% (49.6% elapsed) 

    Alloc rate 2,584,429,494 bytes per MUT second 

    Productivity 66.8% of total user, 45.8% of total elapsed 

pero top informes solamente 1.1g de la memoria use - top, y presumiblemente el Administrador de tareas, informa solo el montón en vivo.

por lo que parece IMAGE_FILE_LARGE_ADDRESS_AWARE no está definida, el proceso está limitado a un espacio de direcciones de 2 GB, y los 42 millones de Set necesita más que eso - a menos que especifique un tamaño máximo de almacenamiento dinámico o sugerido que es más pequeño:

$ ./mem +RTS -s -M1800M -RTS 21000000 
min: 0 
max: 21000000 
    31,330,814,200 bytes allocated in the heap 
    3,551,201,872 bytes copied during GC 
    1,157,426,280 bytes maximum residency (12 sample(s)) 
     13,669,312 bytes maximum slop 
      1154 MB total memory in use (0 MB lost due to fragmentation) 

            Tot time (elapsed) Avg pause Max pause 
    Gen 0  59971 colls,  0 par 2.70s 2.70s  0.0000s 0.0002s 
    Gen 1  12 colls,  0 par 4.23s 4.85s  0.4043s 3.3144s 

    INIT time 0.00s ( 0.00s elapsed) 
    MUT  time 11.99s (12.00s elapsed) 
    GC  time 6.93s ( 7.55s elapsed) 
    EXIT time 0.00s ( 0.00s elapsed) 
    Total time 18.93s (19.56s elapsed) 

    %GC  time  36.6% (38.6% elapsed) 

    Alloc rate 2,611,793,025 bytes per MUT second 

    Productivity 63.4% of total user, 61.3% of total elapsed 

Al establecer el tamaño de pila máximo por debajo de lo que usaría naturalmente, deja que quepa en poco más que el espacio necesario para Set, al precio de un tiempo de GC un poco más largo, y sugiere un tamaño de montón de -H1800M para finalizar utilizando solo

1831 MB total memory in use (0 MB lost due to fragmentation) 

Por lo tanto, si especifica un tamaño de almacenamiento dinámico máximo inferior a 2 GB (pero lo suficientemente grande como para que quepa el Set), debería funcionar.

+0

gracias por su análisis – ErikR

+0

¿Y funciona con '-M1800M'? –

+0

Sí, funciona con '-M1800M' – ErikR

4

El default heap size is unlimited.

Usando GHC 7.2 en una máquina de 64 bits de Windows XP, I pueden asignar valores más altos, ajustando el tamaño de la pila más grande, de forma explícita:

$ ./A 42000000 +RTS -s -H1.6G 
min: 0 
max: 42000000 
    32,590,763,756 bytes allocated in the heap 
    3,347,044,008 bytes copied during GC 
    714,186,476 bytes maximum residency (4 sample(s)) 
     3,285,676 bytes maximum slop 
      1651 MB total memory in use (0 MB lost due to fragmentation) 

y

$ ./A 42000000 +RTS -s -H1.7G 
min: 0 
max: 42000000 
    32,590,763,756 bytes allocated in the heap 
    3,399,477,240 bytes copied during GC 
    757,603,572 bytes maximum residency (4 sample(s)) 
     3,281,580 bytes maximum slop 
      1754 MB total memory in use (0 MB lost due to fragmentation) 

incluso:

$ ./A 42000000 +RTS -s -H1.85G 
min: 0 
max: 42000000 
    32,590,763,784 bytes allocated in the heap 
    3,492,115,128 bytes copied during GC 
    821,240,344 bytes maximum residency (4 sample(s)) 
     3,285,676 bytes maximum slop 
      1909 MB total memory in use (0 MB lost due to fragmentation) 

Es decir, puedo asignar hasta Windows XP 2G process limit. Me imagino que en Win 7 no tendrá un límite tan bajo - esta tabla suggests either 4G or 192G - solo solicite todo lo que necesite (y use un GHC más reciente).

Cuestiones relacionadas