繁体   English   中英

R和并行内存为parallel :: mclapply

[英]R and shared memory for parallel::mclapply

我试图通过并行执行在大约1000个项目列表上执行的昂贵操作来利用四核机器。

我目前正在使用R的parallel :: mclapply函数:

res = rbind.fill(parallel::mclapply(lst, fun, mc.cores=3, mc.preschedule=T))

哪个有效。 问题是,产生的任何其他子进程必须分配大块内存:

在此输入图像描述

理想情况下,我希望每个内核都可以从父R进程访问共享内存,因此当我增加mclapply中使用的内核数量时,我不会在内核限制之前达到RAM限制。

我目前对如何调试此问题感到茫然。 每个进程访问的所有大型数据结构都是全局(当前)。 这是某种问题吗?

我确实将操作系统的共享内存最大设置增加到20 GB(可用RAM):

$ cat /etc/sysctl.conf 
kern.sysv.shmmax=21474836480
kern.sysv.shmall=5242880
kern.sysv.shmmin=1
kern.sysv.shmmni=32
kern.sysv.shmseg=8
kern.maxprocperuid=512
kern.maxproc=2048

我认为这会解决问题,但问题仍然存在。

还有其他想法吗?

Linux和macosx在分叉时具有写复制机制,这意味着内存页面实际上没有被复制,而是在第一次写入之前共享。 mclapply基于fork(),所以可能(除非你写入你的大共享数据),你看到的进程列表报告的内存不是实际的内存。

但是,在收集结果时,主进程必须为mclapply的每个返回结果分配内存。

为了进一步帮助您,我们需要了解您的有趣功能。

R-devel Digest,第149卷,第22期可能会有什么提示

Radford Neal从2015年7月26日开始回答:

当mclapply分支启动新进程时,内存最初与父进程共享。 但是,只要进程写入内存页,就必须复制内存页。 不幸的是,R的垃圾收集器写入每个对象,以便在完成完整的垃圾收集时对其进行标记和取消标记,因此很可能每个R对象在每个进程中都会被复制,即使它们中的许多实际上没有被更改(从这一点开始) R计划的观点)。

我想我会认为由于写时复制功能,它不会使用额外的内存。 我认为它的列表元素很大? 也许当R将元素传递给fun()时,它实际上是制作列表项的副本而不是使用copy on write。 如果是这样,以下可能会更好:

fun <- function(itemNumber){
  myitem <- lst[[itemNumber]]
  # now do your computations
}
res = rbind.fill(parallel::mclapply(1:length(lst), fun, mc.cores=3, mc.preschedule=T))

或者直接在函数中使用lst[[itemNumber]] 如果R / Linux / macos在编写函数时不够聪明,不能使用copy-on-write,那么可能采用这种修改方法。

编辑:我假设您没有修改列表中的项目。 如果你这样做,R将会复制数据。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM