Dear Martin,
The next is some answers.
1.
Yes, I think I followed the original rlucyber's design.
If diff = FALSE (default), then all ranks generate the same random number
from the given seed.
If diff = TRUE, then all ranks have different random number (each rank take
a stream) from the given seed.
2.
The fixed code is attached.
I guess you want to divide "R" jobs rather "length(ns)" jobs, therefore, it
should be "get.jid(n = R, ...)".
You may use "comm.print(id, allrank = TRUE)" to show job distribution.
As in you case, "R <- 5" and "mpiexec -np 4 Rscript this.script", you
will have 1 in rank 0, 2 in rank 1, 3 in rank 2, and none in rank 3
(not even 4.)
The "writeChunk()" should adjust accordingly. I presume "n = R" is used, then
"chunk" will be "1" in that function. This is really dependent on how you
distribute your jobs.
3.
Your pbdNCDF4 code is correct. However, if you don't have a parallel file
system, it probably gain no performance in a nc file. At least, the code is
concise. Be careful, serial writing in parallel, you need
sync/close/barrier/reopen the same nc file sequentially rank by rank, or
the writing may not be correct. (usually wrong.)
Let us know if there are further questions.
Sincerely,
Wei-Chen Chen
### "20130310-Martin_fixed.r"
library(pbdNCDF4, quiet=TRUE)
writeChunk <- function(jn, nc, ns, n) {
# jn=job number: it is a vector in the general case
#WCC R <- sum(ns[jn])
R <- length(jn)
# the numbers of replications in this jn;
# jn is a vector when more than 1 processes are distributed to a core
#WCC chunk <- ns[1L]
chunk <- 1
# size of the full chunk
x <- replicate(n = R, expr =
sample.int(n = n, replace = TRUE),
simplify = "array")
# generate R random vectors
ncvar_put(vals = as.vector(x), start = c(1, chunk * (jn[1L] - 1L) + 1L),
count = c(-1, R),
nc = nc, varid = "indices")
# store them in the ncdf file
}
R <- 5L # total number of replications, i.e processes
chunk <- 2L # number of tasks per core, i.e. 'chunk' of processes per rank
n <- 10L # length of each vector
init()
vecind <- ncdim_def(name = "vecind", vals = seq_len(n), units = "",
create_dimvar = TRUE) # vector index
vecnum <- ncdim_def(name = "vecnum", vals = seq_len(R), units = "",
create_dimvar = TRUE) # vector number
x_var <- ncvar_def(name = "indices", dim = list(vecind, vecnum),
units = "", prec = "integer")
nc <- nc_create_par(filename = "
indices.nc", vars = x_var)
nc_var_par_access(nc = nc, var = "indices", collective = TRUE)
nchunks <- R %/% chunk # total number of full chunks
nrem <- R - nchunks * chunk # remaining processes
ns <- c(rep(x = chunk, times = nchunks),
if(! nrem) NULL else nrem) # numbers of processes for all chunks
#WCC id <- as.integer(get.jid(n = length(ns),
id <- as.integer(get.jid(n = R,
method = "block")) # divide jobs
comm.print(id, all.rank = TRUE) # print job distribution for all.
comm.set.seed(seed = rep(x = 12345L, times = 6L),
diff = TRUE)
# different ranks use different streams
# are the seeds 2^127 steps apart in the
# random number stream, as suggested
# by L'Ecuyer?
writeChunk(jn = id, ns = ns, nc = nc, n = n)
comm.end.seed()
nc_sync(nc = nc)
nc_close(nc = nc)
finalize()