set.seed(20140219)
Y <- rnorm(5000, rep(c(1, 5, 10, 25, 50), rep(1000, 5)))
Y <- Y[sample(5000)]
G <- rep(1:100, rep(50, 100))
dofor <- function(x, y = Y, g = G) {
for (i in unique(g)) mean(y[g == i])
}
dotapp <- function(x, y = Y, g = G) {
tapply(y, g, function(z) mean(z))
}
repfn <- function(f, n = 100, cmp = FALSE) {
tm0 <- Sys.time()
if (cmp == TRUE)
f <- cmpfun(f)
replicate(n, f(0))
tm1 <- Sys.time()
(tm1 - tm0)/n
}
bench <- c(forLoop = repfn(dofor), tapply = repfn(dotapp))
bench/min(bench)
## forLoop tapply
## 3.167 1.000
compiler package pre-installed.cmpfunrequire(compiler)
bench <- c(bench,
forComp=repfn(dofor,cmp=TRUE),
forPreComp=repfn(cmpfun(dofor)),
tappComp=repfn(dotapp,cmp=TRUE)
)
bench/min(bench)
## forLoop tapply forComp forPreComp tappComp
## 3.167 1.000 3.132 3.081 1.032
fun <- function(x, y = Y, g = G) {
a <- 1:5000 * g
b <- y - 32
ab <- tcrossprod(a, b)
for (i in 1:5000) {
ab[i, i] <- g[i]%%3
}
for (i in 1:5000) {
ab[i, 1] <- a[i] - b[i]
ab[1, i] <- b[i] - a[i]
}
}
bench2 <- c(repfn(fun), repfn(fun, cmp = TRUE))
bench2/min(bench2)
## [1] 1.243 1.000
repfn..Renviron file in your home directory.R_COMPILE_PKGS=TRUE
R_ENABLE_JIT=3
snow library.require(snow)
cl <- makeCluster(4)
dotappClus <- function(x) {
parLapply(cl, split(Y, G), mean)
}
repfnClus <- function(f, n = 100) {
tm0 <- Sys.time()
parSapply(cl, integer(n), f, y = Y, g = G)
tm1 <- Sys.time()
(tm1 - tm0)/n
}
bench <- c(bench, tappClus1 = repfn(dotappClus), tappClus2 = repfnClus(dotapp),
forClus = repfnClus(dofor))
stopCluster(cl)
bench/min(bench)
## forLoop tapply forComp forPreComp tappComp tappClus1
## 6.635 2.095 6.561 6.454 2.162 2.387
## tappClus2 forClus
## 1.000 2.800
snowfall, doParallelrequire(doParallel, quietly = TRUE)
cl <- makeCluster(4)
registerDoParallel(cl)
invisible({
t0 <- Sys.time()
foreach(i = 1:100) %dopar% dotapp(0)
t1 <- Sys.time()
})
stopCluster(cl)
bench <- c(bench, tappForEach = (t1 - t0)/100)
bench/min(bench)
## forLoop tapply forComp forPreComp tappComp tappClus1
## 6.635 2.095 6.561 6.454 2.162 2.387
## tappClus2 forClus tappForEach
## 1.000 2.800 2.033
Conceptually, it's trivial to parallelize chains in MCMC.
For JAGS, there is a package available, dclone (for data cloning) that includes helpful functions to run chains in parallel.
Check the documentation, but it looks pretty easy. parJagsModel and parCodaSamples
This package should take care of instantiating each pRNG with sufficiently different seeds.
For stan, you don't get much help. Do your parallelism in such a way that you get a list of stanfit objects, then combine them with the helper function sflist2stanfit.
So you could do something like:
parSapply(cl, function(i) stan(fit = f1, seed = seed, chains = 1, chain_id = i,
refresh = -1))
There are examples in the R documentation for sflist2stanfit, so check that out.
By iterating the chainid, and having a consistent seed, stan should ensure that you get different pRNG sequences.
\home\ddd281\bin (my "home" directory)~\bincd \home\ddd281mkdir \home\ddd281\FolderNamels -l ~\bin\home\ddd281 - 5GB limit per user.
\scratch\ddd281 - This is the "working directory" for running jobs. It has a 5TB limit per user.
\archive\ddd281 - This is longer-term storage. It is backed up, and begins with an allocation of 2TB/user. Faculty sponsors can request more.mv src dst to move file src to dst (can also function as a "rename")cp src dst to copy file src to dstrm src to remove (delete) src-r flag to them.rsync to move files to and from the cluster, but you can also use WinSCP or gFTP or similar program.rsync -azvr src dst - There are some funky things with trailing slashes. (read the manpage)hpctunnel active, first, and then you can log onto the individual clusters to transfer files.ls -l | wc -l lists the files in a directory, and then sends that output to the next command.wc -l counts the lines in the input. So the combined command counts the number of files in a folder.ls -l > out.filels -l | wc -l >> out.file&> or &>> (to redirect both stdout and stderr)2> (1>)vim, nano, emacs, etc (personal preference, but vim is the best)echo "This is a line ot text." > out.filesed) to do simple search and replace using regular expressions.cat out.file | sed "s/ot /of /" > out.file fixes our typo..sh#!\usr\bin\env bash on the first linechmod +x scriptname.sh./scriptname.sh or sh scriptname.sh$1 (for the 1st argument) and so on.VAR=24 and recalled with $VAR$PATH is your "search path" which lists (in order) where the shell will search for executable files.export PATH=/home/ddd281/bin:$PATHnyuhpc_update.sh#! /usr/bin/env bash
set -e
if [ "`ps aux |grep hpctunnel|wc -l`" -lt "2" ] ; then
echo "Need to have HPC's SSH tunnel active. Run ssh hpctunnel"
exit 0;
fi
if [ "$1" != "pdfs" ]; then
rsync -avzr --exclude '*.pdf' --delete cpp/ bowery:~/ocr_files/
exit 0;
fi
rsync -azvr --delete cpp/ bowery:~/ocr_files/
exit 0;
~/.ssh/config file (create if it doesn't exit)ssh hpctunnel and then login. Then, in a new terminal, you can connect to the cluster you want with ssh usq, ssh bowery, ssh cardiac1ddd281@hpc.es.its.nyu.edu, login, and then you can simply ssh usq (or whichever cluster)Host hpctunnel
HostName hpc.es.its.nyu.edu
LocalForward 8020 usq.es.its.nyu.edu:22
LocalForward 8021 bowery.es.its.nyu.edu:22
LocalForward 8022 cardiac1.es.its.nyu.edu:22
User NetID
Host usq
HostName localhost
Port 8020
ForwardX11 yes
User NetID
Host bowery
HostName localhost
Port 8021
ForwardX11 yes
User NetID
Host cardiac1
HostName localhost
Port 8022
ForwardX11 yes
User NetID
Rscript filename.Rstata -b do filename or stata < filename.do > filename.logset processors X where X is the number of cores to use../my_programqsub -I -q interactive -l nodes=1:ppn=8,walltime=04:00:00#PBS -V
#PBS -S /bin/bash
#PBS -N ocr-2014-02-19
#PBS -l nodes=1:ppn=1,walltime=10:00:00
#PBS -l mem=1GB
#PBS -q s48
#PBS -M ddd281@nyu.edu
#PBS -m bea
#PBS -w /scratch/ddd281/ocr_wd/
#PBS -e localhost:${PBS_O_WORKDIR}/pbs_files/${PBS_JOBNAME}.e${PBS_JOBID}
#PBS -o localhost:${PBS_O_WORKDIR}/pbs_files/${PBS_JOBNAME}.o${PBS_JOBID}
#PBS -V - exports environment variables from current session to the job's sessionPBS -S /bin/bash - which shell to use. No need to change this.#PBS -N ocr-2014-02-19 - a name for the job. This will be used in emails, and in naming some logfiles.#PBS -l nodes=1:ppn=1,walltime=10:00:00
nodes=1 - tells the scheduler how many nodes to allocate to the jobppn=1 - how many processors per node?walltime=10:00:00 - how much time to allocate to this job (and NO longer)#PBS -l mem=1GB - how much memory to allocate to this job (and NO longer)#PBS -q s48 - which queue should this job be placed in?#PBS -M ddd281@nyu.edu - NYU email#PBS -m bea - email me on begin, aborts, ends#PBS -w /scratch/ddd281/ocr_wd/ - sets the working directory for the job#PBS -e localhost:${PBS_O_WORKDIR}/pbs_files/${PBS_JOBNAME}.e${PBS_JOBID} - location to redirect stderr#PBS -o localhost:${PBS_O_WORKDIR}/pbs_files/${PBS_JOBNAME}.o${PBS_JOBID} - location to redirect stdoutman qsub for much more information on options.qsub to submit a job (pbs script)showq | grep ddd281 to view your jobs in the queueqdel 1234 to delete job number 1234qstat 1234 to see status report on job 1234module availr/intel/3.0.1module show r for more info (for instance, where binaries are stored, etc)module load r/intel/3.0.1module command is available:source /etc/profile.d/env-modules.shhpc.Rargs <- commandArgs(trailingOnly = TRUE)
if(length(args)!=2) stop(paste0("Not the right number of arguments!",args))
args <- as.double(args)
load("s_africa_data.Rdata")
require(cvTools)
require(topicmodels)
cvLDA <- function(Ntopics,K=5) {
folds<-cvFolds(nrow(dtm),K,1)
perplex <- rep(NA,K)
llk <- rep(NA,K)
for(i in unique(folds$which)){
which.test <- folds$subsets[folds$which==i]
which.train <- {1:nrow(dtm)}[-which.test]
dtm.train <- dtm[which.train,]
dtm.test <- dtm[which.test,]
lda.fit <- LDA(dtm.train,Ntopics)
perplex[i] <- perplexity(lda.fit,dtm.test)
llk[i] <- logLik(lda.fit)
}
perplex <- mean(perplex)
perpSD <- sd(perplex)
llk <- mean(llk)
llkSD <- sd(llk)
return(c(K=Ntopics,perplexity=perplex,perpSD=perpSD,logLik=llk,logLikSD=llkSD))
}
Topics.to.Est <- seq(args[1],args[2])
cv.out <- t(sapply(Topics.to.Est,cvLDA))
name<-paste0("cv.out.",min(Topics.to.Est),".",max(Topics.to.Est))
assign(name,cv.out)
save(list=name,file=paste0(name,".Rdata"))
ldacv.pbs#!/bin/bash
#PBS -V
#PBS -S /bin/bash
#PBS -N ldacv-INSERTMIN-INSERTMAX
#PBS -l nodes=1:ppn=1,walltime=12:00:00
#PBS -l mem=8GB
#PBS -q s48
#PBS -M ddd281@nyu.edu
#PBS -m bea
#PBS -e localhost:${PBS_O_WORKDIR}/pbs_files/${PBS_JOBNAME}.e${PBS_JOBID}
#PBS -o localhost:${PBS_O_WORKDIR}/pbs_files/${PBS_JOBNAME}.o${PBS_JOBID}
set -e
OLDDIR=`pwd`
cd /scratch/ddd281/ldacv
module load gsl/intel/1.15
/home/ddd281/local/bin/Rscript --vanilla hpc.R INSERTMIN INSERTMAX
cd $OLDDIR
exit 0;
start_ldacv.sh./start_ldacv.sh 50 50./start_ldacv.sh 10 13#!/bin/bash
set -e
cat ldacv.pbs | sed "s/INSERTMIN/$1/g" | sed "s/INSERTMAX/$2/g" > ldacv.${1}-${2}.pbs
qsub ldacv.${1}-${2}.pbs
rm ldacv.${1}-${2}.pbs
files <- dir()
files <- files[grep("cv.out", files)]
cv.out <- NULL
for (f in files) {
load(f)
vr <- strsplit(f, ".", fixed = TRUE)[[1]]
vr <- paste(vr[-length(vr)], collapse = ".")
cv.out <- rbind(cv.out, get(vr))
rm(list = vr)
}
cv.out <- cv.out[order(cv.out[, "K"]), ]
save(cv.out, file = "ldacv_all.Rdata")
snow) would only be more complicated and error prone#PBS -l nodes=<N/12>:ppn=12
...
cd directory_for_job1
mpiexec -comm none -n 1 $executable arguments_for_job1 > output 2> error &
...
cd directory_for_jobN
mpiexec -comm none -n 1 $executable arguments_for_jobN > output 2> error &
wait
set -e at the start of shell scripts! This will make it quit immediately upon encountering an error../configuremake && make install--prefix=/home/ddd281/local to configuremake && make install as normal. This will install R to the appropriate directory.module load gcc/4.7.3 (on bowery, versions may be different, so check module avail)\home\ddd281\local\bin to your PATH, or you can just call R with \home\ddd281\local\bin\Rscriptmodule load intel/11.1.046icc / icpc / etc-O2 -fPIC -align -Zp8 -axP -unroll -xP -ip-shared-intel to get my C++ to compile properly.