我在一个Ubuntu工作站上运行R,有8个虚拟核心和8Gb的RAM。我希望常规使用多核软件包来并行使用8个核心;然而我发现整个R过程变成8倍重复。
由于R实际上似乎比gc中报告的内存使用更多的内存(通过因子5,甚至在gc()之后),这意味着即使相对温和的内存使用(一个200Mb对象)也变得难以处理的内存一次重复8次。
我调查了bigmemory让子进程共享相同的内存空间;但它需要一些重大的我的代码,因为它不处理数据帧。
由于R实际上似乎比gc中报告的内存使用更多的内存(通过因子5,甚至在gc()之后),这意味着即使相对温和的内存使用(一个200Mb对象)也变得难以处理的内存一次重复8次。
我调查了bigmemory让子进程共享相同的内存空间;但它需要一些重大的我的代码,因为它不处理数据帧。
有没有办法使R尽可能精简,然后分叉,即让操作系统尽可能多的内存回收?
编辑:
我想我明白现在发生了什么。问题不是我认为是 – 在父线程中存在的对象,并且不操作的对象不会重复八次。相反,我的问题,我相信,来自我使每个孩子过程执行的操纵的性质。每个都必须操纵一个大的因素与几十万的水平,我认为这是记忆大的位。结果,确实是总的存储器负载与核的数量成比例的情况;但不像我想象的那么显着。
我得到的另一个教训是,对于4个物理内核,超线程的可能性,超线程实际上对于R来说通常不是一个好主意。增益是最小的,并且内存成本可能是不平凡的。所以我从现在开始工作在4核。
对于那些想要实验的人,这是我运行的代码类型:
# Create data sampdata <- data.frame(id = 1:1000000) for (letter in letters) { sampdata[,letter] <- rnorm(1000000) } sampdata$groupid = ceiling(sampdata$id/2) # Enable multicore library(multicore) options(cores=4) # number of cores to distribute the job to # Actual job system.time(do.call("cbind",mclapply(subset(sampdata,select = c(a:z)),function(x) tapply(x,sampdata$groupid,sum)) ))
你试过
data.table吗?
> system.time(ans1 <- do.call("cbind",lapply(subset(sampdata,select=c(a:z)),function(x)tapply(x,sum)) )) user system elapsed 906.157 13.965 928.645 > require(data.table) > DT = as.data.table(sampdata) > setkey(DT,groupid) > system.time(ans2 <- DT[,lapply(.SD,sum),by=groupid]) user system elapsed 186.920 1.056 191.582 # 4.8 times faster > # massage minor diffs in results... > ans2$groupid=NULL > ans2=as.matrix(ans2) > colnames(ans2)=letters > rownames(ans1)=NULL > identical(ans1,ans2) [1] TRUE
你的例子很有趣。它是相当大(200MB),有很多组(50万),每组非常小(2行)。 191s可以改进很多,但至少它是一个开始。 [2011年3月]
现在,这个成语(即lapply(.SD,…))已经改进了很多。与v1.8.2,在一个更快的计算机比上面的测试,和最新版本的R等,这里是更新的比较:
sampdata <- data.frame(id = 1:1000000) for (letter in letters) sampdata[,letter] <- rnorm(1000000) sampdata$groupid = ceiling(sampdata$id/2) dim(sampdata) # [1] 1000000 28 system.time(ans1 <- do.call("cbind",function(x) tapply(x,sum)) )) # user system elapsed # 224.57 3.62 228.54 DT = as.data.table(sampdata) setkey(DT,groupid) system.time(ans2 <- DT[,by=groupid]) # user system elapsed # 11.23 0.01 11.24 # 20 times faster # massage minor diffs in results... ans2[,groupid:=NULL] ans2[,id:=NULL] ans2=as.matrix(ans2) rownames(ans1)=NULL identical(ans1,ans2) # [1] TRUE
sessionInfo() R version 2.15.1 (2012-06-22) Platform: x86_64-pc-mingw32/x64 (64-bit) locale: [1] LC_COLLATE=English_United Kingdom.1252 LC_CTYPE=English_United Kingdom.1252 [3] LC_MONETARY=English_United Kingdom.1252 LC_NUMERIC=C [5] LC_TIME=English_United Kingdom.1252 attached base packages: [1] stats graphics grDevices datasets utils methods base other attached packages: [1] data.table_1.8.2 RODBC_1.3-6