Torque は、Moab によってジョブに割り当てられたノード名を含むファイルを常に作成し、そのファイルのパスをPBS_NODEFILE
環境変数を介してジョブに渡します。ノード名は、そのノード上のジョブに複数のコアが割り当てられたことを示すために、複数回リストされる場合があります。この場合、 の一意のノード名ごとにクラスター ワーカーを開始しますPBS_NODEFILE
が、登録時に正しいコア数を指定できるように、これらのノードのそれぞれに割り当てられたコアの数を追跡しますdoMC
。
PBS_NODEFILE
以下は、割り当てられたノード情報を含むデータ フレームを読み取って返す関数です。
getnodes <- function() {
f <- Sys.getenv('PBS_NODEFILE')
x <- if (nzchar(f)) readLines(f) else rep('localhost', 3)
as.data.frame(table(x), stringsAsFactors=FALSE)
}
返されたデータ フレームには、ノード名の「x」という名前の列と、対応するコア数の「Freq」という名前の列が含まれています。
これにより、一意のノードごとに 1 つのワーカーを持つ SOCK クラスターの作成と登録が簡単になります。
nodes <- getnodes()
cl <- makeSOCKcluster(nodes$x)
registerDoSNOW(cl)
ワーカーごとに 1 つのタスクを使用してループを簡単に実行できるようになりましたが、特に使用される関数の実装に関連するとのforeach
実装の詳細に依存せずに、それらのワーカーのそれぞれに割り当てられたコアの正しい数を渡すことはそれほど簡単ではありません。による。もちろん、割り当てられたコアの数が各ノードで同じであることがわかっている場合は簡単ですが、問題の一般的な解決策が必要な場合は困難です。snow
doSNOW
clusterApplyLB
doSNOW
1 つの (それほど洗練されていない) 一般的な解決策は、snowclusterApply
関数を介して、割り当てられたコアの数を各ワーカーのグローバル変数に割り当てることです。
setcores <- function(cl, nodes) {
f <- function(cores) assign('allocated.cores', cores, pos=.GlobalEnv)
clusterApply(cl, nodes$Freq, f)
}
setcores(cl, nodes)
これにより、各ワーカーの「allocated.cores」変数の値が、そのノードが に出現した回数と等しいことが保証されますPBS_NODEFILE
。
これで、登録時にそのグローバル変数を使用できますdoMC
。
r <- foreach(i=seq_along(nodes$x), .packages='doMC') %dopar% {
registerDoMC(allocated.cores)
foreach(j=1:allocated.cores, .combine='c') %dopar% {
i * j
}
}
この R スクリプトを実行するために使用できるジョブ スクリプトの例を次に示します。
#!/bin/sh
#PBS -l nodes=4:ppn=8
cd "$PBS_O_WORKDIR"
R --slave -f hybridSOCK.R
これがコマンドを介して送信されるqsub
と、R スクリプトは 4 つのワーカーを持つ SOCK クラスターを作成し、それらの各ワーカーはforeach
8 つのコアを使用して内側のループを実行します。しかし、R コードは一般的なものであるため、 を介して要求されたリソースに関係なく、正しいことを行う必要がありますqsub
。