阻止和等待R

tre*_*bot 6 r blocking

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

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

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

Mar*_*gan 7

另一个很少推荐它的黑客是?socketConnection使用套接字调整两个进程之间通信底部的示例.我们将forked进程设置为服务器(服务器必须首先启动,因此不能成为交互式进程)并将其发送到路上......

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

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

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

这告诉我,当我执行后续命令时,分叉进程等了一秒半

> mccollect(d)
$`28975`
   user  system elapsed 
  0.000   0.000   1.515 
Run Code Online (Sandbox Code Playgroud)

如果进程是分离的而不是分叉的,那么这将具有更合理的感觉,如在MPI作业中,可以使用Rmpi包在节点之间进行通信.


nog*_*pes 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"
Run Code Online (Sandbox Code Playgroud)

别误会我的意思; 如果你要深入研究这些东西,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)
Run Code Online (Sandbox Code Playgroud)