3

この質問(https://stackoverflow.com/questions/17222942/allow-foreach-workers-to-register-and-distribute-sub-tasks-to-other-workers)の続きで、接続するためのベストプラクティスは何ですか外側の並列ループのコードの一部を処理する内側の並列ループでプロセッサ アフィニティを回避するために、doSNOW と SOCK を Torque/MOAB スケジューラにクラスタ化しますか?

その質問に対するスティーブの答えから、スケジューラーとの干渉のないベースライン コードは次のようになります。

library(doSNOW)
hosts <- c('host-1', 'host-2')
cl <- makeSOCKcluster(hosts)
registerDoSNOW(cl)
r <- foreach(i=1:4, .packages='doMC') %dopar% {
  registerDoMC(2)
  foreach(j=1:8, .combine='c') %dopar% {
    i * j
  }
}
stopCluster(cl)  
4

1 に答える 1

3

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実装の詳細に依存せずに、それらのワーカーのそれぞれに割り当てられたコアの正しい数を渡すことはそれほど簡単ではありません。による。もちろん、割り当てられたコアの数が各ノードで同じであることがわかっている場合は簡単ですが、問題の一般的な解決策が必要な場合は困難です。snowdoSNOWclusterApplyLBdoSNOW

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 クラスターを作成し、それらの各ワーカーはforeach8 つのコアを使用して内側のループを実行します。しかし、R コードは一般的なものであるため、 を介して要求されたリソースに関係なく、正しいことを行う必要がありますqsub

于 2013-06-25T13:57:56.887 に答える