Commit 99af6a54 authored by Florian Gerber's avatar Florian Gerber

v 0.8-1

parent 86e9d398
Package: optimParallel
Type: Package
Title: Parallel Version of the L-BFGS-B Optimization Method
Version: 0.8
Date: 2019-02-25
Version: 0.8-1
Date: 2019-05-07
Author: Florian Gerber
Maintainer: Florian Gerber <florian.gerber@math.uzh.ch>
Description: Provides a parallel version of the L-BFGS-B method of optim(). The main function of the package is optimParallel(), which has the same usage and output as optim(). Using optimParallel() can significantly reduce the optimization time.
......
- version 0.8-1:
commit dfbf0197d2b1cd02b36fa7877cf5506127a52150
Author: Florian Gerber <florian.gerber@math.uzh.ch>
Date: Tue May 7 10:07:40 2019 -0600
(1) improve documentation
- version 0.8:
commit f0a8ed6e658cb481d549fd908d5640bf03abf394
Author: Florian Gerber <florian.gerber@math.uzh.ch>
......
......@@ -12,7 +12,7 @@
#' @param fn see the documentation of \code{\link[stats]{optim}}.
#' @param gr see the documentation of \code{\link[stats]{optim}}.
#' @param ... see the documentation of \code{\link[stats]{optim}}.
#' All R object required by \code{fn} and \code{gr} have to be added here.
#' See section 'Notes' for more information.
#' @param lower see the documentation of \code{\link[stats]{optim}}.
#' @param upper see the documentation of \code{\link[stats]{optim}}.
#' @param control see the documentation of \code{\link[stats]{optim}}.
......@@ -53,10 +53,15 @@
#' whether all required packages are on the search paths of all processes.
#' If, for example, the R package \pkg{spam} is required and missing on those search paths,
#' it can be added via \code{clusterEvalQ(cl, library("spam"))}.}
#' \item{2.}{If \code{fn} or \code{gr} depend on functions or objects defined in the current R session,
#' \item{2.}{If \code{fn} or \code{gr} have more than one argument,
#' it may be necessary to pass those to \code{optimParallel} via the \code{...} argument.
#' \item{3.}{Using parallel R code inside \code{fn} and \code{gr} can work if suitable clusters are setup (one cluster for \code{optimParallel} and one for the parallel execution of \code{fn} and \code{gr}).}
#' \item{4.}{Using \code{optimParallel} with \eqn{n} parallel processes increases the memory usage by about factor \eqn{n} compared to a call to \code{\link[stats]{optim}}.
#' An illustration is given in the section 'Examples'. }
#' \item{3.}{We recommend that all R objects used by \code{fn} and/or \code{gr} are passed to \code{fn} and/or \code{gr} via arguments.
#' In certain cases it may also work that \code{fn} and/or \code{gr} use objects from the \code{.GlobalEnv} (without having corresponding arguments).
#' In that case it can be necessary to pass those objects to all processes of the used cluster via \code{\link[parallel]{clusterExport}}.
#' An illustration is given in the section 'Examples'.}
#' \item{4.}{Using parallel R code inside \code{fn} and \code{gr} can work if suitable clusters are setup (one cluster for \code{optimParallel} and one for the parallel execution of \code{fn} and \code{gr}).}
#' \item{5.}{Using \code{optimParallel} with \eqn{n} parallel processes increases the memory usage by about factor \eqn{n} compared to a call to \code{\link[stats]{optim}}.
#' If the memory limit is reached this may severely slowdown the optimization.
#' Strategies to reduce memory usage are
#' (1) kill all unused processes on the computer,
......@@ -122,6 +127,21 @@
#' lower=c(-Inf, .0001), control=control,
#' parallel=list(forward=TRUE))
#' ## each step invokes 3 parallel calls to negll()
#'
#' ## passing objects to fn/gr (see section 'Notes')
#' ## ----------------------------------------------
#' a <- 10
#' fn <- function(par, b) sum((par-a-b)^2)
#'
#' ## approach 1:
#' clusterExport(cl, "a")
#' optimParallel(par=1, fn=fn, b=1)
#'
#' ## approach 2 (recommended):
#' ## rewrite 'fn' such that all necessary objects
#' ## are passed as arguments
#' fn <- function(par, a, b) sum((par-a-b)^2)
#' optimParallel(par=1, fn=fn, a=20, b=1)
#'
#' setDefaultCluster(cl=NULL); stopCluster(cl) }
#' @export
......@@ -196,9 +216,8 @@ FGgenerator <- function(par, fn, gr=NULL, ...,
assign("fn", fn, envir=e)
assign("gr", gr, envir=e)
parallel::clusterExport(parallel$cl, "e", list2env(list(e=e)))
parallel::clusterEvalQ(parallel$cl, ls())
if(!is.null(gr)){
exprList <- getExprGr(fn, fn, dots=dots)
exprList <- getExprGr(fn=fn, gr=gr, dots=dots)
} else {
nParallel <- if(parallel$forward) 1+length(par) else 1+2*length(par)
exprList <- lapply(seq_len(nParallel), getExprApprox, f=fn, name=names(par), dots=dots)
......
......@@ -23,7 +23,7 @@ optimParallel(par, fn, gr = NULL, ..., lower = -Inf, upper = Inf,
\item{gr}{see the documentation of \code{\link[stats]{optim}}.}
\item{...}{see the documentation of \code{\link[stats]{optim}}.
All R object required by \code{fn} and \code{gr} have to be added here.}
See section 'Notes' for more information.}
\item{lower}{see the documentation of \code{\link[stats]{optim}}.}
......@@ -63,6 +63,33 @@ and the R package \pkg{parallel} to evaluate \code{fn}
and its (approximate) gradient in parallel.\cr\cr
Some default values of the argument \code{parallel} can be set via\cr\code{options("optimParallel.forward", "optimParallel.loginfo")}.
}
\section{Notes}{
\describe{
\item{1.}{If \code{fn} or \code{gr} depend on functions or methods from loaded packages,
it may be necessary to explicitly load those packages in all processes of the cluster.
For \code{cl} of class \code{"cluster"} one can use \code{clusterEvalQ(cl, search())} to check
whether all required packages are on the search paths of all processes.
If, for example, the R package \pkg{spam} is required and missing on those search paths,
it can be added via \code{clusterEvalQ(cl, library("spam"))}.}
\item{2.}{If \code{fn} or \code{gr} have more than one argument,
it may be necessary to pass those to \code{optimParallel} via the \code{...} argument.
An illustration is given in the section 'Examples'. }
\item{3.}{We recommend that all R objects used by \code{fn} and/or \code{gr} are passed to \code{fn} and/or \code{gr} via arguments.
In certain cases it may also work that \code{fn} and/or \code{gr} use objects from the \code{.GlobalEnv} (without having corresponding arguments).
In that case it can be necessary to pass those objects to all processes of the used cluster via \code{\link[parallel]{clusterExport}}.
An illustration is given in the section 'Examples'.}
\item{4.}{Using parallel R code inside \code{fn} and \code{gr} can work if suitable clusters are setup (one cluster for \code{optimParallel} and one for the parallel execution of \code{fn} and \code{gr}).}
\item{5.}{Using \code{optimParallel} with \eqn{n} parallel processes increases the memory usage by about factor \eqn{n} compared to a call to \code{\link[stats]{optim}}.
If the memory limit is reached this may severely slowdown the optimization.
Strategies to reduce memory usage are
(1) kill all unused processes on the computer,
(2) revise the code of \code{fn} and/or \code{gr} to reduce its memory usage, and
(3) reduce the number of parallel processes by specifying the argument \code{parallel=list(forward=TRUE)} and/or
setting up a cluster with less parallel processes.}
}
}
\section{Issues and bug report}{
A list of known issues of \code{optimParallel} can be found at \url{https://git.math.uzh.ch/florian.gerber/optimParallel/issues}.
......@@ -117,6 +144,21 @@ optimParallel(par=c(1,1), fn=negll, x=x, sleep=.5, verbose=TRUE,
parallel=list(forward=TRUE))
## each step invokes 3 parallel calls to negll()
## passing objects to fn/gr (see section 'Notes')
## ----------------------------------------------
a <- 10
fn <- function(par, b) sum((par-a-b)^2)
## approach 1:
clusterExport(cl, "a")
optimParallel(par=1, fn=fn, b=1)
## approach 2 (recommended):
## rewrite 'fn' such that all necessary objects
## are passed as arguments
fn <- function(par, a, b) sum((par-a-b)^2)
optimParallel(par=1, fn=fn, a=20, b=1)
setDefaultCluster(cl=NULL); stopCluster(cl) }
}
\references{
......
......@@ -69,3 +69,21 @@ test_that("optimParallel - use compiled code from other packages",{
verbose=verbose)
})
FN4 <- function(par, a, sleep=0){
Sys.sleep(sleep)
sum(10*par^2) + a
}
GR4 <- function(par, b, sleep=0){
Sys.sleep(sleep)
b*2*par
}
test_that("optimParallel - fn and gr can have different aguments",{
expect_equal(optimParallel(par=1, fn=FN4, gr=GR4,
a=1, b=10, sleep=0,
control=control)$par, 0)
})
......@@ -22,7 +22,7 @@ f4 <- function(par){
sum(par^2)
}
g4 <- function(par){
# cat("g:", par,"\n")
# cat("g:", par,"\n")
# Sys.sleep(1)
2*par
}
......@@ -192,5 +192,3 @@ test_that("... args",{
control=list(factr=factr), a=1),
verbose=verbose)
})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment