[med-svn] [r-cran-doparallel] 10/12: New upstream version 1.0.10

Andreas Tille tille at debian.org
Mon Oct 9 14:03:11 UTC 2017


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository r-cran-doparallel.

commit eb44b6673c547d92cd0d266bc22753b42c25f4e1
Author: Andreas Tille <tille at debian.org>
Date:   Mon Oct 9 16:01:46 2017 +0200

    New upstream version 1.0.10
---
 DESCRIPTION                             |  27 ++
 MD5                                     |  18 ++
 NAMESPACE                               |   7 +
 NEWS                                    |  32 ++
 R/doParallel.R                          | 515 ++++++++++++++++++++++++++++++++
 R/zzz.R                                 |   3 +
 build/vignette.rds                      | Bin 0 -> 240 bytes
 debian/README.test                      |   8 -
 debian/changelog                        |  25 --
 debian/compat                           |   1 -
 debian/control                          |  27 --
 debian/copyright                        |  29 --
 debian/docs                             |   3 -
 debian/patches/series                   |   1 -
 debian/patches/unittest-no-report.patch |  20 --
 debian/rules                            |   6 -
 debian/source/format                    |   1 -
 debian/tests/control                    |   3 -
 debian/tests/run-unit-test              |  10 -
 debian/watch                            |   2 -
 demo/00Index                            |   1 +
 demo/sincParallel.R                     |  37 +++
 inst/doc/gettingstartedParallel.R       |  73 +++++
 inst/doc/gettingstartedParallel.Rnw     | 344 +++++++++++++++++++++
 inst/doc/gettingstartedParallel.pdf     | Bin 0 -> 151532 bytes
 inst/examples/bootParallel.R            |  83 +++++
 inst/unitTests/options.R                |  84 ++++++
 inst/unitTests/runTestSuite.sh          |  46 +++
 man/doParallel-package.Rd               |  39 +++
 man/registerDoParallel.Rd               |  59 ++++
 tests/doRUnit.R                         |  70 +++++
 vignettes/gettingstartedParallel.Rnw    | 344 +++++++++++++++++++++
 32 files changed, 1782 insertions(+), 136 deletions(-)

diff --git a/DESCRIPTION b/DESCRIPTION
new file mode 100644
index 0000000..30ca57c
--- /dev/null
+++ b/DESCRIPTION
@@ -0,0 +1,27 @@
+Package: doParallel
+Type: Package
+Title: Foreach Parallel Adaptor for the 'parallel' Package
+Version: 1.0.10
+Authors at R: c(person("Rich", "Calaway", role="cre", email="richcala at microsoft.com"),
+             person("Revolution", "Analytics", role=c("aut", "cph")),
+			 person("Steve", "Weston", role="aut"),
+			 person("Dan", "Tenenbaum", role="ctb"))
+Description: Provides a parallel backend for the %dopar% function using
+        the parallel package.
+Depends: R (>= 2.14.0), foreach(>= 1.2.0), iterators(>= 1.0.0),
+        parallel, utils
+Suggests: caret, mlbench, rpart
+Enhances: compiler, RUnit
+License: GPL-2
+Author: Rich Calaway [cre],
+  Revolution Analytics [aut, cph],
+  Steve Weston [aut],
+  Dan Tenenbaum [ctb]
+Maintainer: Rich Calaway <richcala at microsoft.com>
+Repository: CRAN
+Repository/R-Forge/Project: doparallel
+Repository/R-Forge/Revision: 15
+Repository/R-Forge/DateTimeStamp: 2015-10-13 20:31:22
+Date/Publication: 2015-10-14 09:53:49
+NeedsCompilation: no
+Packaged: 2015-10-13 20:46:30 UTC; rforge
diff --git a/MD5 b/MD5
new file mode 100644
index 0000000..78557e9
--- /dev/null
+++ b/MD5
@@ -0,0 +1,18 @@
+685f76c9510b8d41b6a311a2896888e3 *DESCRIPTION
+16c1196e34ef2f64277123d8d53442f5 *NAMESPACE
+d98f2f0bd408746894779f617982fdbe *NEWS
+614375f4652288a8c2ed615b3a53f188 *R/doParallel.R
+86f0e4745e79399332a21f661de57bbb *R/zzz.R
+c9d9d7e1319bf838125f1f9b53dc16a0 *build/vignette.rds
+ad6e7aeda54fa895a60fd8c0c92a39bf *demo/00Index
+acd97a961dc67743d9ae85b28aa8fec1 *demo/sincParallel.R
+d1d107a8aed2c92fe6efa71cbc691831 *inst/doc/gettingstartedParallel.R
+bf3cfed8a81605cf697c7e1e95bd856c *inst/doc/gettingstartedParallel.Rnw
+2510d1587aecb5c9aaaee0110320bc4d *inst/doc/gettingstartedParallel.pdf
+0a17c88eb4ddb5c75a71bd940627f1b1 *inst/examples/bootParallel.R
+f2621d4a791a20471698dfe4ceb351eb *inst/unitTests/options.R
+59ecbac80339ba8a55adc7ec51ced837 *inst/unitTests/runTestSuite.sh
+127e4697324d014bdf67e3e3c9ddf80f *man/doParallel-package.Rd
+8f2ff4e8944398c34a7add4667cec738 *man/registerDoParallel.Rd
+8a0378f6fce59830532f2880723693f0 *tests/doRUnit.R
+bf3cfed8a81605cf697c7e1e95bd856c *vignettes/gettingstartedParallel.Rnw
diff --git a/NAMESPACE b/NAMESPACE
new file mode 100644
index 0000000..fc2a413
--- /dev/null
+++ b/NAMESPACE
@@ -0,0 +1,7 @@
+export(registerDoParallel)
+export(stopImplicitCluster)
+importFrom("utils", "packageDescription", "packageName")
+import(foreach)
+import(iterators)
+import(parallel)
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..11dd16d
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,32 @@
+NEWS/ChangeLog for doParallel
+-----------------------------
+1.0.9  2015-09-21
+    o  Bug fixes to stopImplicitCluster functionality, courtesy of Dan Tenenbaum.
+	
+1.0.8  2014-02-25
+    o  Modified vignette to use no more than two workers.
+    
+1.0.7  2014-02-01
+    o  Modified to work better when a foreach loop is executed 
+       in a package (courtesy of Steve Weston)
+    o  Added unit tests and a minimal working example
+
+1.0.6  2013-10-25
+    o  Changed foreach, iterators, and parallel from Depends to
+	   Imports (request of Steve Weston and Stefan Schlager)
+	   
+1.0.4  2013-09-01
+    o  New attachExportEnv option for doParallelSNOW
+    o  New function stopImplicitCluster to stop the implicitly created 
+       socket cluster.
+    o  Updated inst/unitTests/runTestSuite.sh, bug report from Michael Cheng
+
+1.0.3  2013-06-06
+    o  New preschedule option for doParallelSNOW, courtesy of Steve Weston
+    o  Removed assignment into global environment to meet CRAN standards.
+
+1.0.2  2013-05-29
+    o  Efficiency improvements courtesy of Steve Weston
+
+1.0.1  2012-04-09
+    o  Updated to support RevoScaleR's rxExec function
diff --git a/R/doParallel.R b/R/doParallel.R
new file mode 100644
index 0000000..0ea51cd
--- /dev/null
+++ b/R/doParallel.R
@@ -0,0 +1,515 @@
+#
+# Copyright (c) 2008-2010, Revolution Analytics
+#
+# This program is free software; you can redistribute it and/or modify 
+# it under the terms of the GNU General Public License (version 2) as 
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, 
+# but WITHOUT ANY WARRANTY; without even the implied warranty of 
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
+# General Public License for more details.
+#
+# A copy of the GNU General Public License is available at
+# http://www.r-project.org/Licenses/
+#
+
+.options <- new.env(parent=emptyenv())
+.revoDoParCluster <- NULL
+
+# this explicitly registers a multicore parallel backend
+registerDoParallel <- function(cl, cores=NULL, ...) {
+  opts <- list(...)
+  optnames <- names(opts)
+  if (is.null(optnames))
+    optnames <- rep('', length(opts))
+
+  # filter out unnamed arguments with a warning
+  unnamed <- ! nzchar(optnames)
+  if (any(unnamed)) {
+    warning('ignoring doParallel package option(s) specified with unnamed argument')
+    opts <- opts[!unnamed]
+    optnames <- optnames[!unnamed]
+  }
+
+  # filter out unrecognized options with a warning
+  recog <- optnames %in% c('nocompile')
+  if (any(!recog)) {
+    warning(sprintf('ignoring unrecognized doParallel package option(s): %s',
+	  			  paste(optnames[!recog], collapse=', ')), call.=FALSE)
+    opts <- opts[recog]
+    optnames <- optnames[recog]
+  }
+
+  # clear .options in case registerDoParallel is called multiple times
+  old.optnames <- ls(.options, all.names=TRUE)
+  rm(list=old.optnames, pos=.options)
+
+  # set new options
+  for (i in seq(along=opts)) {
+    assign(optnames[i], opts[[i]], pos=.options)
+  }
+
+  if (missing(cl) || is.numeric(cl)) {
+    if (.Platform$OS.type == "windows") {
+	  if (!missing(cl) && is.numeric(cl)) {
+            cl <- makeCluster(cl)
+	  } else {
+        if (!missing(cores) && is.numeric(cores)){
+            cl <- makeCluster(cores)
+        } else {
+            cl <- makeCluster(3)
+        }
+	  }
+	  assign(".revoDoParCluster", cl, pos=.options)
+	  reg.finalizer(.options, function(e){
+	      stopImplicitCluster()
+		}, onexit = TRUE)
+	  setDoPar(doParallelSNOW, cl, snowinfo)
+    } else {
+      if (!missing(cl) && is.numeric(cl)) {
+        cores <- cl
+      }
+      # register multicore backend
+      setDoPar(doParallelMC, cores, mcinfo) 
+    }
+  } else {
+    setDoPar(doParallelSNOW, cl, snowinfo)
+  }
+}
+
+"stopImplicitCluster" <- function()
+{
+    if (exists(".revoDoParCluster", where=.options) && !is.null(.options[['.revoDoParCluster']])) {
+        stopCluster(.options[['.revoDoParCluster']])
+        remove(".revoDoParCluster", envir=.options)
+    }
+}
+
+# internal function that determines the number of workers to use
+workers <- function(data) {
+  if ("cluster" %in% class(data)) {
+    length(data)
+  } else {
+    cores <- data
+    if (!is.null(cores)) {
+      # use the number specified when registering doMC
+      cores
+    } else {
+      cores <- getOption('cores')
+      if (!is.null(cores)) {
+        # use the number specified via the 'cores' option
+        cores
+      } else {
+        # use 1/2 the number detected by parallel 
+		cores <- parallel::detectCores()
+		if (cores > 2) {
+		  cores <- ceiling(cores/2)
+		}
+		cores
+	  }
+	}
+  }
+}
+
+# passed to setDoPar via registerDoParallel, and called by getDoParWorkers, etc
+mcinfo <- function(data, item) {
+  switch(item,
+         workers=workers(data),
+         name='doParallelMC',
+         version=packageDescription('doParallel', fields='Version'),
+         NULL)
+}
+
+# passed to setDoPar via registerDoParallel, and called by getDoParWorkers, etc
+snowinfo <- function(data, item) {
+  switch(item,
+         workers=workers(data),
+         name='doParallelSNOW',
+         version=packageDescription('doParallel', fields='Version'),
+         NULL)
+}
+
+comp <- if (getRversion() < "2.13.0") {
+  function(expr, ...) expr
+} else {
+  function(expr, ...) {
+    if (isTRUE(.options$nocompile))
+      expr
+    else
+      compiler::compile(expr, ...)
+  }
+}
+
+
+parSpl <- try(parallel::splitList, silent=TRUE)
+## Use the "splitList" function from parallel if it's exported
+## Otherwise, use the definition it had in R 3.0.2.
+"splitList" <- if (inherits(parSpl, "try-error")) {
+    function (x, ncl) 
+	lapply(splitIndices(length(x), ncl), function(i) x[i])
+} else {
+	parSpl
+}
+
+doParallelMC <- function(obj, expr, envir, data) {
+  # set the default mclapply options
+  preschedule <- TRUE
+  set.seed <- TRUE
+  silent <- FALSE
+  cores <- workers(data)
+
+  if (!inherits(obj, 'foreach'))
+    stop('obj must be a foreach object')
+
+  it <- iter(obj)
+  argsList <- as.list(it)
+  accumulator <- makeAccum(it)
+
+  # make sure all of the necessary libraries have been loaded
+  for (p in obj$packages)
+    library(p, character.only=TRUE)
+
+  # check for multicore-specific options
+  options <- obj$options$multicore
+  if (!is.null(options)) {
+    nms <- names(options)
+    recog <- nms %in% c('preschedule', 'set.seed', 'silent', 'cores')
+    if (any(!recog))
+      warning(sprintf('ignoring unrecognized multicore option(s): %s',
+                      paste(nms[!recog], collapse=', ')), call.=FALSE)
+
+    if (!is.null(options$preschedule)) {
+      if (!is.logical(options$preschedule) || length(options$preschedule) != 1) {
+        warning('preschedule must be logical value', call.=FALSE)
+      } else {
+        if (obj$verbose)
+          cat(sprintf('setting mc.preschedule option to %d\n', options$preschedule))
+        preschedule <- options$preschedule
+      }
+    }
+
+    if (!is.null(options$set.seed)) {
+      if (!is.logical(options$set.seed) || length(options$set.seed) != 1) {
+        warning('set.seed must be logical value', call.=FALSE)
+      } else {
+        if (obj$verbose)
+          cat(sprintf('setting mc.set.seed option to %d\n', options$set.seed))
+        set.seed <- options$set.seed
+      }
+    }
+
+    if (!is.null(options$silent)) {
+      if (!is.logical(options$silent) || length(options$silent) != 1) {
+        warning('silent must be logical value', call.=FALSE)
+      } else {
+        if (obj$verbose)
+          cat(sprintf('setting mc.silent option to %d\n', options$silent))
+        silent <- options$silent
+      }
+    }
+
+    if (!is.null(options$cores)) {
+      if (!is.numeric(options$cores) || length(options$cores) != 1 ||
+          options$cores < 1) {
+        warning('cores must be numeric value >= 1', call.=FALSE)
+      } else {
+        if (obj$verbose)
+          cat(sprintf('setting mc.cores option to %d\n', options$cores))
+        cores <- options$cores
+      }
+    }
+  }
+
+  # define the "worker" function, compiling expr if possible
+  c.expr <- comp(expr, env=envir, options=list(suppressUndefined=TRUE))
+  FUN <- function(args) tryCatch(eval(c.expr, envir=args, enclos=envir),
+                                 error=function(e) e)
+
+  # execute the tasks
+  results <- mclapply(argsList, FUN, mc.preschedule=preschedule,
+                      mc.set.seed=set.seed, mc.silent=silent,
+                      mc.cores=cores)
+
+  # call the accumulator with all of the results
+  tryCatch(accumulator(results, seq(along=results)), error=function(e) {
+    cat('error calling combine function:\n')
+    print(e)
+    NULL
+  })
+
+  # check for errors
+  errorValue <- getErrorValue(it)
+  errorIndex <- getErrorIndex(it)
+
+  # throw an error or return the combined results
+  if (identical(obj$errorHandling, 'stop') && !is.null(errorValue)) {
+    msg <- sprintf('task %d failed - "%s"', errorIndex,
+                   conditionMessage(errorValue))
+    stop(simpleError(msg, call=expr))
+  } else {
+    getResult(it)
+  }
+}
+
+makeDotsEnv <- function(...) {
+  list(...)
+  function() NULL
+}
+
+.doSnowGlobals <- new.env(parent=emptyenv())
+
+getparentenv <- function(pkgname) {
+  parenv <- NULL
+
+  # if anything goes wrong, print the error object and return
+  # the global environment
+  tryCatch({
+    # pkgname is NULL in many cases, as when the foreach loop
+    # is executed interactively or in an R script
+    if (is.character(pkgname)) {
+      # load the specified package
+      if (require(pkgname, character.only=TRUE)) {
+        # search for any function in the package
+        pkgenv <- as.environment(paste0('package:', pkgname))
+        for (sym in ls(pkgenv)) {
+          fun <- get(sym, pkgenv, inherits=FALSE)
+          if (is.function(fun)) {
+            env <- environment(fun)
+            if (is.environment(env)) {
+              parenv <- env
+              break
+            }
+          }
+        }
+        if (is.null(parenv)) {
+          stop('loaded ', pkgname, ', but parent search failed', call.=FALSE)
+        } else {
+          message('loaded ', pkgname, ' and set parent environment')
+        }
+      }
+    }
+  },
+  error=function(e) {
+    cat(sprintf('Error getting parent environment: %s\n',
+                conditionMessage(e)))
+  })
+
+  # return the global environment by default
+  if (is.null(parenv)) globalenv() else parenv
+}
+
+workerInit <- function(expr, exportenv, pkgname, packages, attach=FALSE) {
+  assign('expr', expr, .doSnowGlobals)
+  assign('exportenv', exportenv, .doSnowGlobals)
+  exportEnv <- .doSnowGlobals$exportenv
+  parent.env(exportEnv) <- getparentenv(pkgname)
+  if (attach) {
+    attach(exportEnv)
+  }
+  
+  tryCatch({
+    for (p in packages)
+      library(p, character.only=TRUE)
+
+    NULL  # indicates success
+  },
+  error=function(e) {
+    # a character string indicates an error
+    conditionMessage(e)
+  })
+}
+workerCleanup <- function() {
+	if ("exportEnv" %in% search()) {
+		detach(exportEnv)
+	}
+}
+
+evalWrapper <- function(args) {
+  lapply(names(args), function(n) assign(n, args[[n]], pos=.doSnowGlobals$exportenv))
+  tryCatch(eval(.doSnowGlobals$expr, envir=.doSnowGlobals$exportenv), error=function(e) e)
+}
+
+# This function takes the place of workerInit and evalWrapper when
+# preschedule is enabled.  It is executed by the master via clusterApply
+# such that there is a single chunked task for each worker in the
+# cluster, rather than using clusterCall to initialize the workers and
+# clusterApplyLB to compute the tasks one-by-one.  This strategy can be
+# significantly more efficient when there are many small tasks, and is
+# very similar to the default behavior of mclapply.
+workerPreschedule <- function(largs, expr, exportenv, pkgname, packages) {
+  parent.env(exportenv) <- getparentenv(pkgname)
+  task <- function(args) {
+    lapply(names(args), function(n) assign(n, args[[n]], pos=exportenv))
+    eval(expr, envir=exportenv)
+  }
+
+  tryCatch({
+    # load all necessary packages
+    for (p in packages)
+      library(p, character.only=TRUE)
+
+    # execute all of the tasks
+    lapply(largs, task)
+  },
+  error=function(e) {
+    # only one exception was thrown, but we don't know which one,
+    # so we'll return it for all of the tasks
+    lapply(seq_along(largs), function(i) e)
+  })
+}
+
+doParallelSNOW <- function(obj, expr, envir, data) {
+  cl <- data
+  preschedule <- FALSE
+  attachExportEnv <- FALSE
+
+  if (!inherits(obj, 'foreach'))
+    stop('obj must be a foreach object')
+
+  it <- iter(obj)
+  accumulator <- makeAccum(it)
+
+  # check for snow-specific options
+  options <- obj$options$snow
+  if (!is.null(options)) {
+    nms <- names(options)
+    recog <- nms %in% c('preschedule', 'attachExportEnv')
+    if (any(!recog))
+      warning(sprintf('ignoring unrecognized snow option(s): %s',
+                      paste(nms[!recog], collapse=', ')), call.=FALSE)
+
+    if (!is.null(options$preschedule)) {
+      if (!is.logical(options$preschedule) ||
+          length(options$preschedule) != 1) {
+        warning('preschedule must be logical value', call.=FALSE)
+      } else {
+        if (obj$verbose)
+          cat(sprintf('bundling all tasks into %d chunks\n', length(cl)))
+        preschedule <- options$preschedule
+      }
+    }
+    if (!is.null(options$attachExportEnv)) {
+      if (!is.logical(options$attachExportEnv) ||
+          length(options$attachExportEnv) != 1) {
+        warning('attachExportEnv must be logical value', call.=FALSE)
+      } else {
+        if (obj$verbose)
+          cat("attaching export environment\n")
+        attachExportEnv <- options$attachExportEnv
+      }
+    }
+  }
+
+  # setup the parent environment by first attempting to create an environment
+  # that has '...' defined in it with the appropriate values
+  exportenv <- tryCatch({
+    qargs <- quote(list(...))
+    args <- eval(qargs, envir)
+    environment(do.call(makeDotsEnv, args))
+  },
+  error=function(e) {
+    new.env(parent=emptyenv())
+  })
+  noexport <- union(obj$noexport, obj$argnames)
+  getexports(expr, exportenv, envir, bad=noexport)
+  vars <- ls(exportenv)
+  if (obj$verbose) {
+    if (length(vars) > 0) {
+      cat('automatically exporting the following variables',
+          'from the local environment:\n')
+      cat(' ', paste(vars, collapse=', '), '\n')
+    } else {
+      cat('no variables are automatically exported\n')
+    }
+  }
+
+  # compute list of variables to export
+  export <- unique(obj$export)
+  ignore <- intersect(export, vars)
+  if (length(ignore) > 0) {
+    warning(sprintf('already exporting variable(s): %s',
+            paste(ignore, collapse=', ')))
+    export <- setdiff(export, ignore)
+  }
+
+  # add explicitly exported variables to exportenv
+  if (length(export) > 0) {
+    if (obj$verbose)
+      cat(sprintf('explicitly exporting variables(s): %s\n',
+                  paste(export, collapse=', ')))
+
+    for (sym in export) {
+      if (!exists(sym, envir, inherits=TRUE))
+        stop(sprintf('unable to find variable "%s"', sym))
+      val <- get(sym, envir, inherits=TRUE)
+      if (is.function(val) &&
+          (identical(environment(val), .GlobalEnv) ||
+           identical(environment(val), envir))) {
+        # Changing this function's environment to exportenv allows it to
+        # access/execute any other functions defined in exportenv.  This
+        # has always been done for auto-exported functions, and not
+        # doing so for explicitly exported functions results in
+        # functions defined in exportenv that can't call each other.
+        environment(val) <- exportenv
+      }
+      assign(sym, val, pos=exportenv, inherits=FALSE)
+    }
+  }
+
+  # send exports to workers
+  c.expr <- comp(expr, env=envir, options=list(suppressUndefined=TRUE))
+  
+   # packageName function added in R 3.0.0
+   pkgname <- if (exists('packageName', mode='function'))
+     packageName(envir)
+   else
+     NULL
+
+  if (! preschedule) {
+    # send exports to workers
+    r <- clusterCall(cl, workerInit, c.expr, exportenv, pkgname, 
+                     obj$packages, attachExportEnv)
+    for (emsg in r) {
+      if (!is.null(emsg))
+        stop('worker initialization failed: ', emsg)
+    }
+
+    # execute the tasks
+    argsList <- as.list(it)
+    results <- clusterApplyLB(cl, argsList, evalWrapper)
+	
+	# clean up the workers
+	if (attachExportEnv){
+	  clusterCall(cl, workerCleanup)
+	}
+  } else {
+    # convert argument iterator into a list of lists
+    argsList <- splitList(as.list(it), length(cl))
+
+    # execute the tasks
+    results <- do.call(c, clusterApply(cl, argsList, workerPreschedule,
+                                       c.expr, exportenv, pkgname, 
+                                       obj$packages))
+  }
+
+
+  # call the accumulator with all of the results
+  tryCatch(accumulator(results, seq(along=results)), error=function(e) {
+    cat('error calling combine function:\n')
+    print(e)
+  })
+
+  # check for errors
+  errorValue <- getErrorValue(it)
+  errorIndex <- getErrorIndex(it)
+
+  # throw an error or return the combined results
+  if (identical(obj$errorHandling, 'stop') && !is.null(errorValue)) {
+    msg <- sprintf('task %d failed - "%s"', errorIndex,
+                   conditionMessage(errorValue))
+    stop(simpleError(msg, call=expr))
+  } else {
+    getResult(it)
+  }
+}
diff --git a/R/zzz.R b/R/zzz.R
new file mode 100644
index 0000000..898c9c7
--- /dev/null
+++ b/R/zzz.R
@@ -0,0 +1,3 @@
+".onUnload" <- function(libpath) {
+	stopImplicitCluster()
+}
diff --git a/build/vignette.rds b/build/vignette.rds
new file mode 100644
index 0000000..9ffb58e
Binary files /dev/null and b/build/vignette.rds differ
diff --git a/debian/README.test b/debian/README.test
deleted file mode 100644
index 55a9142..0000000
--- a/debian/README.test
+++ /dev/null
@@ -1,8 +0,0 @@
-Notes on how this package can be tested.
-────────────────────────────────────────
-
-To run the unit tests provided by the package you can do
-
-   sh  run-unit-test
-
-in this directory.
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index d00174e..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,25 +0,0 @@
-r-cran-doparallel (1.0.10-3) unstable; urgency=medium
-
-  * Test-Depends and Suggests: r-cran-caret, r-cran-mlbench, r-cran-rpart
-
- -- Andreas Tille <tille at debian.org>  Thu, 23 Jun 2016 08:29:43 +0200
-
-r-cran-doparallel (1.0.10-2) unstable; urgency=medium
-
-  * Fix autopkgtest (Thanks to Gordon Ball)
-
- -- Andreas Tille <tille at debian.org>  Wed, 08 Jun 2016 15:17:30 +0200
-
-r-cran-doparallel (1.0.10-1) unstable; urgency=medium
-
-  * New upstream version
-  * cme fix dpkg-control
-  * fix unit autopkgtest
-
- -- Andreas Tille <tille at debian.org>  Tue, 03 May 2016 22:33:20 +0200
-
-r-cran-doparallel (1.0.8-1) unstable; urgency=low
-
-  * Initial release (closes: #753293)
-
- -- Andreas Tille <tille at debian.org>  Mon, 30 Jun 2014 11:47:43 +0200
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index ec63514..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-9
diff --git a/debian/control b/debian/control
deleted file mode 100644
index da80250..0000000
--- a/debian/control
+++ /dev/null
@@ -1,27 +0,0 @@
-Source: r-cran-doparallel
-Maintainer: Debian Med Packaging Team <debian-med-packaging at lists.alioth.debian.org>
-Uploaders: Andreas Tille <tille at debian.org>
-Section: gnu-r
-Testsuite: autopkgtest
-Priority: optional
-Build-Depends: debhelper (>= 9),
-               cdbs,
-               r-base-dev,
-               r-cran-iterators,
-               r-cran-foreach
-Standards-Version: 3.9.8
-Vcs-Browser: https://anonscm.debian.org/viewvc/debian-med/trunk/packages/R/r-cran-doparallel/trunk/
-Vcs-Svn: svn://anonscm.debian.org/debian-med/trunk/packages/R/r-cran-doparallel/trunk/
-Homepage: http://cran.r-project.org/web/packages/doParallel
-
-Package: r-cran-doparallel
-Architecture: any
-Depends: ${shlibs:Depends},
-         ${misc:Depends},
-         ${R:Depends},
-         r-cran-iterators,
-         r-cran-foreach
-Suggests: r-cran-caret, r-cran-mlbench, r-cran-rpart
-Description: GNU R foreach parallel adaptor for the parallel package
- This GNU R package provides a parallel backend for the %dopar% function
- using the parallel package.
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index 7f83be8..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,29 +0,0 @@
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Name: doParallel
-Upstream-Contact: Revolution Analytics <packages at revolutionanalytics.com>
-Source: http://cran.r-project.org/web/packages/doParallel/
-
-Files: *
-Copyright: 2012-2014 Revolution Analytics, Steve Weston
-License: GPL-2
-
-Files: debian/*
-Copyright: 2014 Andreas Tille <tille at debian.org>
-License: GPL-2
-
-License: GPL-2
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 2 of the License.
- .
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
- .
- You should have received a copy of the GNU General Public License
- along with this program.  If not, see <http://www.gnu.org/licenses/>.
- .
- On Debian systems, the complete text of the GNU General Public
- License can be found in `/usr/share/common-licenses/GPL-2'.
-
diff --git a/debian/docs b/debian/docs
deleted file mode 100644
index 3adf0d6..0000000
--- a/debian/docs
+++ /dev/null
@@ -1,3 +0,0 @@
-debian/README.test
-debian/tests/run-unit-test
-tests
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index e762fc2..0000000
--- a/debian/patches/series
+++ /dev/null
@@ -1 +0,0 @@
-unittest-no-report.patch
diff --git a/debian/patches/unittest-no-report.patch b/debian/patches/unittest-no-report.patch
deleted file mode 100644
index 699967e..0000000
--- a/debian/patches/unittest-no-report.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-Description: don't write a test summary in a read-only directory
-Author: Gordon Ball <gordon at chronitis.net>
-
---- a/tests/doRUnit.R
-+++ b/tests/doRUnit.R
-@@ -48,14 +48,6 @@
-   ## Report to stdout and text files
-   cat("------------------- UNIT TEST SUMMARY ---------------------\n\n")
-   printTextProtocol(tests, showDetails=FALSE)
--  printTextProtocol(tests, showDetails=FALSE,
--                    fileName=paste(pathReport, "Summary.txt", sep=""))
--  printTextProtocol(tests, showDetails=TRUE,
--                    fileName=paste(pathReport, ".txt", sep=""))
-- 
--  ## Report to HTML file
--  printHTMLProtocol(tests, fileName=paste(pathReport, ".html", sep=""))
--#  printHTMLProtocol(tests, fileName=file.path(dirname(dirname(getwd())),pkg,"gsDesign-RUnit-Test-Summary.html")) #paste(pathReport, ".html", sep=""))  
-  
-   ## Return stop() to cause R CMD check stop in case of
-   ##  - failures i.e. FALSE to unit tests or
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index a9fa538..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/make -f
-
-include /usr/share/R/debian/r-cran.mk
-
-install/$(package)::
-	chmod +x debian/$(package)/usr/lib/R/site-library/$(cranNameOrig)/unitTests/runTestSuite.sh
diff --git a/debian/source/format b/debian/source/format
deleted file mode 100644
index 163aaf8..0000000
--- a/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (quilt)
diff --git a/debian/tests/control b/debian/tests/control
deleted file mode 100644
index 9da42b6..0000000
--- a/debian/tests/control
+++ /dev/null
@@ -1,3 +0,0 @@
-Tests: run-unit-test
-Depends: @, r-cran-runit, r-cran-caret, r-cran-mlbench, r-cran-rpart
-Restrictions: allow-stderr
diff --git a/debian/tests/run-unit-test b/debian/tests/run-unit-test
deleted file mode 100644
index ae6d6bb..0000000
--- a/debian/tests/run-unit-test
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh -e
-
-pkg=r-cran-doparallel
-if [ "$ADTTMP" = "" ] ; then
-  ADTTMP=`mktemp -d /tmp/${pkg}-test.XXXXXX`
-fi
-cd $ADTTMP
-cp -a /usr/share/doc/${pkg}/tests/* $ADTTMP
-R --no-save < doRUnit.R
-rm -f $ADTTMP/*
diff --git a/debian/watch b/debian/watch
deleted file mode 100644
index e794a1f..0000000
--- a/debian/watch
+++ /dev/null
@@ -1,2 +0,0 @@
-version=3
-http://cran.r-project.org/src/contrib/doParallel_([-\d.]*)\.tar\.gz
diff --git a/demo/00Index b/demo/00Index
new file mode 100644
index 0000000..8489066
--- /dev/null
+++ b/demo/00Index
@@ -0,0 +1 @@
+sincParallel         computation of the sinc function
diff --git a/demo/sincParallel.R b/demo/sincParallel.R
new file mode 100644
index 0000000..d51eabc
--- /dev/null
+++ b/demo/sincParallel.R
@@ -0,0 +1,37 @@
+library(doParallel)
+registerDoParallel()
+
+# Define a function that creates an iterator that returns subvectors
+ivector <- function(x, chunks) {
+  n <- length(x)
+  i <- 1
+
+  nextEl <- function() {
+    if (chunks <= 0 || n <= 0) stop('StopIteration')
+    m <- ceiling(n / chunks)
+    r <- seq(i, length=m)
+    i <<- i + m
+    n <<- n - m
+    chunks <<- chunks - 1
+    x[r]
+  }
+
+  obj <- list(nextElem=nextEl)
+  class(obj) <- c('abstractiter', 'iter')
+  obj
+}
+
+# Define the coordinate grid and figure out how to split up the work
+x <- seq(-10, 10, by=0.1)
+nw <- getDoParWorkers()
+cat(sprintf('Running with %d worker(s)\n', nw))
+
+# Compute the value of the sinc function at each point in the grid
+z <- foreach(y=ivector(x, nw), .combine=cbind) %dopar% {
+  y <- rep(y, each=length(x))
+  r <- sqrt(x ^ 2 + y ^ 2)
+  matrix(10 * sin(r) / r, length(x))
+}
+
+# Plot the results as a perspective plot
+persp(x, x, z, ylab='y', theta=30, phi=30, expand=0.5, col="lightblue")
diff --git a/inst/doc/gettingstartedParallel.R b/inst/doc/gettingstartedParallel.R
new file mode 100644
index 0000000..2410e01
--- /dev/null
+++ b/inst/doc/gettingstartedParallel.R
@@ -0,0 +1,73 @@
+### R code from vignette source 'gettingstartedParallel.Rnw'
+
+###################################################
+### code chunk number 1: loadLibs
+###################################################
+library(doParallel)
+cl <- makeCluster(2)
+registerDoParallel(cl)
+foreach(i=1:3) %dopar% sqrt(i)
+
+
+###################################################
+### code chunk number 2: gettingstartedParallel.Rnw:149-150
+###################################################
+stopCluster(cl)
+
+
+###################################################
+### code chunk number 3: gettingstartedParallel.Rnw:193-196
+###################################################
+library(doParallel)
+cl <- makeCluster(2)
+registerDoParallel(cl)
+
+
+###################################################
+### code chunk number 4: bootpar
+###################################################
+x <- iris[which(iris[,5] != "setosa"), c(1,5)]
+trials <- 10000
+
+ptime <- system.time({
+  r <- foreach(icount(trials), .combine=cbind) %dopar% {
+    ind <- sample(100, 100, replace=TRUE)
+    result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))
+    coefficients(result1)
+  }
+})[3]
+ptime
+
+
+###################################################
+### code chunk number 5: bootseq
+###################################################
+stime <- system.time({
+  r <- foreach(icount(trials), .combine=cbind) %do% {
+    ind <- sample(100, 100, replace=TRUE)
+    result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))
+    coefficients(result1)
+  }
+})[3]
+stime
+
+
+###################################################
+### code chunk number 6: getDoParWorkers
+###################################################
+getDoParWorkers()
+
+
+###################################################
+### code chunk number 7: getDoParName
+###################################################
+getDoParName()
+getDoParVersion()
+
+
+###################################################
+### code chunk number 8: gettingstartedParallel.Rnw:274-275
+###################################################
+stopCluster(cl)
+
+
diff --git a/inst/doc/gettingstartedParallel.Rnw b/inst/doc/gettingstartedParallel.Rnw
new file mode 100644
index 0000000..c169735
--- /dev/null
+++ b/inst/doc/gettingstartedParallel.Rnw
@@ -0,0 +1,344 @@
+% \VignetteIndexEntry{Getting Started with doParallel and foreach}
+% \VignetteDepends{doParallel}
+% \VignetteDepends{foreach}
+% \VignettePackage{doParallel}
+\documentclass[12pt]{article}
+\usepackage{amsmath}
+\usepackage[pdftex]{graphicx}
+\usepackage{color}
+\usepackage{xspace}
+\usepackage{url}
+\usepackage{fancyvrb}
+\usepackage{fancyhdr}
+    \usepackage[
+         colorlinks=true,
+         linkcolor=blue,
+         citecolor=blue,
+         urlcolor=blue]
+         {hyperref}
+         \usepackage{lscape}
+
+\usepackage{Sweave}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% define new colors for use
+\definecolor{darkgreen}{rgb}{0,0.6,0}
+\definecolor{darkred}{rgb}{0.6,0.0,0}
+\definecolor{lightbrown}{rgb}{1,0.9,0.8}
+\definecolor{brown}{rgb}{0.6,0.3,0.3}
+\definecolor{darkblue}{rgb}{0,0,0.8}
+\definecolor{darkmagenta}{rgb}{0.5,0,0.5}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\newcommand{\bld}[1]{\mbox{\boldmath $#1$}}
+\newcommand{\shell}[1]{\mbox{$#1$}}
+\renewcommand{\vec}[1]{\mbox{\bf {#1}}}
+
+\newcommand{\ReallySmallSpacing}{\renewcommand{\baselinestretch}{.6}\Large\normalsize}
+\newcommand{\SmallSpacing}{\renewcommand{\baselinestretch}{1.1}\Large\normalsize}
+
+\newcommand{\halfs}{\frac{1}{2}}
+
+\setlength{\oddsidemargin}{-.25 truein}
+\setlength{\evensidemargin}{0truein}
+\setlength{\topmargin}{-0.2truein}
+\setlength{\textwidth}{7 truein}
+\setlength{\textheight}{8.5 truein}
+\setlength{\parindent}{0.20truein}
+\setlength{\parskip}{0.10truein}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\pagestyle{fancy}
+\lhead{}
+\chead{Getting Started with doParallel and foreach}
+\rhead{}
+\lfoot{}
+\cfoot{}
+\rfoot{\thepage}
+\renewcommand{\headrulewidth}{1pt}
+\renewcommand{\footrulewidth}{1pt}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\title{Getting Started with doParallel and foreach}
+\author{Steve Weston\footnote{Steve Weston wrote the original version of this vignette for the doMC package. Rich Calaway
+adapted the vignette for doParallel.} and Rich Calaway \\ doc at revolutionanalytics.com}
+
+
+\begin{document}
+
+\maketitle
+
+\thispagestyle{empty}
+
+\section{Introduction}
+
+The \texttt{doParallel} package is a ``parallel backend'' for the
+\texttt{foreach} package.  It provides a mechanism needed to execute
+\texttt{foreach} loops in parallel.  The \texttt{foreach} package must
+be used in conjunction with a package such as \texttt{doParallel} in order to
+execute code in parallel.  The user must register a parallel backend to
+use, otherwise \texttt{foreach} will execute tasks sequentially, even
+when the \%dopar\% operator is used.\footnote{\texttt{foreach} will
+issue a warning that it is running sequentially if no parallel backend
+has been registered.  It will only issue this warning once, however.}
+
+The \texttt{doParallel} package acts as an interface between \texttt{foreach}
+and the \texttt{parallel} package of R 2.14.0 and later. The \texttt{parallel}
+package is essentially a merger of the \texttt{multicore} package, which was 
+written by Simon Urbanek, and the \texttt{snow} package, which was written
+by Luke Tierney and others. The \texttt{multicore} functionality supports
+multiple workers only on those operating systems that
+support the \texttt{fork} system call; this excludes Windows. By default,
+\texttt{doParallel} uses \texttt{multicore} functionality on Unix-like
+systems and \texttt{snow} functionality on Windows.  Note that
+the \texttt{multicore} functionality only runs tasks on a single
+computer, not a cluster of computers. However, you can use the
+\texttt{snow} functionality to execute on a cluster, using Unix-like
+operating systems, Windows, or even a combination.
+It is pointless to use \texttt{doParallel} and \texttt{parallel}
+on a machine with only one processor with a single core.  To get a speed
+improvement, it must run on a machine with multiple processors, multiple
+cores, or both.
+
+\section{A word of caution}
+
+Because the \texttt{parallel} package in \texttt{multicore} mode 
+starts its workers using
+\texttt{fork} without doing a subsequent \texttt{exec}, it has some
+limitations.  Some operations cannot be performed properly by forked
+processes.  For example, connection objects very likely won't work.
+In some cases, this could cause an object to become corrupted, and
+the R session to crash.
+
+\section{Registering the \texttt{doParallel} parallel backend}
+
+To register \texttt{doParallel} to be used with \texttt{foreach}, you must
+call the \texttt{registerDoParallel} function.  If you call this with no
+arguments, on Windows you will get three workers and on Unix-like
+systems you will get a number of workers equal to approximately half the
+number of cores on your system. You can also specify a cluster
+(as created by the \texttt{makeCluster} function) or a number of cores. 
+The \texttt{cores} argument specifies the number of worker
+processes that \texttt{doParallel} will use to execute tasks, which will 
+by default be
+equal to one-half the total number of cores on the machine.  You don't need to
+specify a value for it, however.  By default, \texttt{doParallel} will use the 
+value of the ``cores'' option, as specified with
+the standard ``options'' function.  If that isn't set, then
+\texttt{doParallel} will try to detect the number of cores, and use one-half
+that many workers.
+
+Remember: unless \texttt{registerDoMC} is called, \texttt{foreach} will
+{\em not} run in parallel.  Simply loading the \texttt{doParallel} package is
+not enough.
+
+\section{An example \texttt{doParallel} session}
+
+Before we go any further, let's load \texttt{doParallel}, register it, and use
+it with \texttt{foreach}. We will use \texttt{snow}-like functionality in this 
+vignette, so we start by loading the package and starting a cluster:
+
+<<loadLibs>>=
+library(doParallel)
+cl <- makeCluster(2)
+registerDoParallel(cl)
+foreach(i=1:3) %dopar% sqrt(i)
+@
+<<echo=FALSE>>=
+stopCluster(cl)
+@
+
+To use \texttt{multicore}-like functionality, we would specify the number
+of cores to use instead (but note that on Windows, attempting to use more
+than one core with \texttt{parallel} results in an error):
+\begin{verbatim}
+library(doParallel}
+registerDoParallel(cores=2)
+foreach(i=1:3) %dopar% sqrt(i)
+\end{verbatim}
+
+\begin{quote}
+Note well that this is {\em not} a practical use of \texttt{doParallel}.  This
+is our ``Hello, world'' program for parallel computing.  It tests that
+everything is installed and set up properly, but don't expect it to run
+faster than a sequential \texttt{for} loop, because it won't!
+\texttt{sqrt} executes far too quickly to be worth executing in
+parallel, even with a large number of iterations.  With small tasks, the
+overhead of scheduling the task and returning the result can be greater
+than the time to execute the task itself, resulting in poor performance.
+In addition, this example doesn't make use of the vector capabilities of
+\texttt{sqrt}, which it must to get decent performance.  This is just a
+test and a pedagogical example, {\em not} a benchmark.
+\end{quote}
+
+But returning to the point of this example, you can see that it is very
+simple to load \texttt{doParallel} with all of its dependencies
+(\texttt{foreach}, \texttt{iterators}, \texttt{parallel}, etc), and to
+register it.  For the rest of the R session, whenever you execute
+\texttt{foreach} with \texttt{\%dopar\%}, the tasks will be executed
+using \texttt{doParallel} and \texttt{parallel}.  Note that you can register
+a different parallel backend later, or deregister \texttt{doParallel} by
+registering the sequential backend by calling the \texttt{registerDoSEQ}
+function.
+
+\section{A more serious example}
+
+Now that we've gotten our feet wet, let's do something a bit less
+trivial.  One good example is bootstrapping.  Let's see how long it
+takes to run 10,000 bootstrap iterations in parallel on
+\Sexpr{getDoParWorkers()} cores:
+
+<<echo=FALSE>>=
+library(doParallel)
+cl <- makeCluster(2)
+registerDoParallel(cl)
+@
+<<bootpar>>=
+x <- iris[which(iris[,5] != "setosa"), c(1,5)]
+trials <- 10000
+
+ptime <- system.time({
+  r <- foreach(icount(trials), .combine=cbind) %dopar% {
+    ind <- sample(100, 100, replace=TRUE)
+    result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))
+    coefficients(result1)
+  }
+})[3]
+ptime
+@
+
+Using \texttt{doParallel} and \texttt{parallel} we were able to perform
+10,000 bootstrap iterations in \Sexpr{ptime} seconds on
+\Sexpr{getDoParWorkers()} cores.  By changing the \texttt{\%dopar\%} to
+\texttt{\%do\%}, we can run the same code sequentially to determine the
+performance improvement:
+
+<<bootseq>>=
+stime <- system.time({
+  r <- foreach(icount(trials), .combine=cbind) %do% {
+    ind <- sample(100, 100, replace=TRUE)
+    result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))
+    coefficients(result1)
+  }
+})[3]
+stime
+@
+
+
+The sequential version ran in \Sexpr{stime} seconds, which means the
+speed up is about \Sexpr{round(stime / ptime, digits=1)} on
+\Sexpr{getDoParWorkers()} workers.\footnote{If you build this vignette
+yourself, you can see how well this problem runs on your hardware.  None
+of the times are hardcoded in this document.  You can also run the same
+example which is in the examples directory of the \texttt{doParallel}
+distribution.} Ideally, the speed up would be \Sexpr{getDoParWorkers()},
+but no multicore CPUs are ideal, and neither are the operating systems
+and software that run on them.
+
+At any rate, this is a more realistic example that is worth executing in
+parallel.  We do not explain what it's doing or how it works
+here.  We just want to give you something more substantial than the
+\texttt{sqrt} example in case you want to run some benchmarks yourself.
+You can also run this example on a cluster by simply reregistering 
+with a cluster object that specifies the nodes to use. (See the
+\texttt{makeCluster} help file for more details.)
+
+\section{Getting information about the parallel backend}
+
+To find out how many workers \texttt{foreach} is going to use, you can
+use the \texttt{getDoParWorkers} function:
+
+<<getDoParWorkers>>=
+getDoParWorkers()
+@
+
+This is a useful sanity check that you're actually running in parallel.
+If you haven't registered a parallel backend, or if your machine only
+has one core, \texttt{getDoParWorkers} will return one.  In either case,
+don't expect a speed improvement.  \texttt{foreach} is clever, but it
+isn't magic.
+
+The \texttt{getDoParWorkers} function is also useful when you want the
+number of tasks to be equal to the number of workers.  You may want to
+pass this value to an iterator constructor, for example.
+
+You can also get the name and version of the currently registered
+backend:
+
+<<getDoParName>>=
+getDoParName()
+getDoParVersion()
+@
+<<echo=FALSE>>=
+stopCluster(cl)
+@
+This is mostly useful for documentation purposes, or for checking that
+you have the most recent version of \texttt{doParallel}.
+
+\section{Specifying multicore options}
+
+When using \texttt{multicore}-like functionality, the \texttt{doParallel} package allows 
+you to specify various options when
+running \texttt{foreach} that are supported by the underlying
+\texttt{mclapply} function: ``preschedule'', ``set.seed'', ``silent'',
+and ``cores''.  You can learn about these options from the
+\texttt{mclapply} man page.  They are set using the \texttt{foreach}
+\texttt{.options.multicore} argument.  Here's an example of how to do
+that:
+
+\begin{verbatim}
+mcoptions <- list(preschedule=FALSE, set.seed=FALSE)
+foreach(i=1:3, .options.multicore=mcoptions) %dopar% sqrt(i)
+\end{verbatim}
+
+The ``cores'' options allows you to temporarily override the number of
+workers to use for a single \texttt{foreach} operation.  This is more
+convenient than having to re-register \texttt{doParallel}.  Although if no
+value of ``cores'' was specified when \texttt{doParallel} was registered, you
+can also change this value dynamically using the \texttt{options}
+function:
+
+\begin{verbatim}
+options(cores=2)
+getDoParWorkers()
+options(cores=3)
+getDoParWorkers()
+\end{verbatim}
+
+If you did specify the number of cores when registering \texttt{doParallel},
+the ``cores'' option is ignored:
+
+\begin{verbatim}
+registerDoParallel(4)
+options(cores=2)
+getDoParWorkers()
+\end{verbatim}
+
+As you can see, there are a number of options for controlling the number
+of workers to use with \texttt{parallel}, but the default behaviour
+usually does what you want.
+
+\section{Stopping your cluster}
+
+If you are using \texttt{snow}-like functionality, you will want to stop your
+cluster when you are done using it. The \texttt{doParallel} package's 
+\texttt{.onUnload} function will do this automatically if the cluster was created
+automatically by \texttt{registerDoParallel}, but if you created the cluster manually
+you should stop it using the \texttt{stopCluster} function:
+
+\begin{verbatim}
+stopCluster(cl)
+\end{verbatim}
+
+\section{Conclusion}
+
+The \texttt{doParallel} and \texttt{parallel} packages provide a nice,
+efficient parallel programming platform for multiprocessor/multicore
+computers running operating systems such as Linux and Mac OS X.  It is
+very easy to install, and very easy to use.  In short order, an average
+R programmer can start executing parallel programs, without any previous
+experience in parallel computing.
+
+\end{document}
diff --git a/inst/doc/gettingstartedParallel.pdf b/inst/doc/gettingstartedParallel.pdf
new file mode 100644
index 0000000..58ae617
Binary files /dev/null and b/inst/doc/gettingstartedParallel.pdf differ
diff --git a/inst/examples/bootParallel.R b/inst/examples/bootParallel.R
new file mode 100644
index 0000000..45cd14e
--- /dev/null
+++ b/inst/examples/bootParallel.R
@@ -0,0 +1,83 @@
+suppressMessages(library(doParallel))
+cl <- makePSOCKcluster(4)
+registerDoParallel(cl)
+
+cat(sprintf('doParallel %s\n', packageVersion('doParallel')))
+junk <- matrix(0, 1000000, 8)
+cat(sprintf('Size of extra junk data: %d bytes\n', object.size(junk)))
+
+x <- iris[which(iris[,5] != "setosa"), c(1,5)]
+
+trials <- 10000
+
+ptime <- system.time({
+  r <- foreach(icount(trials), .combine=cbind,
+               .export='junk') %dopar% {
+    ind <- sample(100, 100, replace=TRUE)
+    result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))
+    coefficients(result1)
+  }
+})[3]
+cat(sprintf('parallel foreach:                    %6.1f sec\n', ptime))
+
+ptime2 <- system.time({
+  snowopts <- list(preschedule=TRUE)
+  r <- foreach(icount(trials), .combine=cbind,
+               .export='junk', .options.snow=snowopts) %dopar% {
+    ind <- sample(100, 100, replace=TRUE)
+    result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))
+    coefficients(result1)
+  }
+})[3]
+cat(sprintf('parallel foreach with prescheduling: %6.1f sec\n', ptime2))
+
+
+ptime3 <- system.time({
+  chunks <- getDoParWorkers()
+  r <- foreach(n=idiv(trials, chunks=chunks), .combine=cbind,
+               .export='junk') %dopar% {
+    y <- lapply(seq_len(n), function(i) {
+      ind <- sample(100, 100, replace=TRUE)
+      result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))
+      coefficients(result1)
+    })
+    do.call('cbind', y)
+  }
+})[3]
+cat(sprintf('chunked parallel foreach:            %6.1f sec\n', ptime3))
+
+ptime4 <- system.time({
+  mkworker <- function(x, junk) {
+    force(x)
+    force(junk)
+    function(i) {
+      ind <- sample(100, 100, replace=TRUE)
+      result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))
+      coefficients(result1)
+    }
+  }
+  y <- parLapply(cl, seq_len(trials), mkworker(x, junk))
+  r <- do.call('cbind', y)
+})[3]
+cat(sprintf('parLapply:                           %6.1f sec\n', ptime4))
+
+stime <- system.time({
+  y <- lapply(seq_len(trials), function(i) {
+    ind <- sample(100, 100, replace=TRUE)
+    result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))
+    coefficients(result1)
+  })
+  r <- do.call('cbind', y)
+})[3]
+cat(sprintf('sequential lapply:                   %6.1f sec\n', stime))
+
+stime2 <- system.time({
+  r <- foreach(icount(trials), .combine=cbind) %do% {
+    ind <- sample(100, 100, replace=TRUE)
+    result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))
+    coefficients(result1)
+  }
+})[3]
+cat(sprintf('sequential foreach:                  %6.1f sec\n', stime2))
+
+stopCluster(cl)
diff --git a/inst/unitTests/options.R b/inst/unitTests/options.R
new file mode 100644
index 0000000..f1865b3
--- /dev/null
+++ b/inst/unitTests/options.R
@@ -0,0 +1,84 @@
+test.preschedule <- function() {
+  x <- list(1:3, 1:9, 1:19)
+  cs <- 1:20
+  dpn <- getDoParName()
+
+  for (chunkSize in cs) {
+    ## preschedule is TRUE for MC by default and 
+    ## FALSE for SNOW, so we test by setting them otherwise
+    if (identical(dpn, "doParallelMC")) {
+      opts <- list(preschedule=FALSE)
+    } else {
+      opts <- list(preschedule=TRUE)
+    }
+    for (y in x) {
+      if (identical(dpn, "doParallelMC")) {
+        actual <- foreach(i=y, .options.multicore=opts) %dopar% i
+      }
+      else {
+        actual <- foreach(i=y, .options.snow=opts) %dopar% i
+      }
+      checkEquals(actual, as.list(y))
+      if (identical(dpn, "doParallelMC")) {
+        actual <- foreach(i=y, .combine="c", .options.multicore=opts) %dopar% i
+      }
+      else {
+        actual <- foreach(i=y, .combine="c", .options.snow=opts) %dopar% i
+      }
+      checkEquals(actual, y)
+    }
+  }
+}
+
+test.attach <- function() {
+    if (identical(getDoParName(), "doParallelMC")) {
+        return(TRUE)
+    } else {
+        myFun <- function(x){
+            myFun1(x+1)
+           }
+        myFun1 <- function(x){
+            2*x
+         }
+        testFun <- function(){
+                inRes1 <- checkTrue("exportEnv" %in% search())
+                if (!inRes1) {
+                    stop("Attaching exportEnv failed")
+                }
+                inRes2 <- checkTrue(exists("myFun1", where=2))
+                if (!inRes1) {
+                    stop("myFun1 not found in exportEnv")
+                }
+                myFun(1)
+               }
+        res <- suppressWarnings(foreach(i=1:4, .combine="c", .packages="RUnit", 
+                   .export="myFun1", .options.snow=list(attachExportEnv=TRUE)) %dopar%  testFun())
+
+        checkEquals(res, c(4,4, 4, 4))
+    }
+}
+
+pkgname.test.stress <- function() {
+    if (!require(caret, quietly=TRUE)) {
+        return(TRUE)
+    } else {
+        library(mlbench)
+        data(BostonHousing)
+
+        lmFit <- train(medv ~ . + rm:lstat,
+                       data = BostonHousing, 
+                       "lm")
+
+        library(rpart)
+        rpartFit <- train(medv ~ .,
+                          data = BostonHousing,
+                          "rpart",
+                          tuneLength = 9)
+    }
+}
+
+"test.pkgname.test.stress" <- function()
+{
+    res <- try(pkgname.test.stress())
+    checkTrue(!is(res, "try-error"), msg="pkgname stress test failed")    
+}
\ No newline at end of file
diff --git a/inst/unitTests/runTestSuite.sh b/inst/unitTests/runTestSuite.sh
new file mode 100644
index 0000000..5d2804f
--- /dev/null
+++ b/inst/unitTests/runTestSuite.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+LOGFILE=test.log
+
+R --vanilla --slave > ${LOGFILE} 2>&1 <<'EOF'
+library(doParallel)
+library(RUnit)
+
+verbose <- as.logical(Sys.getenv('FOREACH_VERBOSE', 'FALSE'))
+
+library(doParallel)
+registerDoParallel()
+
+options(warn=1)
+options(showWarnCalls=TRUE)
+
+cat('Starting test at', date(), '\n')
+cat(sprintf('doParallel version: %s\n', getDoParVersion()))
+cat(sprintf('Running with %d worker(s)\n', getDoParWorkers()))
+
+tests <- c('options.R')
+
+errcase <- list()
+for (f in tests) {
+  cat('\nRunning test file:', f, '\n')
+  t <- runTestFile(f)
+  e <- getErrors(t)
+  if (e$nErr + e$nFail > 0) {
+    errcase <- c(errcase, t)
+    print(t)
+  }
+}
+
+if (length(errcase) == 0) {
+  cat('*** Ran all tests successfully ***\n')
+} else {
+  cat('!!! Encountered', length(errcase), 'problems !!!\n')
+  for (t in errcase) {
+    print(t)
+  }
+}
+
+stopImplicitCluster()
+
+cat('Finished test at', date(), '\n')
+EOF
diff --git a/man/doParallel-package.Rd b/man/doParallel-package.Rd
new file mode 100644
index 0000000..e9aa4bf
--- /dev/null
+++ b/man/doParallel-package.Rd
@@ -0,0 +1,39 @@
+\name{doParallel-package}
+\alias{doParallel-package}
+\alias{doParallel}
+\docType{package}
+\title{
+The doParallel Package
+}
+\description{
+The doParallel package provides a parallel backend for the foreach/\%dopar\%
+function using the \code{parallel} package of R 2.14.0 and later.
+}
+\details{
+Further information is available in the following help topics:
+\tabular{ll}{
+\code{registerDoParallel} \tab register doParallel to be used by foreach/\%dopar\%\cr
+}
+
+To see a tutorial introduction to the doParallel package,
+use \code{vignette("gettingstartedParallel")}.  To see a tutorial
+introduction to the foreach package, use \code{vignette("foreach")}.
+
+To see a demo of doParallel computing the sinc function,
+use \code{demo(sincParallel)}.
+
+Some examples (in addition to those in the help pages) are included in
+the ``examples'' directory of the doParallel package.  To list the files in
+the examples directory,
+use \code{list.files(system.file("examples", package="doParallel"))}.
+To run the bootstrap example, use
+\code{source(system.file("examples", "bootParallel.R", package="doParallel"))}.
+This is a simple benchmark, executing both sequentally and in parallel.
+There are many more examples that come with the foreach package,
+which will work with the doParallel package if it is registered as the
+parallel backend.
+
+For a complete list of functions with individual help pages,
+use \code{library(help="doParallel")}.
+}
+\keyword{package}
diff --git a/man/registerDoParallel.Rd b/man/registerDoParallel.Rd
new file mode 100644
index 0000000..09e505c
--- /dev/null
+++ b/man/registerDoParallel.Rd
@@ -0,0 +1,59 @@
+\name{registerDoParallel}
+\alias{registerDoParallel}
+\alias{stopImplicitCluster}
+\title{registerDoParallel}
+\description{
+The \code{registerDoParallel} function is used to register the 
+parallel backend with the \code{foreach} package.
+}
+\usage{
+registerDoParallel(cl, cores=NULL, \dots)
+stopImplicitCluster()
+}
+\arguments{
+  \item{cl}{A cluster object as returned by \code{makeCluster}, or the number
+  of nodes to be created in the cluster. If not specified, on Windows a 
+  three worker cluster is created and used.}
+  \item{cores}{The number of cores to use for parallel execution. If not
+  specified, the number of cores is set to the value of 
+  \code{options("cores")}, if specified, or to one-half the number of cores detected
+  by the \code{parallel} package.}
+  \item{\dots}{Package options.  Currently, only the \code{nocompile} option
+  is supported.  If \code{nocompile} is set to \code{TRUE}, compiler
+  support is disabled.}
+}
+\details{
+The \code{parallel} package from R 2.14.0 and later provides functions for 
+parallel execution of R code on machines with multiple cores or processors 
+or multiple computers.  It is essentially a blend of the \code{snow} and 
+\code{multicore} packages. By default, the \code{doParallel} package uses 
+\code{snow}-like functionality.  The \code{snow}-like functionality
+should work fine on Unix-like systems, but the \code{multicore}-like 
+functionality is limited to a single sequential worker on Windows systems.
+On workstations with multiple cores running Unix-like operating systems, 
+the system \code{fork} call is used to spawn copies of the current process. 
+
+The \code{doParallel} backend supports both multicore and snow options passed
+through the \code{foreach} function. 
+The supported multicore options are \code{preschedule}, \code{set.seed},
+\code{silent}, and \code{cores}, which are analogous to the similarly named 
+arguments to \code{\link{mclapply}}, and are passed using the
+\code{.options.multicore} argument to \code{foreach}. The supported snow options are 
+\code{preschedule}, which like its multicore analog can be used to chunk the 
+tasks so that each worker gets a prescheduled chunk of tasks, and 
+\code{attachExportEnv}, which can be used to attach the export environment
+in certain cases where R's lexical scoping is unable to find a needed
+export. The snow options are passed to \code{foreach} using the \code{.options.snow}
+argument.
+
+The function \code{stopImplicitCluster} can be used in vignettes and other places
+where it is important to explicitly close the implicitly created cluster.
+}
+\examples{
+cl <- makePSOCKcluster(2)
+registerDoParallel(cl)
+m <- matrix(rnorm(9), 3, 3)
+foreach(i=1:nrow(m), .combine=rbind) %dopar%  (m[i,] / mean(m[i,]))
+stopCluster(cl)
+}
+\keyword{utilities}
diff --git a/tests/doRUnit.R b/tests/doRUnit.R
new file mode 100644
index 0000000..752cfa9
--- /dev/null
+++ b/tests/doRUnit.R
@@ -0,0 +1,70 @@
+## unit tests will not be done if RUnit is not available
+if(require("RUnit", quietly=TRUE)) {
+ 
+  ## --- Setup ---
+ 
+  pkg <- "doParallel" # <-- Change to package name!
+  
+  if(Sys.getenv("RCMDCHECK") == "FALSE") {
+    ## Path to unit tests for standalone running under Makefile (not R CMD check)
+    ## PKG/tests/../inst/unitTests
+    path <- file.path(getwd(), "..", "inst", "unitTests")
+  } else {
+    ## Path to unit tests for R CMD check
+    ## PKG.Rcheck/tests/../PKG/unitTests
+    path <- system.file(package=pkg, "unitTests")
+  }
+  cat("\nRunning unit tests\n")
+  print(list(pkg=pkg, getwd=getwd(), pathToUnitTests=path))
+ 
+  library(package=pkg, character.only=TRUE)
+  ################################################################
+  ## BEGIN PACKAGE SPECIFIC CONFIGURATION                        #
+  ################################################################
+  registerDoParallel(2)
+  ################################################################
+  ## END PACKAGE SPECIFIC CONFIGURATION                          #
+  ################################################################
+ 
+  ## If desired, load the name space to allow testing of private functions
+  ## if (is.element(pkg, loadedNamespaces()))
+  ##     attach(loadNamespace(pkg), name=paste("namespace", pkg, sep=":"), pos=3)
+  ##
+  ## or simply call PKG:::myPrivateFunction() in tests
+
+ 
+ 
+  ## --- Testing ---
+ 
+  ## Define tests
+  testSuite <- defineTestSuite(name=paste(pkg, "unit testing"),
+                                          dirs=path, testFileRegexp = "^options\\.R$")
+  ## Run
+  tests <- runTestSuite(testSuite)
+ 
+  ## Default report name
+  pathReport <- file.path(path, "report")
+ 
+  ## Report to stdout and text files
+  cat("------------------- UNIT TEST SUMMARY ---------------------\n\n")
+  printTextProtocol(tests, showDetails=FALSE)
+  printTextProtocol(tests, showDetails=FALSE,
+                    fileName=paste(pathReport, "Summary.txt", sep=""))
+  printTextProtocol(tests, showDetails=TRUE,
+                    fileName=paste(pathReport, ".txt", sep=""))
+ 
+  ## Report to HTML file
+  printHTMLProtocol(tests, fileName=paste(pathReport, ".html", sep=""))
+#  printHTMLProtocol(tests, fileName=file.path(dirname(dirname(getwd())),pkg,"gsDesign-RUnit-Test-Summary.html")) #paste(pathReport, ".html", sep=""))  
+ 
+  ## Return stop() to cause R CMD check stop in case of
+  ##  - failures i.e. FALSE to unit tests or
+  ##  - errors i.e. R errors
+  tmp <- getErrors(tests)
+  if(tmp$nFail > 0 | tmp$nErr > 0) {
+    stop(paste("\n\nunit testing failed (#test failures: ", tmp$nFail,
+               ", #R errors: ",  tmp$nErr, ")\n\n", sep=""))
+  }
+} else {
+  warning("cannot run unit tests -- package RUnit is not available")
+}
diff --git a/vignettes/gettingstartedParallel.Rnw b/vignettes/gettingstartedParallel.Rnw
new file mode 100644
index 0000000..c169735
--- /dev/null
+++ b/vignettes/gettingstartedParallel.Rnw
@@ -0,0 +1,344 @@
+% \VignetteIndexEntry{Getting Started with doParallel and foreach}
+% \VignetteDepends{doParallel}
+% \VignetteDepends{foreach}
+% \VignettePackage{doParallel}
+\documentclass[12pt]{article}
+\usepackage{amsmath}
+\usepackage[pdftex]{graphicx}
+\usepackage{color}
+\usepackage{xspace}
+\usepackage{url}
+\usepackage{fancyvrb}
+\usepackage{fancyhdr}
+    \usepackage[
+         colorlinks=true,
+         linkcolor=blue,
+         citecolor=blue,
+         urlcolor=blue]
+         {hyperref}
+         \usepackage{lscape}
+
+\usepackage{Sweave}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% define new colors for use
+\definecolor{darkgreen}{rgb}{0,0.6,0}
+\definecolor{darkred}{rgb}{0.6,0.0,0}
+\definecolor{lightbrown}{rgb}{1,0.9,0.8}
+\definecolor{brown}{rgb}{0.6,0.3,0.3}
+\definecolor{darkblue}{rgb}{0,0,0.8}
+\definecolor{darkmagenta}{rgb}{0.5,0,0.5}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\newcommand{\bld}[1]{\mbox{\boldmath $#1$}}
+\newcommand{\shell}[1]{\mbox{$#1$}}
+\renewcommand{\vec}[1]{\mbox{\bf {#1}}}
+
+\newcommand{\ReallySmallSpacing}{\renewcommand{\baselinestretch}{.6}\Large\normalsize}
+\newcommand{\SmallSpacing}{\renewcommand{\baselinestretch}{1.1}\Large\normalsize}
+
+\newcommand{\halfs}{\frac{1}{2}}
+
+\setlength{\oddsidemargin}{-.25 truein}
+\setlength{\evensidemargin}{0truein}
+\setlength{\topmargin}{-0.2truein}
+\setlength{\textwidth}{7 truein}
+\setlength{\textheight}{8.5 truein}
+\setlength{\parindent}{0.20truein}
+\setlength{\parskip}{0.10truein}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\pagestyle{fancy}
+\lhead{}
+\chead{Getting Started with doParallel and foreach}
+\rhead{}
+\lfoot{}
+\cfoot{}
+\rfoot{\thepage}
+\renewcommand{\headrulewidth}{1pt}
+\renewcommand{\footrulewidth}{1pt}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\title{Getting Started with doParallel and foreach}
+\author{Steve Weston\footnote{Steve Weston wrote the original version of this vignette for the doMC package. Rich Calaway
+adapted the vignette for doParallel.} and Rich Calaway \\ doc at revolutionanalytics.com}
+
+
+\begin{document}
+
+\maketitle
+
+\thispagestyle{empty}
+
+\section{Introduction}
+
+The \texttt{doParallel} package is a ``parallel backend'' for the
+\texttt{foreach} package.  It provides a mechanism needed to execute
+\texttt{foreach} loops in parallel.  The \texttt{foreach} package must
+be used in conjunction with a package such as \texttt{doParallel} in order to
+execute code in parallel.  The user must register a parallel backend to
+use, otherwise \texttt{foreach} will execute tasks sequentially, even
+when the \%dopar\% operator is used.\footnote{\texttt{foreach} will
+issue a warning that it is running sequentially if no parallel backend
+has been registered.  It will only issue this warning once, however.}
+
+The \texttt{doParallel} package acts as an interface between \texttt{foreach}
+and the \texttt{parallel} package of R 2.14.0 and later. The \texttt{parallel}
+package is essentially a merger of the \texttt{multicore} package, which was 
+written by Simon Urbanek, and the \texttt{snow} package, which was written
+by Luke Tierney and others. The \texttt{multicore} functionality supports
+multiple workers only on those operating systems that
+support the \texttt{fork} system call; this excludes Windows. By default,
+\texttt{doParallel} uses \texttt{multicore} functionality on Unix-like
+systems and \texttt{snow} functionality on Windows.  Note that
+the \texttt{multicore} functionality only runs tasks on a single
+computer, not a cluster of computers. However, you can use the
+\texttt{snow} functionality to execute on a cluster, using Unix-like
+operating systems, Windows, or even a combination.
+It is pointless to use \texttt{doParallel} and \texttt{parallel}
+on a machine with only one processor with a single core.  To get a speed
+improvement, it must run on a machine with multiple processors, multiple
+cores, or both.
+
+\section{A word of caution}
+
+Because the \texttt{parallel} package in \texttt{multicore} mode 
+starts its workers using
+\texttt{fork} without doing a subsequent \texttt{exec}, it has some
+limitations.  Some operations cannot be performed properly by forked
+processes.  For example, connection objects very likely won't work.
+In some cases, this could cause an object to become corrupted, and
+the R session to crash.
+
+\section{Registering the \texttt{doParallel} parallel backend}
+
+To register \texttt{doParallel} to be used with \texttt{foreach}, you must
+call the \texttt{registerDoParallel} function.  If you call this with no
+arguments, on Windows you will get three workers and on Unix-like
+systems you will get a number of workers equal to approximately half the
+number of cores on your system. You can also specify a cluster
+(as created by the \texttt{makeCluster} function) or a number of cores. 
+The \texttt{cores} argument specifies the number of worker
+processes that \texttt{doParallel} will use to execute tasks, which will 
+by default be
+equal to one-half the total number of cores on the machine.  You don't need to
+specify a value for it, however.  By default, \texttt{doParallel} will use the 
+value of the ``cores'' option, as specified with
+the standard ``options'' function.  If that isn't set, then
+\texttt{doParallel} will try to detect the number of cores, and use one-half
+that many workers.
+
+Remember: unless \texttt{registerDoMC} is called, \texttt{foreach} will
+{\em not} run in parallel.  Simply loading the \texttt{doParallel} package is
+not enough.
+
+\section{An example \texttt{doParallel} session}
+
+Before we go any further, let's load \texttt{doParallel}, register it, and use
+it with \texttt{foreach}. We will use \texttt{snow}-like functionality in this 
+vignette, so we start by loading the package and starting a cluster:
+
+<<loadLibs>>=
+library(doParallel)
+cl <- makeCluster(2)
+registerDoParallel(cl)
+foreach(i=1:3) %dopar% sqrt(i)
+@
+<<echo=FALSE>>=
+stopCluster(cl)
+@
+
+To use \texttt{multicore}-like functionality, we would specify the number
+of cores to use instead (but note that on Windows, attempting to use more
+than one core with \texttt{parallel} results in an error):
+\begin{verbatim}
+library(doParallel}
+registerDoParallel(cores=2)
+foreach(i=1:3) %dopar% sqrt(i)
+\end{verbatim}
+
+\begin{quote}
+Note well that this is {\em not} a practical use of \texttt{doParallel}.  This
+is our ``Hello, world'' program for parallel computing.  It tests that
+everything is installed and set up properly, but don't expect it to run
+faster than a sequential \texttt{for} loop, because it won't!
+\texttt{sqrt} executes far too quickly to be worth executing in
+parallel, even with a large number of iterations.  With small tasks, the
+overhead of scheduling the task and returning the result can be greater
+than the time to execute the task itself, resulting in poor performance.
+In addition, this example doesn't make use of the vector capabilities of
+\texttt{sqrt}, which it must to get decent performance.  This is just a
+test and a pedagogical example, {\em not} a benchmark.
+\end{quote}
+
+But returning to the point of this example, you can see that it is very
+simple to load \texttt{doParallel} with all of its dependencies
+(\texttt{foreach}, \texttt{iterators}, \texttt{parallel}, etc), and to
+register it.  For the rest of the R session, whenever you execute
+\texttt{foreach} with \texttt{\%dopar\%}, the tasks will be executed
+using \texttt{doParallel} and \texttt{parallel}.  Note that you can register
+a different parallel backend later, or deregister \texttt{doParallel} by
+registering the sequential backend by calling the \texttt{registerDoSEQ}
+function.
+
+\section{A more serious example}
+
+Now that we've gotten our feet wet, let's do something a bit less
+trivial.  One good example is bootstrapping.  Let's see how long it
+takes to run 10,000 bootstrap iterations in parallel on
+\Sexpr{getDoParWorkers()} cores:
+
+<<echo=FALSE>>=
+library(doParallel)
+cl <- makeCluster(2)
+registerDoParallel(cl)
+@
+<<bootpar>>=
+x <- iris[which(iris[,5] != "setosa"), c(1,5)]
+trials <- 10000
+
+ptime <- system.time({
+  r <- foreach(icount(trials), .combine=cbind) %dopar% {
+    ind <- sample(100, 100, replace=TRUE)
+    result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))
+    coefficients(result1)
+  }
+})[3]
+ptime
+@
+
+Using \texttt{doParallel} and \texttt{parallel} we were able to perform
+10,000 bootstrap iterations in \Sexpr{ptime} seconds on
+\Sexpr{getDoParWorkers()} cores.  By changing the \texttt{\%dopar\%} to
+\texttt{\%do\%}, we can run the same code sequentially to determine the
+performance improvement:
+
+<<bootseq>>=
+stime <- system.time({
+  r <- foreach(icount(trials), .combine=cbind) %do% {
+    ind <- sample(100, 100, replace=TRUE)
+    result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))
+    coefficients(result1)
+  }
+})[3]
+stime
+@
+
+
+The sequential version ran in \Sexpr{stime} seconds, which means the
+speed up is about \Sexpr{round(stime / ptime, digits=1)} on
+\Sexpr{getDoParWorkers()} workers.\footnote{If you build this vignette
+yourself, you can see how well this problem runs on your hardware.  None
+of the times are hardcoded in this document.  You can also run the same
+example which is in the examples directory of the \texttt{doParallel}
+distribution.} Ideally, the speed up would be \Sexpr{getDoParWorkers()},
+but no multicore CPUs are ideal, and neither are the operating systems
+and software that run on them.
+
+At any rate, this is a more realistic example that is worth executing in
+parallel.  We do not explain what it's doing or how it works
+here.  We just want to give you something more substantial than the
+\texttt{sqrt} example in case you want to run some benchmarks yourself.
+You can also run this example on a cluster by simply reregistering 
+with a cluster object that specifies the nodes to use. (See the
+\texttt{makeCluster} help file for more details.)
+
+\section{Getting information about the parallel backend}
+
+To find out how many workers \texttt{foreach} is going to use, you can
+use the \texttt{getDoParWorkers} function:
+
+<<getDoParWorkers>>=
+getDoParWorkers()
+@
+
+This is a useful sanity check that you're actually running in parallel.
+If you haven't registered a parallel backend, or if your machine only
+has one core, \texttt{getDoParWorkers} will return one.  In either case,
+don't expect a speed improvement.  \texttt{foreach} is clever, but it
+isn't magic.
+
+The \texttt{getDoParWorkers} function is also useful when you want the
+number of tasks to be equal to the number of workers.  You may want to
+pass this value to an iterator constructor, for example.
+
+You can also get the name and version of the currently registered
+backend:
+
+<<getDoParName>>=
+getDoParName()
+getDoParVersion()
+@
+<<echo=FALSE>>=
+stopCluster(cl)
+@
+This is mostly useful for documentation purposes, or for checking that
+you have the most recent version of \texttt{doParallel}.
+
+\section{Specifying multicore options}
+
+When using \texttt{multicore}-like functionality, the \texttt{doParallel} package allows 
+you to specify various options when
+running \texttt{foreach} that are supported by the underlying
+\texttt{mclapply} function: ``preschedule'', ``set.seed'', ``silent'',
+and ``cores''.  You can learn about these options from the
+\texttt{mclapply} man page.  They are set using the \texttt{foreach}
+\texttt{.options.multicore} argument.  Here's an example of how to do
+that:
+
+\begin{verbatim}
+mcoptions <- list(preschedule=FALSE, set.seed=FALSE)
+foreach(i=1:3, .options.multicore=mcoptions) %dopar% sqrt(i)
+\end{verbatim}
+
+The ``cores'' options allows you to temporarily override the number of
+workers to use for a single \texttt{foreach} operation.  This is more
+convenient than having to re-register \texttt{doParallel}.  Although if no
+value of ``cores'' was specified when \texttt{doParallel} was registered, you
+can also change this value dynamically using the \texttt{options}
+function:
+
+\begin{verbatim}
+options(cores=2)
+getDoParWorkers()
+options(cores=3)
+getDoParWorkers()
+\end{verbatim}
+
+If you did specify the number of cores when registering \texttt{doParallel},
+the ``cores'' option is ignored:
+
+\begin{verbatim}
+registerDoParallel(4)
+options(cores=2)
+getDoParWorkers()
+\end{verbatim}
+
+As you can see, there are a number of options for controlling the number
+of workers to use with \texttt{parallel}, but the default behaviour
+usually does what you want.
+
+\section{Stopping your cluster}
+
+If you are using \texttt{snow}-like functionality, you will want to stop your
+cluster when you are done using it. The \texttt{doParallel} package's 
+\texttt{.onUnload} function will do this automatically if the cluster was created
+automatically by \texttt{registerDoParallel}, but if you created the cluster manually
+you should stop it using the \texttt{stopCluster} function:
+
+\begin{verbatim}
+stopCluster(cl)
+\end{verbatim}
+
+\section{Conclusion}
+
+The \texttt{doParallel} and \texttt{parallel} packages provide a nice,
+efficient parallel programming platform for multiprocessor/multicore
+computers running operating systems such as Linux and Mac OS X.  It is
+very easy to install, and very easy to use.  In short order, an average
+R programmer can start executing parallel programs, without any previous
+experience in parallel computing.
+
+\end{document}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/r-cran-doparallel.git



More information about the debian-med-commit mailing list