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

もう 1 つのハックは、?socketConnectionソケットを使用した 2 つのプロセス間の通信の下部にある例を適応させることです。フォークされたプロセスをサーバーにし (サーバーを最初に起動する必要があるため、対話型プロセスにすることはできません)、途中で送信します...

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)

これは、フォークされたプロセスが、後続のコマンドを実行している間、1 秒半待機したことを示しています。

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

Rmpi パッケージを使用してノード間で通信できる MPI ジョブのように、プロセスがフォークされるのではなく分離されている場合、これはより正当な感じになります。

于 2013-02-06T02:39:56.033 に答える
5

そのようなプロセスをフォークできることさえ知りませんでした。少し遊んだ後、sendChildStdinチェックすべき機能を見つけました。これは、子プロセスにシグナルを送る少なくとも 1 つの方法です。次に例を示します。

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(またはその約1秒以内に)「成功!」画面に印刷されます(チェックが停止します)。

これは、並列を使用するための代替であることに注意してください。どうやらtcltkと並列パッケージは一緒にうまく機能しないようです(これはR開発で修正され、パッチが適用されているようですので、Rバージョン2.15.3以降の並列で動作する可能性があります)。したがって、他の目的でも並列パッケージを使用している場合は、これを使用する場合は注意が必要です。並列があなたが試みていた単なるオプションであり、それを他の目的に使用していない場合、この方法はうまくいくはずです。

于 2013-02-06T18:18:07.887 に答える