Steve,
I used a non-trivial example and got a nice speed boost, so thanks for
that advice.
Now I need advice on a real-world application. I am working with a
genomic data-set that involves a lot of calculations on a data-frame
as well as parallel sub-settting of an annotation data-frame. The
data.frames initially have about 30k rows and up to 100 columns. If,
for example, I have 5 cores to work with, it seems to me that the most
efficient way, rather than making repeated calls to the cores, would
be to parcel things out by the number of rows divided by the number of
cores. That would mean sending data.frames to the functions that
do.par calls rather than vectors. Below is some a self-contained
example. It doesn't work because i doesn't get incremented after the
%dopar% operator.
I'm new to the parallel processing world, so if I am not taking the
right approach let me know, or, if another package might work better.
Thanks,
Mark
###########################################################
require(foreach)
require(multicore)
require(doMC)
Ncore <- 5
registerDoMC(cores=Ncore)
Ncol <- 300
Nrow <- 500
do.par.test.called.func <- function(Mat1, Mat2){
?Mat3 <- Mat1 + Mat2
?for(i in 1:nrow(Mat3)){
? ?for (j in 1:ncol(Mat3)){
? ? ?Mat3[i,j] <- sqrt(abs(Mat3[i,j]))
? ?}
?}
?Mat3
}
do.par.test.func <- function(Nrow, Ncol, Ncore){
?x.mat <- matrix(rnorm(Ncol * Nrow), Nrow, Ncol)
?y.mat <- matrix(rnorm(Ncol * Nrow), Nrow, Ncol)
?N <- ceiling(Nrow/Ncore)
?b <- foreach(i = 1:Ncore) %dopar% do.par.test.called.func(x.mat[(i *
N): (((i + 1) * N) -1),], y.mat[(i * N): (((i + 1) * N) -1),])
?b
}
#
do.par.out <- do.par.test.func(Nrow, Ncol, Ncore)
############################################
------------------------------------------------------------
Mark W. Kimpel MD ?** Neuroinformatics ** Dept. of Psychiatry
Indiana University School of Medicine
15032 Hunter Court, Westfield, IN ?46074
(317) 490-5129 Work, & Mobile & VoiceMail
"The real problem is not whether machines think but whether men do."
-- B. F. Skinner
******************************************************************
On Wed, Jul 15, 2009 at 1:50 PM, Steve
Weston<steve at revolution-computing.com> wrote:
And you can get much better results using sqrt directly on the vector,
as it is intended to be called. ?The sqrt function is so fast that it's
crazy to call it in parallel the way my vignette shows. ?The
overhead kills you. ?But I have this bad habit of using sqrt in my
parallel programming examples. ?I actually put a footnote in the
vignette saying you should never do what I just did, but I can see
now that I wasn't nearly explicit enough. ?I should probably include
a big disclaimer saying not to try this at home.
I'm pretty sure that the next version of foreach will issue warnings
if the tasks execute in less than a second. ?But I'll definitely fix
the vignette. ?Sorry about that.
- Steve
On Wed, Jul 15, 2009 at 12:54 PM, Mark Kimpel<mwkimpel at gmail.com> wrote:
I'm having trouble getting these packages to work as I believe they
should. I have a new Debian Lenny box running on an Intel i7 with 12
GB of memory and wrote a test script to see how much performance
increase I could achieve with foreach. For this purpose, I used code
extracted from the vignette. Below is the code, the system.time
output, and sessionInfo(). I should add that I've run this multiple
times and always achieved similar results. These last were achieved
after doing init 1 to get me into a strict terminal mode and avoid the
GUI.
As you can see, the results seem to be the opposite of what one would
expect. The fastest time, by an order of magnitude, is achieved by a
simple for loop, and %do% slightly outperforms %dopar%
How can this be explained?
Mark
####################################
require(foreach)
require(multicore)
require(doMC)
registerDoMC(cores=5)
z <- 30000
for.each.do.time <- system.time(
? ? ? ? ? ?a <- foreach(i = 1:z, .combine = "c") %do% sqrt(i)
? ? ? ? ? ?)
#
for.each.do.par.time <- system.time(
? ? ? ? ? ?b <- foreach(i = 1:z, .combine = "c") %dopar% sqrt(i)
? ? ? ? ? ?)
#
c <- rep(0,z)
loop.time <- system.time(
? ? ? ? ? ?for (i in 1:length(c))
? ? ? ? ? ?c[i] <- sqrt(i)
? ? ? ? ? ?)
#
out <- rbind(unclass(for.each.do.time), unclass(for.each.do.par.time),
unclass(loop.time))
out
"user.self" ? ? "sys.self" ? ? ?"elapsed" ? ? ? "user.child" ? ?"sys.child"
25.713 ?0 ? ? ? 25.712 ?0 ? ? ? 0
25.918 ?0.016 ? 26.015 ?0.192 ? 0.192
0.207999999999998 ? ? ? 0 ? ? ? 0.206000000000003 ? ? ? 0 ? ? ? 0
#
"R.version.platform" "x86_64-unknown-linux-gnu"
"R.version.arch" "x86_64"
"R.version.os" "linux-gnu"
"R.version.system" "x86_64, linux-gnu"
"R.version.status" ""
"R.version.major" "2"
"R.version.minor" "9.1"
"R.version.year" "2009"
"R.version.month" "06"
"R.version.day" "26"
"R.version.svn rev" "48839"
"R.version.language" "R"
"R.version.version.string" "R version 2.9.1 (2009-06-26)"
"locale" "LC_CTYPE=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8;LC_COLLATE=en_US.UTF-8;LC_MONETARY=C;LC_MESSAGES=en_US.UTF-8;LC_PAPER=en_US.UTF-8;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=en_US.UTF-8;LC_IDENTIFICATION=C"
"basePkgs1" "stats"
"basePkgs2" "graphics"
"basePkgs3" "grDevices"
"basePkgs4" "datasets"
"basePkgs5" "utils"
"basePkgs6" "methods"
"basePkgs7" "base"
------------------------------------------------------------
Mark W. Kimpel MD ?** Neuroinformatics ** Dept. of Psychiatry
Indiana University School of Medicine
15032 Hunter Court, Westfield, IN ?46074
(317) 490-5129 Work, & Mobile & VoiceMail
"The real problem is not whether machines think but whether men do."
-- B. F. Skinner
******************************************************************
On Wed, Jul 1, 2009 at 10:56 PM, Steve
Weston<steve at revolution-computing.com> wrote:
There have been several announcements of three new packages that I've
recently uploaded to CRAN: foreach, iterators, and doMC. ?You can read
one description on David Smith's blog, at:
? ?http://blog.revolution-computing.com
or:
? ?http://bit.ly/tygLz
You can also read the vignette that I wrote for foreach on a CRAN
website.
I would like to mention that one of the goals of the foreach package is
to make it easy to write an R package that allows the end user to choose
what parallel computing engine to use. ?That's useful because the user
may already have and use a parallel computing system, and not want to
install and maintain yet another one. ?(The foreach and iterators packages
themselves are trivial to install, since they provide a framework for using
parallel computing systems such as multicore and nws.)
Currently, only the doMC "parallel backend" for multicore is publicly
available on CRAN, but I'm hoping to get a chance to write and release
other backend packages, to support MPI and shared memory, for example.
I'd love to hear from R package authors on how to improve foreach
so that it's a more attractive platform on which to develop parallel
applications. ?Especially if you've had difficulty using parallel
computing systems in the past.
--
Steve Weston
REvolution Computing
One Century Tower | 265 Church Street, Suite 1006
New Haven, CT ?06510
P: 203-777-7442 x266 | www.revolution-computing.com