foreachとdoSNOW

foreach+doSNOWパッケージを使って、並列処理をやってみたから、foreachとdoSNOWの使い方その1。

install.packages("foreach")
install.packages("doSNOW")
library(foreach)
library(doSNOW)
#基本系(返却値リスト)
foreach(i = 1:3) %do% {sqrt(i)}
#.combineオプションを指定することで返却値をベクトルにすることもできる
foreach(i = 1:3,.combine = "c") %do% {sqrt(i)}
#{}内の返却値自体がベクトルの時は.combineにcbindを指定して行列にもできる
foreach(i = 1:3,.combine = "cbind") %do% {letters[1:4]}
#自分で定義した結合方式も可能(↑の.combine関数にcを指定したケースと同じになるようにしてみた)
MyFunc <- function(x,y)c(x,y)
foreach(i = 1:3, .combine = "MyFunc") %do% {
  sqrt(i)
}
Reduce(function(x,y)c(x,y),sqrt(1:3))
foreach(a = 1:1000, b = rep(10, 2)) %do% {a + b}
library(doSNOW)
getDoParWorkers()
getDoParName()
registerDoSNOW(makeCluster(2, type = "SOCK"))
getDoParWorkers()
getDoParName()
getDoParVersion()

N <- 10^4
system.time(foreach(i = 1:N,.combine = "cbind") %do% {
	sum(rnorm(N))
})
system.time(foreach(i = 1:N,.combine = "cbind") %dopar% {
	sum(rnorm(N))
})

並列化させるためには%do%を%dopar%に変えるだけでOK

とあるので、そうした。ちょっとだけ速くなった。
 
RにおけるHPC〜並列計算編〜 Tokyo.R#11 2011/1/29から、foreachとdoSNOWの使い方その2。
スライド19枚目。

pricing.by.mc <- function(S0=100, K=100, B=90, r=0.06, sigma=0.10, T=1, M=52, N=4e5, type="knockout"){ 
	# S0:原資産の現在価格 
	# K :権利公使価格 
	# T :満期 
	# M :時間方向のステップ数 
	# N :モンテカルロ・シミュレーション試行回数 
	# ノックアウトオプションはダウン・アンド・アウトのみを考慮 
	
	delta.t <- T/M # 時間方向の刻み幅 
	z <- matrix(rnorm(M * N), nrow=M) 
	t <- replicate(N, 1:M)/M 
	S <- S0 * exp((r - sigma^2/2) * t + sigma * sqrt(t) * apply(z, 2, cumsum)) 
	if (type=="european") { 
		mean(pmax(S[M,]-K, 0)) 
	} else if (type=="knockout") { 
		y <- apply(S-B, 2, function(x) if(any(x < 0)) 0 
	else max(x[M] - K, 0)) 
	mean(y) 
	}
}
system.time(print(mean(unlist(clusterCall(cl, pricing.by.mc)))))
system.time(print(pricing.by.mc(N=1.2e6, type="knockout")))

スライド22枚目。

library(foreach)
library(doSNOW)
library(randomForest)
# doSNOWパッケージを用いて並列化するための設定
cl <-  makeSOCKcluster(2)
registerDoSNOW(cl)
# 人工的なデータを生成
x <- matrix(runif(20000), 4000)
y <- gl(2, 2000)
# 並列化を行わない場合
system.time(rf.simple <- randomForest(x, y, ntree=1000))
# foreach,doSNOWを用いて並列化した場合
system.time(rf.fe <- foreach(ntree=rep(500, 2), .combine=combine,.packages="randomForest") %dopar% randomForest(x, y, ntree=ntree))

こちらはあまり速くならなかった。原因追究は保留。