並列化

前に並列化を試みたときはうまく出来なかったが、今回うまく並列計算できるようにプログラムが書けた。
コツとしては、とにかく1回のシミュレーションでやることを

function(){ ~}

に収めてしまうことだろう。例えば、既に読み込んでいるからといって

a <- read.csv("適当なデータ")
clustfun <- function{
	lp.assign(a)
}
cl <- makeCluster(8, type="SOCK") #8コア使う
clusterExport(cl, "clustfun")
niter <- 10
clustresult <- parSapply(cl, 1:niter, function(x){clustfun()})

とやってもダメなようである。こうすると、データaもないしlp.assignのためのパッケージもないと言われる。これを回避するために

library(snow)
clustfun <- function{
	a <- read.csv("適当なデータ")
	library(lpSolve)
	lp.assign(a)
}
cl <- makeCluster(8, type="SOCK") #8コア使う
clusterExport(cl, "clustfun")
niter <- 10
clustresult <- parSapply(cl, 1:niter, function(x){clustfun()})

とすると動く。上のシンプレックスシミュレーションでは、結果は行列で返ってくる仕様だったが、

parSapply()

は1回毎のシミュレーションはベクトルで返ってきて、それをcbind()していた。ということで最後に加工した。
 

gsim <- function(){
	#データの読み込み
	pdata <- as.matrix(read.csv("temp.csv"))
	pdata <- pdata[, -1]
	dimnames(pdata) <- NULL
	
	#シンプレックス法シミュレーション用に、データを適当に並び替える
	idx <- sample(1:nrow(pdata))
	newdata <- pdata[idx, ]
	library(lpSolve)
	res <- lp.assign(newdata, direction="max")
	#割当行列
	resmat <- res$solution
	course <- (1:110)[-c(10, 14, 16, 21, 24, 38, 47, 75, 77, 79, 98, 101)]
	gvec <- numeric(length(course)) #グループ
	cvec <- numeric(length(course)) #コース
    evec <- numeric(length(course)) #希望
    smallg <- c(6, 6, 6, 6, 5, 6, 5, 6, 5, 5, 5, 6, 5, 6, 5, 6, 4, 6, 5, 6) #小グループ人数
	groupcut <- c(0, head(cumsum(smallg), -1L), sum(smallg))
	for(i in 1:length(idx)){
		cvec[idx[i]] <- course[which(resmat[i, ] != 0)]
        gvec[idx[i]] <- tail(which(groupcut < course[which(resmat[i, ] !=0)]), 1)
        evec[idx[i]] <- pdata[idx[i], which(resmat[i, ] != 0)]    
	}
    return(rbind(cvec, gvec, evec))
}
cl <- makeCluster(8, type="SOCK") #8コア使う
clusterExport(cl, "gsim")
niter <- 100000 #シミュレーション回数
#8コアでやって13時間くらい
#1回やるだけなら2秒くらい
#つまり55~60時間くらいか?
system.time(
	pniter <- parSapply(cl, 1:niter, function(x){gsim()})
)
#pniter
sscourse <- pniter[(1:(nrow(pniter)/3))*3 - 2, ] #コース結果
ssgroup <- pniter[(1:(nrow(pniter)/3))*3 - 1, ] #グループ結果
ssexpect <- pniter[(1:(nrow(pniter)/3))*3, ] #コースの希望がなんだったか

#これで30MBくらい
write.csv(sscourse, file="sscourse.csv")
write.csv(ssgroup, file="ssgroup.csv")
write.csv(ssexpect, file="ssexpect.csv")