我有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)

这是我所发现的:

运行./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?我缺少明显的东西吗?

    最佳答案

    当前,在Windows上,GHC是32位GHC-我认为Windows 7.6应当可以使用Windows的64位GHC。

    其结果之一是,在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

    那解释了



    因为decodeSize()4G解码为2^32

    升级GHC后,此限制也将保留,直到最终发布适用于Windows的64位GHC。

    作为32位进程,用户模式虚拟地址空间被限制为2或4 GB(取决于IMAGE_FILE_LARGE_ADDRESS_AWARE标志的状态),请参见Memory limits for Windows Releases

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

    在我的64位linux上运行该程序,输入21000000(以弥补Int和指针的两倍大),我得到了

    $ ./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,您的进程被限制为2GB的地址空间,而4,200万个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)
    

    因此,如果您指定的最大堆大小低于2GB(但足以容纳Set),则应该可以使用。

    10-05 22:26
    查看更多