餡子付゛録゛

ソフトウェア開発ツールの便利な使い方を紹介。

Rの並列処理(doParallel/foreach)で繰り返し処理を中断する方法

確認してみたのですが、試行錯誤してみた結果、結論は「ありません」でした*1。仕方が無いので、OpenMP 4.0以前の代替措置*2と同じ事をしてみたいと思います。速度的には改善になるはずです。

library("doParallel")

cl <- makeCluster(detectCores())
registerDoParallel(cl)

f <- TRUE
# 処理を if(f){ ... } で囲み、f==TRUEの間だけ計算するようにする
r <- foreach(i=1:100, .combine='c') %dopar% if(f){
# √計算するだけの処理
  v <- sqrt(i)
  if(v > 6){
# 目標達成をしたら f にFALSEを入れる
    f <- FALSE
  }
  v
}

# 平行処理終了
stopCluster(cl)

# 結果を確認する。f <- FALSE をコメントアウトして比較すると違いが分かるはず。
r

1から100までのルート計算をしていくループですが、ループは止められないけれども、6より大きい結果が得られたら計算自体はスキップすると言う代替です。ループ内の処理が重い場合は、高速化になります。

%dopar% if(f) を %:% when(f) %dopar% に書き換えたくなるのですが、平行処理スコープから親環境の変数は書き換え不可なので、狙った通りには動きません。f <- FALSE を assign("f", FALSE, envir=.GlobalEnv) に変えてみたりしたのですが、狙ったとおりには動きません。どうも平行処理スレッドごとに .GlobalEnv もコピーして保持しているようで、シェアードしないみたいですね。

*1: 初出と記事内容が大きく変わっていましたが、大きく勘違いしていたので訂正しています。動作検証時に %dopar% を %do% と書いてしまうポカをしていました。

*2: OpenMP並列forループの中断処理 - yohhoyの日記