0

各スレッド内で(パッケージtclTaskScheduleから)タイマーを実行したい。ただし、次の最小限のコードtcltk2doParallel

library(doParallel)

n <- detectCores()
cl <- makeCluster(n, outfile="out.log")
registerDoParallel(cl)

testfn <- function() print(paste("hello from", i))
foreach(i=1:n, .packages = c("tcltk", "tcltk2"), .verbose = T) %dopar% {
    tclTaskSchedule(1000, testfn(), id = paste0("task", i), redo = 10)
}

stopCluster(cl)

エラーが発生します(コンソールではなく、に出力されますout.log

Error in eval(expr, envir, enclos) : could not find function "testfn"

ただし、引数から、コンソールからエクスポートされている.verbose = Tことがわかります。testfn

automatically exporting the following variables from the local environment:
  testfn

実際、 with を呼び出すforeach.export = "testfn"同じエラーが発生します。

それで、何がうまくいかないのですか?


(なぜ私はこれをしたいのですか?最終的には、一定の時間間隔で非同期的に多数のデータ ソースをポーリングし、各データ ソースには独自の特定のポーリング間隔がある場合)

4

2 に答える 2

1

tclTaskSchedule問題はその議論を評価する方法にあるというローランドに同意します。私のソリューションはきれいではありませんが、 foreach ループでワーカーのグローバル環境をtestfn使用clusterExportして割り当ててエクスポートすることで機能するようになりました。i

testfn <- function() print(paste("hello from", i))
clusterExport(cl, "testfn")

foreach(i=1:n, .packages = c("tcltk", "tcltk2"), .verbose = F) %dopar% {
    i <<- i
    tclTaskSchedule(1000, testfn(), id = paste0("task", i), redo = 10)
}

おそらく foreach にも渡し.noexport="testfn"ますが、実際には必要ありません。

于 2013-11-01T00:31:03.487 に答える
0

また、並列化されたループ内のtclTaskSchedule: printステートメントが対話型セッションに出力されなくても、別の問題を発見することになります。 foreach

ブログ投稿から:

foreach の問題の 1 つは、ループの反復ごとに新しい RScript インスタンスが作成されるため、ステータス メッセージがコンソール出力に記録されないことです。

回避策は、出力ログ ファイルを作成することです。

cat("", file="log.txt")
testfn <- function() cat("hello from", i, "\n", file="log.txt", append=TRUE)
foreach(i=1:n, .packages = c("tcltk", "tcltk2"), .verbose = T) %dopar% {
    tclTaskSchedule(1000, testfn(), id = paste0("task", i), redo = 10)
}

これは、端末tail -f log.txtから使用して監視できます。bash

于 2013-11-01T00:43:12.530 に答える