我正在尝试使用概要分析来查看我的代码的哪一部分对最大3GB内存的使用负责(如gc()
统计的最大已使用内存see here how所述)。我正在像这样运行内存分析:
Rprof(line.profiling = TRUE, memory.profiling = TRUE)
graf(...) # ... here I run the profiled code
Rprof(NULL)
summaryRprof(lines = "both", memory = "both")
输出如下:
$by.total
total.time total.pct mem.total self.time self.pct
"graf" 299.12 99.69 50814.4 0.02 0.01
#2 299.12 99.69 50814.4 0.00 0.00
"graf.fit.laplace" 299.06 99.67 50787.2 0.00 0.00
"doTryCatch" 103.42 34.47 4339.2 0.00 0.00
"chol" 103.42 34.47 4339.2 0.00 0.00
"tryCatch" 103.42 34.47 4339.2 0.00 0.00
"tryCatchList" 103.42 34.47 4339.2 0.00 0.00
"tryCatchOne" 103.42 34.47 4339.2 0.00 0.00
"chol.default" 101.62 33.87 1087.0 101.62 33.87
graf.fit.laplace.R#46 85.80 28.60 3633.2 0.00 0.00
"backsolve" 78.82 26.27 1635.2 58.40 19.46
我应该如何解释mem.total
?它是什么,单位是什么?我试图查看文档?Rprof
和?summaryRprof
,但似乎文档记录不完善:-/
编辑: Here,他们说Rprof“以固定的时间间隔探测R的总内存使用量”。但这不适合50GB,超出了我的存储能力! (现在为8GB物理+ 12 GB页面文件)。
类似地,正如R.尤达(R Yoda)指出的那样,?summaryRprof
说,如果memory =“ both”,则表示“总内存的变化”。但是究竟是什么(是总内存还是总内存的变化),以及它与50GB的数字如何匹配?
编辑:在profvis
中所做的相同分析-当我将鼠标悬停在50812上方时,它显示“内存分配(MB)”,并悬停在垂直于该垂直方向的黑条上行“峰值内存分配和释放的百分比”。不知道那意味着什么……这大约是50 GB,这意味着也许这可能是所有分配的总和(??)...绝对不是峰值内存使用情况:
答案 0 :(得分:1)
?summaryRprof
说:
如果memory =“ both”和“ both”相同,则除了计时以外,还有Mb的内存消耗。
因此mem.total
以MB为单位
当memory =“ both”和“ both”时,报告总内存的变化(截断为零)[...]
您有8 GB的RAM + 12 GB的交换空间,但是mem.total
声称您已使用50 GB?
因为它是两个后续探测之间的合计增量(Rprof
定期拍摄的内存使用情况快照:如果在执行函数f的同时执行了探测最后一个探测的使用量变化量已添加到f)的mem.total
中。
内存使用量增量可能是负的,但我从未见过负的mem.total
值,所以我猜(!)仅将正值添加到mem.total
中。
这将解释您所看到的50 GB的总使用量:这不是单个时间点上分配的内存量,而是整个执行时间内的聚合内存增量。
这也说明了一个事实,gc
仅显示3 GB为“已用最大(Mb)” :内存已分配和释放/重新分配了很多次,因此您无法运行这会占用大量的时间,但要花大量时间(在RAM中移动大量数据会使所有缓存失效,因此速度很慢),这是CPU应用的计算逻辑的基础。
此摘要(IMHO)似乎也掩盖了一个事实,即垃圾收集器(gc)在不确定的时间点启动,以清理释放的内存。
由于gc开始启动(不确定),因此恕我直言,将负内存增量归因于刚刚探查的单个函数是不公平的。
我会将mem.total
解释为mem.total.used.during.runtime
,这可能是该列的更好标签。
profvis
有更详细的内存使用情况摘要(如您在问题中的屏幕快照中所示):它还汇总了负的内存使用情况变化量(释放的内存),但是profvis documentation也警告关于缺点:
代码面板还显示内存分配和释放。 解释此信息可能会有些棘手,因为它确实 不一定反映在那一行分配和释放的内存 代码。采样探查器记录有关内存的信息 前一个样本与当前样本之间发生的分配 一。这意味着该行上的分配/取消分配值 可能实际上是在前一行代码中发生的。
更详细的答案将需要更多的研究时间(我没有)
-了解C和R源
-根据summaryRprof
创建的数据文件来了解(复制)Rprof
的聚合逻辑
Rprof
数据文件(Rprof.out
)看起来像这样:
:376447:6176258:30587312:152:1#2 "test" 1#1 "test2"
前四个数字(用冒号分隔)表示平均值(请参见?summaryRprof
)
-R_SmallVallocSize:R堆上小块中的向量内存[桶数]
-R_LargeVallocSize:大块中的向量内存[存储桶数](来自malloc)
-R堆上节点中的内存
-在该时间间隔内对内部函数duplicate
的调用次数(用于复制向量,例如,在函数参数的“首次写入时复制”的情况下)
字符串是函数调用堆栈。
只有前两个数字与计算MB的当前(向量)内存使用量有关:
TotalBuckets = R_SmallVallocSize + R_LargeVallocSize
mem.used = TotalBuckets * 8 Bytes / 1024 / 1024
# 50 MB in the above `Rprof` probe line:
# (376447 + 6176258) * 8 / 1024 / 1024
有关Vcells
的详细信息,请参见?Memory
。
顺便说一句:我想尝试summaryRProf(memory = "stats", diff = F)
以获得当前的内存摘要,但是在Ubuntu上收到R3.4.4 64位错误消息:
Error in tapply(seq_len(1L), list(index = c("1::#File", "\"test2\":1#1", :
arguments must have same length
您能重现吗(看起来像“统计数据”坏了)?