前に並列化を試みたときはうまく出来なかったが、今回うまく並列計算できるようにプログラムが書けた。
コツとしては、とにかく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")