Rmpi の並列処理ツールを使用して、大学の Unix クラスターで分析を実行しています。以下に示す R スクリプトを自分のローカル (Windows) マシンで snow パッケージまたは標準の適用関数だけを使用して実行すると、非常に遅くなりますが、正常に動作するようです。Rmpi を使用して Unix クラスターで実行すると、「シリアル化が大きすぎて生のベクターに保存できません」というエラーが表示されます。この投稿適切に思えますが、私が行ったり来たりしているベクトル (50K) は、このエラーのトリガーに近づくべきではありません。さらに、データを小さな断片に分割することで、物事を部分的に機能させることができます。問題は Rmpi に関連するある種のメモリ リークに違いないと思いますが、そのようなことをデバッグするために必要なツールがありません。うまくいけば、少なくともここで何が起こっているかをデバッグするためのツールの方向に私を向けることができます.
私が扱っているデータには最大 250 万件のレコードがあり、各レコードには最大 40 列あります。50K x 40 のデータ フレームを parApply に送信すると、50K の数値ベクトルが返されます。
#In an effort to avoid the serialization error I break into smaller pieces to avoid
#problems with large vectors getting transferred between master and slave nodes
numBreaks<-floor(length(data[,1])/50000)
base<-min(length(data[,1]),50000) #test data sets are < 50K and shouldn't
#crash the function piece.in<-data[c(1:base),] #this is the first batch of records I submit
status<-mpi.parApply(piece.in,1,test) #returns a vector of length 50K
#status<-apply(piece.in,1,test) #commented out, function runs fine locally using
#standard apply function
#cl <- makeSOCKcluster(c("localhost","localhost","localhost","localhost","localhost"))
#status<-parApply(cl,piece.in,1,test) #commented out, function runs fine locally
#using snow's SOCK cluster and identical
#parApply function
if(numBreaks>1){
for (i in 2:numBreaks){
piece.in<-data[c((base+1):(base+50000)),]
piece.out<-mpi.parApply(piece.in,1,test) #returns a vector of length 50K
#piece.out<-apply(piece.in,1,test)
#piece.out<-parApply(cl,piece.in,1,test)
status<-append(status,piece.out) #add to existing vector
base<-base+50000 #increment base
print(paste("clusters assigned to records",base,"through",(base+50000)))
}
}
#This piece cleans up the residual records
if((length(c(base:length(data[,1])))>1) & (base < length(data[,1]))){
piece.in<-data[c((base+1):length(data[,1])),]
#piece.out<-apply(piece.in,1,test)
piece.out<-mpi.parApply(piece.in,1,test)
#piece.out<-parApply(cl,piece.in,1,test)
status<-append(status,piece.out)
print(paste("Final: status has length",length(status)))
}
この関数は、テスト データセット (~100K レコード) で意図したとおりに機能します。Snow または標準の適用機能を使用してローカルで動作します (ただし、1 日かかります)。小さい断片に分割する前に、「シリアル化が大きすぎます...」というエラーで失敗しました。断片を 100K レコードの長さにすると、同じエラーで失敗しました。50K のバッチで送信されるレコードで 130 万から 135 万のレコードをカバーする繰り返しまで (ファイルに書き込まれた print ステートメントで文書化されているように) 正常に実行され、シリアル化エラーで失敗します。
並列処理を行う方法が他にもあることは知っていますが (ここで foreach コマンドを使用したかったのですが)、並列ノードが作成されるコンピューティング環境について何も知らないという制約があるため、そのままにしておきたいと思います。できればRmpiで。これをデバッグする方法に関するヒントはありますか?
とても感謝しております。
クリス