Использование всей доступной оперативной памяти в программе Haskell?


У меня 8 ГБ оперативной памяти, но программы Haskell, по-видимому, могут использовать только 1,3 ГБ.

Я использую эту простую программу, чтобы определить, сколько памяти может выделить программа GHC:
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)

Вот что я нахожу:

  • запуск ./mem.exe 40000000 +RTS -s выполняется успешно и сообщает 1113 MB total memory in use
  • запуск ./mem.exe 42000000 +RTS -s завершается неудачей с out of memory error
  • запуск ./mem.exe 42000000 +RTS -s -M4G ошибок с -M4G: size outside allowed range
  • выполняется ./mem.exe 42000000 +RTS -s -M3.9G выдает out of memory error

Мониторинг процесса с помощью Диспетчера задач Windows показывает, что максимальное использование памяти составляет около 1,2 ГБ.

Моя система: Win7, 8 ГБ оперативной памяти, платформа Haskell 2011.04.0.0, ghc 7.0.4.

Я компилирую с: ghc -O2 mem.hs -rtsopts

Как я могу использовать всю мою доступную оперативную память? Я упускаю что-то очевидное?

2 8

2 ответа:

В настоящее время в Windows GHC является 32-разрядным GHC - я думаю, что 64-разрядный GHC для windows должен быть доступен, когда появится 7.6.

Одним из следствий этого является то, что в Windows вы не можете использовать больше 4G - 1BLOCK памяти, так как максимально допустимым параметром размера является HS_WORD_MAX:

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

С 32-битными словами, HS_WORD_MAX = 2^32-1.

Это объясняет

Бег ./память.exe 42000000 +RTS-s-M4G ошибки out with-M4G: размер вне допустимого диапазона

С тех пор decodeSize() декодирует 4G как 2^32.

Это ограничение сохранится и после обновления вашего GHC, пока, наконец, не будет выпущен 64-битный GHC для Windows.

Как 32-разрядный процесс, виртуальное адресное пространство пользовательского режима ограничено 2 или 4 ГБ (в зависимости от состояния флага IMAGE_FILE_LARGE_ADDRESS_AWARE), CFограничения памяти для выпусков Windows .

Теперь вы пытаетесь построить Set, содержащий 42 миллиона 4-байтовых Ints. a Data.Set.Set имеет пять слов накладных расходов на элемент (конструктор, размер, указатель на левое и правое поддерево, указатель на элемент), поэтому Set займет около 0,94 гигабайта памяти (1,008 "метрического" ГБ). Но процесс использует примерно в два раза больше или больше (ему нужно пространство для сборки мусора, по крайней мере, размер живой кучи).

Запустив программу на моем 64-битном linux, с вводом 21000000 (чтобы компенсировать вдвое большие Ints и указатели), я получаю

$ ./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

Но top сообщает только 1.1g Об использовании памяти - top, и предположительно Диспетчер задач, сообщает только живая куча.

Таким образом, кажется, что IMAGE_FILE_LARGE_ADDRESS_AWARE Не задано, ваш процесс ограничен адресным пространством 2 ГБ, и 42 миллиона Set требуется больше, чем это - если вы не укажете Максимальный или предполагаемый размер кучи, который меньше:

$ ./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

Устанавливая максимальный размер кучи ниже того, что он использовал бы естественно, фактически позволяет ему поместиться едва ли больше, чем пространство, необходимое для Set, ценой немного большего времени GC и предлагая размер кучи -H1800M позволяет ему закончить использование только

1831 MB total memory in use (0 MB lost due to fragmentation)
Поэтому, если вы зададите максимальный размер кучи ниже 2 ГБ (но достаточно большой, чтобы Set поместился), это должно сработать.

Размер кучи по умолчаниюне ограничен .

Используя GHC 7.2 на 64-битной машине Windows XP, я могу выделить более высокие значения, установив размер кучи больше, явно:

$ ./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)

И

$ ./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)

Даже:

$ ./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)

То есть, я могу выделить до предела процесса Windows XP 2G. Я думаю, что на Win 7 у вас не будет такого низкого лимита-эта таблица предполагает либо 4G, либо 192G - просто попросите столько, сколько вам нужно (и используйте более свежий GHC).