6

能够在 R 中创建一个可以阻塞直到资源被定义或被赋予适当值的函数对我来说非常有用。我知道 R 是单线程的,但我希望 mc 能够提供帮助。然而,

library(parallel)
f = function() {
  while(!exists('a')) Sys.sleep(1);
  print('success!')
}
d = mcparallel(f())
a = 1
mccollect(d)

无限期挂起。是否有任何有效的解决方法,或者我是否必须研究完全不同的模式/不同的语言才能实现类似的东西?

4

3 回答 3

7

另一个没有什么可推荐的技巧是调整底部的示例,即?socketConnection使用套接字在两个进程之间进行通信。我们将分叉的进程作为服务器(服务器必须首先启动,所以不能是交互式进程)并在途中发送它......

f <- function() {
    system.time({
        con1 <- socketConnection(port = 6011, server = TRUE, open="r")
        while (isIncomplete(con1))
            readLines(con1)
        close(con1)
    })
}     
d <- mcparallel(f())

然后我们只与它通信一次,并收集结果

con2 <- socketConnection(Sys.info()["nodename"], port = 6011)
writeLines("ok", con2)
close(con2)
mccollect(d)

这表明我执行后续命令时分叉的进程等待了一秒半

> mccollect(d)
$`28975`
   user  system elapsed 
  0.000   0.000   1.515 

如果进程是分开的而不是分叉的,这将具有更合理的感觉,例如在 MPI 作业中,人们可以使用 Rmpi​​ 包在节点之间进行通信。

于 2013-02-06T02:39:56.033 回答
5

我什至不知道可以分叉这样的进程。玩了一会儿后,我找到了该sendChildStdin功能,您应该检查一下。这至少是向子进程发出信号的一种方式。这是一个例子:

f<- function () {
  message<-scan(n = 1, quiet = TRUE, what='character')
  return(message)
}
p  <- mcparallel(f())
a <- 1
# The message shouldn't contain spaces and should end with a newline.
parallel:::sendChildStdin(p, "created\n") 
mccollect(p)[[1]]
[1] "created"

不要误会我的意思;如果您要深入研究这些东西,R 可能不是您想要的语言,但它可能适用于轻量级应用程序。


我之前在 RStudio 中测试过代码,虽然它看起来可以工作,但失败的方式与成功无法区分。无论如何,它基本上不会等待该scan过程。例如,这不应该完成,但它确实(仅在 RStudio 中)

f<- function () {
  message<-scan(n = 1, quiet = TRUE, what='character')
  return(message)
}
p  <- mcparallel(f())
# parallel:::sendChildStdin(p, "created\n")
mccollect(p)[[1]]
# character(0)
于 2013-02-06T02:22:54.150 回答
2

我不知道使用并行的方式,但 tcltk 实用程序以与常规 R 事件循环并行或背景的方式运行。您可以使用tclTaskScheduletcltk2 包中的函数来执行类似于上述循环的操作:

library(tcltk)
library(tcltk2)
tclTaskSchedule(1000, if( exists('a') ) { 
    tclTaskChange('WaitForA', redo=FALSE)
    cat('Success!\n\n')
    }, id='WaitForA',  redo=TRUE )

现在您可以在 R 中执行其他操作(假设a尚不存在),并且在后台,上述内容将a大约每 1 秒检查一次。一旦您创建a(或在大约一秒钟内)然后“成功!” 将被打印到屏幕上(它将停止检查)。

请注意,这是使用并行的替代品。显然 tcltk 和 parallel 包不能很好地结合在一起(看起来这已经在 R devel 中修复并打了补丁,所以这可能在 R 版本 2.15.3 之后与 parallel 一起使用)。因此,如果您还将并行包用于其他事情,请小心使用它。如果并行只是您尝试的一个选项并且您没有将其用于其他事情,那么此方法应该可以正常工作。

于 2013-02-06T18:18:07.887 回答