我想知道是否可以使用R
. 我已经尝试了一些谷歌搜索,但一无所获。
我目前遇到的一般问题:
- 我有一些大物体需要大约半小时才能完成
load
- 我想在数据上生成一系列图(需要几分钟)。
- 发生这种情况时,我想对数据做其他事情(虽然不更改基础数据!)
理想情况下,我将能够从交互式会话中分派命令,而不必等待它返回(这样我就可以在等待绘图渲染的同时去做其他事情)。这是可能的,还是一厢情愿的情况?
我想知道是否可以使用R
. 我已经尝试了一些谷歌搜索,但一无所获。
我目前遇到的一般问题:
load
理想情况下,我将能够从交互式会话中分派命令,而不必等待它返回(这样我就可以在等待绘图渲染的同时去做其他事情)。这是可能的,还是一厢情愿的情况?
为了扩展 Dirk 的答案,我建议您使用parallel
包中的“snow”API。该mcparallel
功能似乎非常适合此功能(如果您不使用 Windows),但由于使用fork
. “雪” API 的问题在于它不正式支持异步操作。但是,如果您不介意使用非导出函数作弊,那么这很容易做到。如果您查看 的代码clusterCall
,您可以弄清楚如何异步提交任务:
> library(parallel)
> clusterCall
function (cl = NULL, fun, ...)
{
cl <- defaultCluster(cl)
for (i in seq_along(cl)) sendCall(cl[[i]], fun, list(...))
checkForRemoteErrors(lapply(cl, recvResult))
}
所以你只是sendCall
用来提交一个任务,并recvResult
等待结果。bigmemory
这是 Dirk 建议的使用包的示例。
big.matrix
您可以使用或等函数创建“大矩阵” as.big.matrix
。您可能希望有效地做到这一点,但我将z
使用以下方法转换矩阵as.big.matrix
:
library(bigmemory)
big <- as.big.matrix(z)
现在我将创建一个集群并将每个工作人员连接到big
使用describe
and attach.big.matrix
:
cl <- makePSOCKcluster(2)
worker.init <- function(descr) {
library(bigmemory)
big <<- attach.big.matrix(descr)
X11() # use "quartz()" on a Mac; "windows()" on Windows
NULL
}
clusterCall(cl, worker.init, describe(big))
除了附加到大矩阵之外,这还会在每个工人上打开图形窗口。
要调用persp
第一个集群工作者,我们使用sendCall
:
parallel:::sendCall(cl[[1]], function() {persp(big[]); NULL}, list())
这几乎立即返回,尽管可能需要一段时间才能出现情节。此时,您可以将任务提交给其他集群工作者,或者做一些完全不相关的事情。只需确保您在向同一工作人员提交另一个任务之前阅读了结果:
r1 <- parallel:::recvResult(cl[[1]])
当然,这很容易出错,而且一点也不漂亮,但是你可以编写一些函数来使它更容易。请记住,诸如此类的非导出函数可能会随着 R 的任何新版本而改变。
请注意,通过子集集群对象在特定工作人员或一组工作人员上执行任务是完全可能且合法的。例如:
clusterEvalQ(cl[1], persp(big[]))
这会将任务发送给第一个工作人员,而其他工作人员什么也不做。但当然,这是同步的,因此在此任务完成之前,您无法对其他集群工作人员执行任何操作。我知道异步发送任务的唯一方法是作弊。
R 是并且将继续是单线程的。
但是你可以共享资源。一种方法是在一个会话中加载您的大数据,将其分配给一个 bigmemory 对象——然后与同一盒子上的其他 R 会话共享该对象的“句柄”。在具有足够内存(即所有数据需求的低倍数)的体面 Linux 机器上应该是小菜一碟。