利用Haskell程序中的所有可用RAM?

Eri*_*ikR 8 windows haskell memory-management heap-memory ghc

我有8 GB的RAM,但Haskell程序似乎只能使用1.3 GB.

我正在使用这个简单的程序来确定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)
Run Code Online (Sandbox Code Playgroud)

这是我发现的:

  • 运行./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 GB.

我的系统:Win7,8 GB RAM,Haskell平台2011.04.0.0,ghc 7.0.4.

我正在编译: ghc -O2 mem.hs -rtsopts

如何使用我所有可用的RAM?我错过了一些明显的东西吗

Dan*_*her 8

目前,在Windows上,GHC是32位GHC - 我认为当7.6到来时,Windows的64位GHC应该是可用的.

这样做的一个结果是,在Windows上,您不能使用超过4G - 1BLOCK内存,因为作为size-parameter允许的最大值是HS_WORD_MAX:

decodeSize(rts_argv[arg], 2, BLOCK_SIZE, HS_WORD_MAX) / BLOCK_SIZE;
Run Code Online (Sandbox Code Playgroud)

使用32位字,HS_WORD_MAX = 2^32-1.

这解释了

使用-M4G运行./mem.exe 42000000 + RTS -s -M4G错误:大小超出允许范围

因为decodeSize()解码4G2^32.

升级GHC后,此限制也将保留,直到最终发布64位GHC for Windows.

作为32位进程,用户模式虚拟地址空间限制为2或4 GB(取决于IMAGE_FILE_LARGE_ADDRESS_AWARE标志的状态),参见Windows发行版的内存限制.

现在,您正在尝试构建一个Set包含4200万个4字节的Ints.A Data.Set.Set每个元素有五个字的开销(构造函数,大小,左右子树指针,元素指针),因此Set将占用大约0.94 GiB的内存(1.008'公制'GB).但是该进程使用大约两倍或更多(它需要空间用于垃圾收集,至少是活动堆的大小).

在我的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
Run Code Online (Sandbox Code Playgroud)

top仅报告1.1g内存使用 - top可能是任务管理器,仅报告实时堆.

所以似乎IMAGE_FILE_LARGE_ADDRESS_AWARE没有设置,你的进程仅限于2GB的地址空间,而4200万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
Run Code Online (Sandbox Code Playgroud)

将最大堆大小设置为低于它自然使用的大小,实际上让它适合于所需的空间Set,以较长的GC时间为代价,并建议堆大小-H1800M让它完成仅使用

1831 MB total memory in use (0 MB lost due to fragmentation)
Run Code Online (Sandbox Code Playgroud)

因此,如果您指定最大堆大小低于2GB(但足够大Set以适合),它应该工作.