diff --git a/.Rbuildignore b/.Rbuildignore
index 2bc8698b2..7109ad47f 100644
--- a/.Rbuildignore
+++ b/.Rbuildignore
@@ -1,14 +1,21 @@
^.*\.Rproj$
-^\.Rproj\.user$
-^\.Rprofile$
-^src/tbb/build/lib_.*$
-^tests/testthat/pkg/RcppParallelTest/src/.*\.s?o$
-^tests/testthat/pkg/RcppParallelTest/src/.*\.dll$
-^inst/lib$
^.travis.yml
^README.md
-^doc$
-^src/.*\.o$
-^gen/
+^\.Rprofile$
+^\.Rproj\.user$
^appveyor\.yml$
+^check$
+^doc$
+^gen$
+^libs$
+^inst/lib$
+^inst/libs$
^revdep$
+^src/.*\.o$
+^src/tbb/build$
+^tags$
+^tests/testthat/pkg/RcppParallelTest/src/.*\.dll$
+^tests/testthat/pkg/RcppParallelTest/src/.*\.s?o$
+^tools/tbb$
+^\.github$
+^patches
\ No newline at end of file
diff --git a/.github/.gitignore b/.github/.gitignore
new file mode 100644
index 000000000..2d19fc766
--- /dev/null
+++ b/.github/.gitignore
@@ -0,0 +1 @@
+*.html
diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml
new file mode 100644
index 000000000..897585d50
--- /dev/null
+++ b/.github/workflows/R-CMD-check.yaml
@@ -0,0 +1,39 @@
+# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
+# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
+on:
+ push:
+ branches: [main, master]
+ pull_request:
+ branches: [main, master]
+
+name: R-CMD-check
+
+jobs:
+ R-CMD-check:
+ runs-on: ${{ matrix.config.os }}
+
+ name: ${{ matrix.config.os }} (${{ matrix.config.r }})
+
+ strategy:
+ fail-fast: false
+ matrix:
+ config:
+ - {os: macOS-latest, r: 'release'}
+ - {os: ubuntu-latest, r: 'release'}
+ - {os: windows-latest, r: 'release'}
+ env:
+ GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
+ R_KEEP_PKG_SOURCE: yes
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: r-lib/actions/setup-r@v2
+ with:
+ use-public-rspm: true
+
+ - uses: r-lib/actions/setup-r-dependencies@v2
+ with:
+ extra-packages: any::rcmdcheck
+ needs: check
+
+ - uses: r-lib/actions/check-r-package@v2
diff --git a/.gitignore b/.gitignore
index 4efd25bce..240c3f21c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,9 +3,18 @@
.Rhistory
.RData
.DS_Store
-config.log
-config.status
-autom4te.cache/
-src-i386/
-src-x64/
+check
inst/doc
+inst/lib
+inst/libs
+libs
+revdep
+src-i386
+src-x64
+tbb.log
+
+src/tbb/build
+src/tbb/build-tbb
+
+R/tbb-autodetected.R
+
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 13c0af011..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-# Run Travis CI for R using https://eddelbuettel.github.io/r-travis/
-
-language: c
-sudo: required
-group: edge
-
-before_install:
- - curl -OLs https://eddelbuettel.github.io/r-travis/run.sh && chmod 0755 run.sh
- - ./run.sh bootstrap
-
-install:
- - ./run.sh install_aptget r-cran-rcpp r-cran-bh r-cran-runit r-cran-knitr r-cran-rmarkdown
-
-script:
- - ./run.sh run_tests
-
-after_failure:
- - ./run.sh dump_logs
-
-notifications:
- email:
- on_success: change
- on_failure: change
\ No newline at end of file
diff --git a/DESCRIPTION b/DESCRIPTION
index 4f06ffef3..d51de8a09 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,36 +1,39 @@
Package: RcppParallel
Type: Package
Title: Parallel Programming Tools for 'Rcpp'
-Version: 4.4.0
+Version: 5.1.10.9000
Authors@R: c(
+ person("Kevin", "Ushey", role = c("aut", "cre"), email = "kevin@rstudio.com",
+ comment = c(ORCID = "0000-0003-2880-7407")),
person("JJ", "Allaire", role = c("aut"), email = "jj@rstudio.com"),
person("Romain", "Francois", role = c("aut", "cph")),
- person("Kevin", "Ushey", role = c("aut", "cre"), email = "kevin@rstudio.com"),
person("Gregory", "Vandenbrouck", role = "aut"),
person("Marcus", "Geelnard", role = c("aut", "cph"),
- comment = "TinyThread library, http://tinythreadpp.bitsnbites.eu/"),
- person(family = "RStudio", role = "cph"),
- person(family = "Intel", role = c("aut", "cph"),
- comment = "Intel TBB library, https://www.threadingbuildingblocks.org/"),
- person(family = "Microsoft", role = "cph")
+ comment = "TinyThread library, https://tinythreadpp.bitsnbites.eu/"),
+ person("Hamada S.", "Badr", email = "badr@jhu.edu", role = c("ctb"),
+ comment = c(ORCID = "0000-0002-9808-2344")),
+ person("Dirk", "Eddelbuettel", role = c("aut"), email = "edd@debian.org",
+ comment = c(ORCID = "0000-0001-6419-907X")),
+ person(family = "Intel", role = c("aut", "cph"), comment = "oneTBB library"),
+ person(family = "UXL Foundation", role = c("aut", "cph"), comment = "oneTBB library"),
+ person(family = "Microsoft", role = "cph"),
+ person(family = "Posit, PBC", role = "cph")
)
Description: High level functions for parallel programming with 'Rcpp'.
For example, the 'parallelFor()' function can be used to convert the work of
a standard serial "for" loop into a parallel one and the 'parallelReduce()'
function can be used for accumulating aggregate or other values.
-Depends: R (>= 3.0.2)
+Depends: R (>= 3.6.0)
Suggests:
Rcpp,
RUnit,
knitr,
rmarkdown
-LinkingTo: BH (>= 1.60.0-1)
-SystemRequirements: GNU make, Windows: cmd.exe and cscript.exe, Solaris: g++ is required
-License: GPL-2
-URL: http://rcppcore.github.io/RcppParallel, https://github.com/RcppCore/RcppParallel
+Roxygen: list(markdown = TRUE)
+SystemRequirements: CMake (>= 3.5)
+License: GPL (>= 3)
+URL: https://rcppcore.github.io/RcppParallel/, https://github.com/RcppCore/RcppParallel
+BugReports: https://github.com/RcppCore/RcppParallel/issues
Biarch: TRUE
-Collate:
- 'build.R'
- 'hooks.R'
- 'options.R'
- 'skeleton.R'
+RoxygenNote: 7.3.2
+Encoding: UTF-8
diff --git a/NAMESPACE b/NAMESPACE
index 2cd799681..94da28d51 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -1,6 +1,9 @@
-export(setThreadOptions)
-export(defaultNumThreads)
-export(RcppParallelLibs)
+# Generated by roxygen2: do not edit by hand
+
export(CxxFlags)
export(LdFlags)
export(RcppParallel.package.skeleton)
+export(RcppParallelLibs)
+export(defaultNumThreads)
+export(setThreadOptions)
+export(tbbLibraryPath)
diff --git a/NEWS.md b/NEWS.md
new file mode 100644
index 000000000..80cdc71e8
--- /dev/null
+++ b/NEWS.md
@@ -0,0 +1,203 @@
+
+## RcppParallel 6.0.0 (UNRELEASED)
+
+* RcppParallel no longer includes tbb headers as part of the RcppParallel/TBB.h
+ header, and instead only exposes its TBB-specific APIs for parallel work.
+
+* RcppParallel now bundles oneTBB 2022.0.0. Note that the TBB ABI has changed;
+ packages which depend on RcppParallel may need to be rebuilt.
+
+* On Windows, RcppParallel now uses the copy of TBB provided by Rtools.
+ If TBB is not available, RcppParallel will use only the fallback 'tinythread'
+ implementation. In practice, this implies that RcppParallel will now only
+ provide a TBB backend with R (>= 4.2.0).
+
+## RcppParallel 5.1.11
+
+* Compatibility fixes for LLVM 21.
+
+## RcppParallel 5.1.10
+
+* Fixed an issue where packages linking to RcppParallel could inadverently
+ depend on internals of the TBB library available during compilation, even
+ if the package did not explicitly use TBB itself.
+
+## RcppParallel 5.1.9
+
+* RcppParallel no longer passes `-rpath` when building / linking on Windows.
+ This fixes build issues when building RcppParallel when using the LLVM
+ linker on Windows. (@kalibera)
+
+## RcppParallel 5.1.8
+
+* RcppParallel now explicitly links to the bundled copy of TBB on macOS. (#206; @jeroen)
+
+## RcppParallel 5.1.7
+
+* Remove deprecated `std::iterator`. (#192; @Enchufa2)
+
+## RcppParallel 5.1.6
+
+* Patch for TBB to allow compilation with gcc-13.
+
+* Fixed a memory leak that could occur when using TinyThread on POSIX systems.
+ (#185; @dipertix and and @kevinushey)
+
+## RcppParallel 5.1.5
+
+* Patches to ensure compatibility with the R 4.2.0 UCRT toolchain on Windows,
+ adapted from patches contributed by Tomas Kalibera.
+
+* Fixed an issue where setting `TBB_ROOT` (or `TBB_INC` / `TBB_LIB`) would
+ copy rather than symlink the associated libraries. (#161)
+
+## RcppParallel 5.1.4
+
+* Fixed an issue causing client packages of RcppParallel to fail to compile
+ on Solaris.
+
+## RcppParallel 5.1.3
+
+* Fixed an issue that prevented compilation of RcppParallel with R (< 4.0.0)
+ of R on Windows.
+
+* The `RCPP_PARALLEL_USE_TBBMALLOC_PROXY` environment variable can now be used
+ to control whether RcppParallel loads the `tbbmalloc_proxy` library on load.
+ See https://www.threadingbuildingblocks.org/docs/help/tbb_userguide/Automically_Replacing_malloc.html
+ for more information.
+
+## RcppParallel 5.1.2
+
+* `RcppParallel` gains the `tbbLibraryPath()` function, to be used when attempting
+ to query the location of the TBB libraries that `RcppParallel` has been
+ configured to use. This may be useful for R packages which wish to explicitly
+ use, or link to, these libraries.
+
+## RcppParallel 5.1.1
+
+* Updated bundled version of TBB (Intel TBB 2019 Update 8).
+
+* RcppParallel can now be configured to use an external copy of TBB, via the
+ `TBB_LIB` and `TBB_INC` environment variables. These should be set to the
+ directories containing the TBB libraries and headers, respectively.
+
+* Added support for the latest versions of Intel oneAPI TBB / oneTBB.
+
+* Updated TBB functionality for the new interface.
+
+* Falling back to building TBB from local source code.
+
+* Backward TBB compatibility based on `__TBB_tbb_stddef_H`.
+
+* Resolved conflicts between system and local TBB headers.
+
+* Fixed URLs, used HTTPS, and minor cleanups.
+
+* Updated package DESCRIPTION and bumped version.
+
+* `setThreadOptions(...)` can again be called multiple times per session.
+ The requested number of threads will be used for invocations to `parallelFor()`
+ and `parallelReduce()` that don't explicitly request a specific number of threads.
+
+* The `parallelFor()` and `parallelReduce()` functions gain the `numThreads`
+ argument, allowing one to limit the number of threads used for a
+ particular computation.
+
+## RcppParallel 5.0.3
+
+* Fixed compilation on macOS M1 machines.
+
+## RcppParallel 5.0.2
+
+* `setThreadOptions(...)` can now only be called once per session, to avoid
+ segfaults when compiling RcppParallel / TBB with gcc 10.1. Subsequent
+ calls to `setThreadOptions(...)` are ignored.
+
+## RcppParallel 5.0.1
+
+* Fixed compilation issue on OpenSUSE Tumbleweed with -flto=auto
+
+* Fixed compilation when CPPFLAGS = -I/usr/local/include and a version
+ of libtbb is installed there
+
+## RcppParallel 5.0.0
+
+* RcppParallel backend can now be customized with RCPP_PARALLEL_BACKEND
+ environment variable (supported values are 'tbb' and 'tinythread')
+
+* Fixed issue when compiling RcppParallel on macOS Catalina
+
+* Fixed issue when compiling RcppParallel with Rtools40
+
+## RcppParallel 4.4.4
+
+* Fixed an issue when compiling RcppParallel with clang-9 on Fedora
+
+## RcppParallel 4.4.3
+
+* Suppress gcc-9 warnings related -Wclass-memaccess
+
+* Added TBB headers for serial TBB operations (#90, @mikejiang)
+
+* Fixed row iterator constructor (#87, @wtianyi)
+
+* Fixed compilation on FreeBSD
+
+## RcppParallel 4.4.2
+
+* Suppress gcc-8 warnings related to -Wclass-memaccess
+
+* Use PKG_CXXFLAGS rather than PKG_CPPFLAGS
+
+* Remove unused dependency on the BH package
+
+## RcppParallel 4.4.1
+
+* Ensure user-specified R configuration passed to TBB
+
+* Work around warnings emitted by gcc 8
+
+## RcppParallel 4.4.0
+
+* Respect user-defined compiler settings (e.g. from ~/.R/Makevars).
+
+* Remove TBB's attempts to suppress compiler diagnostics.
+
+* Allow setting the number of threads to use via RCPP_PARALLEL_NUM_THREADS
+ environment variable.
+
+* Update to TBB 2018 Update 1.
+
+* Add native registration of compiled functions.
+
+## RcppParallel 4.3.20
+
+* Add support for Rtools 3.3 w/ GCC 4.9
+
+## RcppParallel 4.3.14
+
+* Add support for TBB on Solaris
+
+* Fix failure to compile on OS X Snow Leopard R toolchain
+
+* Add const and non-const operator[] for RMatrix class
+
+## RcppParallel 4.3.8
+
+* Add tbbmalloc library
+
+* Correctly pass clang to TBB configure when R is using clang
+
+## RcppParallel 4.3.6
+
+* Support for TBB on Windows
+
+## RcppParallel 4.3.3
+
+* Update to TBB 4.3 (fixes clang compilation error in platform.h)
+
+* Forward CXX to TBB Makefile
+
+## RcppParallel 4.2.5
+
+* Initial release
diff --git a/R/RcppParallel-package.R b/R/RcppParallel-package.R
new file mode 100644
index 000000000..79081f9fb
--- /dev/null
+++ b/R/RcppParallel-package.R
@@ -0,0 +1,24 @@
+
+#' Parallel programming tools for Rcpp
+#'
+#' High level functions for doing parallel programming with Rcpp. For example,
+#' the `parallelFor()` function can be used to convert the work of a
+#' standard serial "for" loop into a parallel one, and the `parallelReduce()`
+#' function can be used for accumulating aggregate or other values.
+#'
+#' The high level interface enables safe and robust parallel programming
+#' without direct manipulation of operating system threads. On Windows, macOS,
+#' and Linux systems the underlying implementation is based on Intel TBB
+#' (Threading Building Blocks). On other platforms, a less-performant fallback
+#' implementation based on the TinyThread library is used.
+#'
+#' For additional documentation, see the package website at:
+#'
+#'
+#'
+#'
+#' @name RcppParallel-package
+#' @docType package
+#' @aliases RcppParallel RcppParallel-package
+#' @keywords package parallel
+NULL
diff --git a/R/aaa.R b/R/aaa.R
new file mode 100644
index 000000000..568a2aac9
--- /dev/null
+++ b/R/aaa.R
@@ -0,0 +1,8 @@
+
+# stubs that get overridden via configure script
+TBB_ENABLED <- TRUE
+TBB_LIB <- ""
+TBB_INC <- ""
+
+TBB_NAME <- "tbb"
+TBB_MALLOC_NAME <- "tbbmalloc"
\ No newline at end of file
diff --git a/R/build.R b/R/build.R
deleted file mode 100644
index 95cbf5e8b..000000000
--- a/R/build.R
+++ /dev/null
@@ -1,99 +0,0 @@
-
-
-# Output the CXX flags. These flags are propagated to sourceCpp via the
-# inlineCxxPlugin (defined below) and to packages via a line in Makevars[.win]
-# like this:
-#
-# PKG_CXXFLAGS += $(shell "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "RcppParallel::CxxFlags()")
-#
-CxxFlags <- function() {
- cat(tbbCxxFlags())
-}
-
-
-# Output the LD flags for building against TBB. These flags are propagated
-# to sourceCpp via the inlineCxxPlugin (defined below) and to packages
-# via a line in Makevars[.win] like this:
-#
-# PKG_LIBS += $(shell "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "RcppParallel::LdFlags()")
-#
-LdFlags <- function() {
- cat(tbbLdFlags())
-}
-
-# alias for backward compatibility
-RcppParallelLibs <- function() {
- LdFlags()
-}
-
-# Inline plugin used by sourceCpp.
-inlineCxxPlugin <- function() {
- list(
- env = list(
- PKG_CXXFLAGS = tbbCxxFlags(),
- PKG_LIBS = tbbLdFlags()
- ),
- includes = "#include ",
- LinkingTo = "RcppParallel",
- body = function(x) x,
- Depends = "RcppParallel"
- )
-}
-
-tbbCxxFlags <- function() {
-
- flags <- c()
-
- # opt-in to TBB on Windows
- if (Sys.info()['sysname'] == "Windows")
- flags <- paste(flags, "-DRCPP_PARALLEL_USE_TBB=1")
-
- flags
-}
-
-# Return the linker flags requried for TBB on this platform
-tbbLdFlags <- function() {
- # on Windows and Solaris we need to explicitly link against tbb.dll
- if ((Sys.info()['sysname'] %in% c("Windows", "SunOS")) && !isSparc()) {
- tbb <- tbbLibPath()
- paste("-L", asBuildPath(dirname(tbb)), " -ltbb -ltbbmalloc", sep = "")
- } else {
- ""
- }
-}
-
-# Determine the platform-specific path to the TBB library
-tbbLibPath <- function(suffix = "") {
- sysname <- Sys.info()['sysname']
- tbbSupported <- list(
- "Darwin" = paste("libtbb", suffix, ".dylib", sep = ""),
- "Linux" = paste("libtbb", suffix, ".so.2", sep = ""),
- "Windows" = paste("tbb", suffix, ".dll", sep = ""),
- "SunOS" = paste("libtbb", suffix, ".so", sep = "")
- )
- if ((sysname %in% names(tbbSupported)) && !isSparc()) {
- libDir <- "lib/"
- if (sysname == "Windows")
- libDir <- paste(libDir, .Platform$r_arch, "/", sep="")
- system.file(paste(libDir, tbbSupported[[sysname]], sep = ""),
- package = "RcppParallel")
- } else {
- NULL
- }
-}
-
-isSparc <- function() {
- Sys.info()['sysname'] == "SunOS" && Sys.info()[["machine"]] != "i86pc"
-}
-
-# Helper function to ape the behavior of the R build system
-# when providing paths to libraries
-asBuildPath <- function(path) {
- if (.Platform$OS.type == "windows") {
- path <- normalizePath(path)
- if (grepl(' ', path, fixed=TRUE))
- path <- utils::shortPathName(path)
- path <- gsub("\\\\", "/", path)
- }
- return(path)
-}
diff --git a/R/flags.R b/R/flags.R
new file mode 100644
index 000000000..6ae1f8280
--- /dev/null
+++ b/R/flags.R
@@ -0,0 +1,53 @@
+
+#' Compilation flags for RcppParallel
+#'
+#' Output the compiler or linker flags required to build against RcppParallel.
+#'
+#' These functions are typically called from `Makevars` as follows:
+#'
+#' ```
+#' PKG_LIBS += $(shell "${R_HOME}/bin/Rscript" -e "RcppParallel::LdFlags()")
+#' ```
+#'
+#' On Windows, the flags ensure that the package links with the built-in TBB
+#' library. On Linux and macOS, the output is empty, because TBB is loaded
+#' dynamically on load by `RcppParallel`.
+#'
+#' \R packages using RcppParallel should also add the following to their
+#' `NAMESPACE` file:
+#'
+#' ```
+#' importFrom(RcppParallel, RcppParallelLibs)
+#' ```
+#'
+#' This is necessary to ensure that \pkg{RcppParallel} (and so, TBB) is loaded
+#' and available.
+#'
+#' @name flags
+#' @rdname flags
+#' @aliases RcppParallelLibs LdFlags CxxFlags
+#'
+#' @return Returns \code{NULL}, invisibly. These functions are called for
+#' their side effects (writing the associated flags to stdout).
+#'
+NULL
+
+
+#' @name flags
+#' @export
+CxxFlags <- function() {
+ cat(tbbCxxFlags())
+}
+
+#' @name flags
+#' @export
+LdFlags <- function() {
+ cat(tbbLdFlags())
+}
+
+#' @name flags
+#' @export
+RcppParallelLibs <- function() {
+ LdFlags()
+}
+
diff --git a/R/hooks.R b/R/hooks.R
deleted file mode 100644
index be993c8f0..000000000
--- a/R/hooks.R
+++ /dev/null
@@ -1,48 +0,0 @@
-
-dllInfo <- NULL
-mallocDllInfo <- NULL
-
-.onLoad <- function(libname, pkgname) {
-
- # load tbb and tbbmalloc on supported platforms
- tbb <- tbbLibPath()
- if (!is.null(tbb)) {
- if (!file.exists(tbb)) {
- warning(paste("TBB library", tbb, "not found."))
- } else {
- dllInfo <<- dyn.load(tbb, local = FALSE, now = TRUE)
- }
- }
- tbbMalloc <- tbbLibPath("malloc")
- if (!is.null(tbbMalloc)) {
- if (!file.exists(tbbMalloc)) {
- warning(paste("TBB malloc library", tbbMalloc, "not found."))
- } else {
- mallocDllInfo <<- dyn.load(tbbMalloc, local = FALSE, now = TRUE)
- }
- }
-
- # load the package library
- library.dynam("RcppParallel", pkgname, libname)
-
- # set default thread options
- numThreads <- "auto"
- numThreadsEnv <- Sys.getenv("RCPP_PARALLEL_NUM_THREADS", unset = NA)
- if (!is.na(numThreadsEnv))
- setThreadOptions(numThreads = as.integer(numThreadsEnv))
- else
- setThreadOptions(numThreads = "auto")
-}
-
-.onUnload <- function(libpath) {
-
- # unload the package library
- library.dynam.unload("RcppParallel", libpath)
-
- # unload tbb if we loaded it
- if (!is.null(dllInfo))
- dyn.unload(dllInfo[["path"]])
- # unload tbbmalloc if we loaded it
- if (!is.null(mallocDllInfo))
- dyn.unload(mallocDllInfo[["path"]])
-}
diff --git a/R/options.R b/R/options.R
index eac85482c..9b54a37c5 100644
--- a/R/options.R
+++ b/R/options.R
@@ -1,7 +1,48 @@
-
-setThreadOptions <- function(numThreads = "auto", stackSize = "auto") {
-
+#' Thread options for RcppParallel
+#'
+#' Set thread options (number of threads to use for task scheduling and stack
+#' size per-thread) for RcppParallel.
+#'
+#' RcppParallel is automatically initialized with the default number of threads
+#' and thread stack size when it loads. You can call `setThreadOptions()` at
+#' any time to change the defaults.
+#'
+#' The `parallelFor()` and `parallelReduce()` also accept `numThreads` as
+#' an argument, if you'd like to control the number of threads specifically
+#' to be made available for a particular parallel function call. Note that
+#' this value is advisory, and TBB may choose a smaller number of threads
+#' if the number of requested threads cannot be honored on the system.
+#'
+#' @aliases setThreadOptions defaultNumThreads
+#'
+#' @param numThreads
+#' Number of threads to use for task scheduling. Call `defaultNumThreads()`
+#' to determine the the default value used for "auto".
+#'
+#' @param stackSize
+#' Stack size (in bytes) to use for worker threads. The
+#' default used for "auto" is 2MB on 32-bit systems and 4MB on 64-bit systems
+#' (note that this parameter has no effect on Windows).
+#'
+#' @return
+#' `defaultNumThreads()` returns the default number of threads used by
+#' RcppParallel, if another value isn't specified either via
+#' `setThreadOptions()` or explicitly in calls to `parallelFor()` and
+#' `parallelReduce()`.
+#'
+#' @examples
+#'
+#' \dontrun{
+#' library(RcppParallel)
+#' setThreadOptions(numThreads = 4)
+#' defaultNumThreads()
+#' }
+#'
+#' @export setThreadOptions
+setThreadOptions <- function(numThreads = "auto",
+ stackSize = "auto")
+{
# validate and resolve numThreads
if (identical(numThreads, "auto"))
numThreads <- -1L
@@ -18,19 +59,27 @@ setThreadOptions <- function(numThreads = "auto", stackSize = "auto") {
else
stackSize <- as.integer(stackSize)
- # Call setThreadOptions if using tbb
- if (!is.null(dllInfo)) {
- invisible(.Call("setThreadOptions", numThreads, stackSize,
- PACKAGE = "RcppParallel"))
- }
-
+ # set RCPP_PARALLEL_NUM_THREADS
if (numThreads == -1L)
Sys.unsetenv("RCPP_PARALLEL_NUM_THREADS")
else
Sys.setenv(RCPP_PARALLEL_NUM_THREADS = numThreads)
+
+ # set RCPP_PARALLEL_STACK_SIZE
+ if (stackSize == 0L)
+ Sys.unsetenv("RCPP_PARALLEL_STACK_SIZE")
+ else
+ Sys.setenv(RCPP_PARALLEL_STACK_SIZE = stackSize)
}
+#' @rdname setThreadOptions
+#' @export
defaultNumThreads <- function() {
.Call("defaultNumThreads", PACKAGE = "RcppParallel")
}
+isUsingTbb <- function() {
+ backend <- Sys.getenv("RCPP_PARALLEL_BACKEND", "tbb")
+ identical(backend, "tbb")
+}
+
diff --git a/R/platform.R b/R/platform.R
new file mode 100644
index 000000000..fe7569ff1
--- /dev/null
+++ b/R/platform.R
@@ -0,0 +1,26 @@
+
+is_windows <- function() {
+ .Platform$OS.type == "windows"
+}
+
+is_mac <- function() {
+ Sys.info()[["sysname"]] == "Darwin"
+}
+
+is_unix <- function() {
+ .Platform$OS.type == "unix"
+}
+
+is_solaris <- function() {
+ Sys.info()[["sysname"]] == "SunOS"
+}
+
+is_sparc <- function() {
+ info <- Sys.info()
+ all(
+ info[["sysname"]] == "SunOS",
+ info[["machine"]] != "i86pc"
+ )
+}
+
+
diff --git a/R/plugin.R b/R/plugin.R
new file mode 100644
index 000000000..78dc2aab2
--- /dev/null
+++ b/R/plugin.R
@@ -0,0 +1,15 @@
+
+# Inline plugin used by sourceCpp.
+inlineCxxPlugin <- function() {
+
+ list(
+ env = list(
+ PKG_CXXFLAGS = tbbCxxFlags(),
+ PKG_LIBS = tbbLdFlags()
+ ),
+ includes = "#include ",
+ LinkingTo = "RcppParallel",
+ body = identity,
+ Depends = "RcppParallel"
+ )
+}
diff --git a/R/skeleton.R b/R/skeleton.R
index 88cbcdbcb..4b12b711d 100644
--- a/R/skeleton.R
+++ b/R/skeleton.R
@@ -1,3 +1,53 @@
+
+#' Create a skeleton for a new package depending on RcppParallel
+#'
+#' \code{RcppParallel.package.skeleton} automates the creation of a new source
+#' package that intends to use features of RcppParallel.
+#'
+#' It is based on the \link[utils]{package.skeleton} function which it executes
+#' first.
+#'
+#' In addition to \link[Rcpp]{Rcpp.package.skeleton} :
+#'
+#' The \samp{DESCRIPTION} file gains an Imports line requesting that the
+#' package depends on RcppParallel and a LinkingTo line so that the package
+#' finds RcppParallel header files.
+#'
+#' The \samp{NAMESPACE} gains a \code{useDynLib} directive as well as an
+#' \code{importFrom(RcppParallel, evalCpp} to ensure instantiation of
+#' RcppParallel.
+#'
+#' The \samp{src} directory is created if it does not exists and a
+#' \samp{Makevars} file is added setting the environment variables
+#' \samp{PKG_LIBS} to accomodate the necessary flags to link with the
+#' RcppParallel library.
+#'
+#' If the \code{example_code} argument is set to \code{TRUE}, example files
+#' \samp{vector-sum.cpp} is created in the \samp{src} directory.
+#' \code{Rcpp::compileAttributes()} is then called to generate
+#' \code{src/RcppExports.cpp} and \code{R/RcppExports.R}. These files are given
+#' as an example and should eventually by removed from the generated package.
+#'
+#' @param name The name of your R package.
+#' @param example_code If \code{TRUE}, example C++ code using RcppParallel is
+#' added to the package.
+#' @param ... Optional arguments passed to \link[Rcpp]{Rcpp.package.skeleton}.
+#' @return Nothing, used for its side effects
+#' @seealso \link[utils]{package.skeleton}
+#' @references Read the \emph{Writing R Extensions} manual for more details.
+#'
+#' Once you have created a \emph{source} package you need to install it: see
+#' the \emph{R Installation and Administration} manual, \code{\link{INSTALL}}
+#' and \code{\link{install.packages}}.
+#' @keywords programming
+#' @examples
+#'
+#' \dontrun{
+#' # simple package
+#' RcppParallel.package.skeleton("foobar")
+#' }
+#'
+#' @export RcppParallel.package.skeleton
RcppParallel.package.skeleton <- function(name = "anRpackage",
example_code = TRUE,
...)
@@ -21,9 +71,12 @@ RcppParallel.package.skeleton <- function(name = "anRpackage",
on.exit(setwd(owd), add = TRUE)
# remove dummy stuff
- unlink("data/dummy.Rda")
+ unlink("data", recursive=TRUE)
unlink("man/dummy.Rd")
unlink("Read-and-delete-me")
+ lns <- readLines("NAMESPACE")
+ writeLines(lns[!grepl("dummy", lns)], "NAMESPACE")
+ unlink("src/init.c")
message("\nAdding RcppParallel settings")
@@ -56,7 +109,7 @@ RcppParallel.package.skeleton <- function(name = "anRpackage",
message(" >> added src/Makevars")
cat(
c(
- 'CXX_STD = CXX11',
+ '# We also need importFrom(RcppParallel,RcppParallelLibs) in NAMESPACE',
'PKG_LIBS += $(shell ${R_HOME}/bin/Rscript -e "RcppParallel::RcppParallelLibs()")'
),
file = "src/Makevars",
@@ -67,7 +120,6 @@ RcppParallel.package.skeleton <- function(name = "anRpackage",
message(" >> added src/Makevars.win")
cat(
c(
- 'CXX_STD = CXX11',
'PKG_CXXFLAGS += -DRCPP_PARALLEL_USE_TBB=1',
'PKG_LIBS += $(shell "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "RcppParallel::RcppParallelLibs()")'
),
diff --git a/R/tbb-autodetected.R.in b/R/tbb-autodetected.R.in
new file mode 100644
index 000000000..7cc750e09
--- /dev/null
+++ b/R/tbb-autodetected.R.in
@@ -0,0 +1,7 @@
+
+TBB_ENABLED <- @TBB_ENABLED@
+TBB_LIB <- "@TBB_LIB@"
+TBB_INC <- "@TBB_INC@"
+
+TBB_NAME <- "@TBB_NAME@"
+TBB_MALLOC_NAME <- "@TBB_MALLOC_NAME@"
\ No newline at end of file
diff --git a/R/tbb.R b/R/tbb.R
new file mode 100644
index 000000000..3d8fbb328
--- /dev/null
+++ b/R/tbb.R
@@ -0,0 +1,135 @@
+
+#' Get the Path to a TBB Library
+#'
+#' Retrieve the path to a TBB library. This can be useful for \R packages
+#' using RcppParallel that wish to use, or re-use, the version of TBB that
+#' RcppParallel has been configured to use.
+#'
+#' @param name
+#' The name of the TBB library to be resolved. Normally, this is one of
+#' `tbb`, `tbbmalloc`, or `tbbmalloc_proxy`. When `NULL`, the library
+#' path containing the TBB libraries is returned instead.
+#'
+#' @export
+tbbLibraryPath <- function(name = NULL) {
+
+ # library paths for different OSes
+ sysname <- Sys.info()[["sysname"]]
+
+ # find root for TBB install
+ tbbRoot <- Sys.getenv("TBB_LIB", unset = tbbRoot())
+ if (is.null(name))
+ return(tbbRoot)
+
+ # form library names
+ tbbLibNames <- list(
+ "Darwin" = paste0("lib", name, ".dylib"),
+ "Windows" = paste0("lib", name, c("12", ""), ".a"),
+ "SunOS" = paste0("lib", name, ".so"),
+ "Linux" = paste0("lib", name, c(".so.2", ".so"))
+ )
+
+ # skip systems that we know not to be compatible
+ isCompatible <- !is_sparc() && !is.null(tbbLibNames[[sysname]])
+ if (!isCompatible)
+ return(NULL)
+
+ # find the request library (if any)
+ libNames <- tbbLibNames[[sysname]]
+ for (libName in libNames) {
+
+ tbbName <- file.path(tbbRoot, libName)
+ if (file.exists(tbbName))
+ return(tbbName)
+
+ arch <- if (nzchar(.Platform$r_arch)) .Platform$r_arch
+ suffix <- paste(c("lib", arch, libName), collapse = "/")
+ tbbName <- system.file(suffix, package = "RcppParallel")
+ if (file.exists(tbbName))
+ return(tbbName)
+
+ }
+
+}
+
+tbbCxxFlags <- function() {
+
+ if (!TBB_ENABLED)
+ return("-DRCPP_PARALLEL_USE_TBB=0")
+
+ flags <- c("-DRCPP_PARALLEL_USE_TBB=1")
+
+ # if TBB_INC is set, apply those library paths
+ tbbInc <- Sys.getenv("TBB_INC", unset = TBB_INC)
+ if (!file.exists(tbbInc)) {
+ tbbInc <- system.file("include", package = "RcppParallel")
+ }
+
+ # add include path
+ if (nzchar(tbbInc) && file.exists(tbbInc)) {
+
+ # prefer new interface if version.h exists -- we keep this
+ # for compatibility with packages like StanHeaders, rstan
+ versionPath <- file.path(tbbInc, "tbb/version.h")
+ if (file.exists(versionPath))
+ flags <- c(flags, "-DTBB_INTERFACE_NEW")
+
+ # now add the include path
+ flags <- c(flags, paste0("-I", asBuildPath(tbbInc)))
+
+ }
+
+ # return flags as string
+ paste(flags, collapse = " ")
+
+}
+
+# Return the linker flags required for TBB on this platform
+tbbLdFlags <- function() {
+
+ # on Windows, we statically link to oneTBB
+ if (is_windows()) {
+
+ libPath <- system.file("libs", package = "RcppParallel")
+ if (nzchar(.Platform$r_arch))
+ libPath <- file.path(libPath, .Platform$r_arch)
+
+ ldFlags <- sprintf("-L%s -lRcppParallel", asBuildPath(libPath))
+ return(ldFlags)
+
+ }
+
+ # shortcut if TBB_LIB defined
+ tbbLib <- Sys.getenv("TBB_LINK_LIB", Sys.getenv("TBB_LIB", unset = TBB_LIB))
+ if (nzchar(tbbLib)) {
+ if (R.version$os == "emscripten") {
+ fmt <- "-L%1$s -l%2$s"
+ return(sprintf(fmt, asBuildPath(tbbLib), TBB_NAME))
+ }
+ fmt <- "-L%1$s -Wl,-rpath,%1$s -l%2$s -l%3$s"
+ return(sprintf(fmt, asBuildPath(tbbLib), TBB_NAME, TBB_MALLOC_NAME))
+ }
+
+ # explicitly link on macOS
+ # https://github.com/RcppCore/RcppParallel/issues/206
+ if (is_mac()) {
+ fmt <- "-L%s -l%s -l%s"
+ return(sprintf(fmt, asBuildPath(tbbLibraryPath()), TBB_NAME, TBB_MALLOC_NAME))
+ }
+
+ # nothing required on other platforms
+ ""
+
+}
+
+tbbRoot <- function() {
+
+ if (nzchar(TBB_LIB))
+ return(TBB_LIB)
+
+ rArch <- .Platform$r_arch
+ parts <- c("lib", if (nzchar(rArch)) rArch)
+ libDir <- paste(parts, collapse = "/")
+ system.file(libDir, package = "RcppParallel")
+
+}
diff --git a/R/utils.R b/R/utils.R
new file mode 100644
index 000000000..53ced6389
--- /dev/null
+++ b/R/utils.R
@@ -0,0 +1,24 @@
+
+# generate paths consumable by the compilers and linkers
+# in particular, on Windows and Solaris, this means the path _cannot_ be quoted !!
+asBuildPath <- function(path) {
+
+ # normalize paths using forward slashes
+ path <- normalizePath(path, winslash = "/", mustWork = FALSE)
+
+ # prefer short path names if the path has spaces
+ if (is_windows() && grepl(" ", path, fixed = TRUE))
+ path <- utils::shortPathName(path)
+
+ # if we still have spaces, and we're not Windows or Solaris, try quoting
+ if (grepl(" ", path, fixed = TRUE) && !is_solaris())
+ path <- shQuote(path)
+
+ # ensure we use forward slashes, even on Windows
+ path <- chartr("\\", "/", path)
+
+ # return path
+ path
+
+}
+
diff --git a/R/zzz.R b/R/zzz.R
new file mode 100644
index 000000000..54374e097
--- /dev/null
+++ b/R/zzz.R
@@ -0,0 +1,71 @@
+
+# !diagnostics suppress=.dllInfo,.tbbDllInfo,.tbbMallocDllInfo,.tbbMallocProxyDllInfo
+
+# NOTE: we intentionally do _not_ load tbbmalloc_proxy by default, as its
+# intended use is to replace the default allocator, something that may be
+# dangerous to do by default. in addition, TBB's documentation recommends
+# only loading explicitly via e.g. LD_PRELOAD
+.dllInfo <- NULL
+.tbbDllInfo <- NULL
+.tbbMallocDllInfo <- NULL
+.tbbMallocProxyDllInfo <- NULL
+
+loadTbbLibrary <- function(name) {
+ # TBB is statically linked on Windows
+ if (is_windows()) {
+ return(NULL)
+ }
+ path <- tbbLibraryPath(name)
+ if (is.null(path))
+ return(NULL)
+
+ if (!file.exists(path)) {
+ warning("TBB library ", shQuote(name), " not found.")
+ return(NULL)
+ }
+
+ dyn.load(path, local = FALSE, now = TRUE)
+
+}
+
+.onLoad <- function(libname, pkgname) {
+
+ # on Windows, load RcppParallel first
+ if (.Platform$OS.type == "windows") {
+ .dllInfo <<- library.dynam("RcppParallel", pkgname, libname)
+ }
+
+ # load tbb, tbbmalloc
+ .tbbDllInfo <<- loadTbbLibrary("tbb")
+ .tbbMallocDllInfo <<- loadTbbLibrary("tbbmalloc")
+
+ # load tbbmalloc_proxy, but only if requested
+ useTbbMallocProxy <- Sys.getenv("RCPP_PARALLEL_USE_TBBMALLOC_PROXY", unset = "FALSE")
+ if (useTbbMallocProxy %in% c("TRUE", "True", "true", "1"))
+ .tbbMallocProxyDllInfo <<- loadTbbLibrary("tbbmalloc_proxy")
+
+ # load RcppParallel library if available
+ if (.Platform$OS.type != "windows") {
+ .dllInfo <<- library.dynam("RcppParallel", pkgname, libname, local = FALSE)
+ }
+
+}
+
+.onUnload <- function(libpath) {
+
+ # unload the package library
+ if (!is.null(.dllInfo))
+ library.dynam.unload("RcppParallel", libpath)
+
+ # NOTE: we do not explicitly unload tbbmalloc_proxy as switching
+ # the allocator at runtime can cause issues
+
+ # unload tbbmalloc if we loaded it
+ if (!is.null(.tbbMallocDllInfo))
+ dyn.unload(.tbbMallocDllInfo[["path"]])
+
+ # unload tbb if we loaded it
+ if (!is.null(.tbbDllInfo))
+ dyn.unload(.tbbDllInfo[["path"]])
+
+}
diff --git a/README.md b/README.md
index f0c68b576..620e6d21b 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,63 @@
-## RcppParallel Package
-[](https://travis-ci.org/RcppCore/RcppParallel)
-[](https://ci.appveyor.com/project/RcppCore/RcppParallel)
-[](https://cran.r-project.org/package=RcppParallel)
+## RcppParallel
-High level functions for doing parallel programming with Rcpp. For example, the `parallelFor` function can be used to convert the work of a standard serial "for" loop into a parallel one and the `parallelReduce` function can be used for accumulating aggregate or other values.
+
+[](https://cran.r-project.org/package=RcppParallel)
+[](https://github.com/RcppCore/RcppParallel/actions/workflows/R-CMD-check.yaml)
+
-The high level interface enables safe and robust parallel programming without direct manipulation of operating system threads. On Windows, OS X, and Linux systems the underlying implementation is based on [Intel TBB](https://www.threadingbuildingblocks.org/) (Threading Building Blocks). On other platforms a less-performant fallback implementation based on the [TinyThread](http://tinythreadpp.bitsnbites.eu/) library is used.
+High level functions for parallel programming with Rcpp. The `parallelFor()` function can be used to convert the work of a standard serial "for" loop into a parallel one, and the `parallelReduce()` function can be used for accumulating aggregate or other values.
+
+The high level interface enables safe and robust parallel programming without direct manipulation of operating system threads. On Windows, macOS, and Linux systems, the underlying implementation is based on [Intel TBB](https://github.com/oneapi-src/oneTBB) (Threading Building Blocks). On other platforms, a less-performant fallback implementation based on the [TinyThread](https://tinythreadpp.bitsnbites.eu/) library is used.
For additional documentation on using RcppParallel see the package website at http://rcppcore.github.io/RcppParallel/.
+
+### Intel TBB
+
+`RcppParallel` supports the new interface of Intel TBB, and can be configured to use an external copy of TBB (e.g., with [`oneTBB`](https://github.com/oneapi-src/oneTBB) or the system TBB library), using the `TBB_LIB` and `TBB_INC` environment variables.
+
+To build the development version of `RcppParallel` with [`oneTBB`](https://github.com/oneapi-src/oneTBB):
+
+- Install [`oneTBB`](https://github.com/oneapi-src/oneTBB).
+
+For example, installing [`oneTBB`](https://github.com/oneapi-src/oneTBB) on Linux 64-bit (`x86_64`) to `$HOME` directory (change if needed!):
+
+```bash
+TBB_RELEASE="https://api.github.com/repos/oneapi-src/oneTBB/releases/latest"
+TBB_TAG=$(curl --silent $TBB_RELEASE | grep -Po '"tag_name": "\K.*?(?=")')
+TBB_VERSION=${TBB_TAG#?}
+
+wget https://github.com/oneapi-src/oneTBB/releases/download/v$TBB_VERSION/oneapi-tbb-$TBB_VERSION-lin.tgz
+tar zxvf oneapi-tbb-$TBB_VERSION-lin.tgz -C $HOME
+
+export TBB="$HOME/oneapi-tbb-$TBB_VERSION"
+```
+Note that you may replace `TBB_VERSION=${TBB_TAG#?}` with a custom version number if needed ( check available releases [here](https://github.com/oneapi-src/oneTBB/releases) ).
+
+- Set the TBB environment variables (specifically: `TBB` for the installation prefix, `TBB_INC` for the directory that includes the header files, and `TBB_LIB` for the libraries directory).
+
+For example, installing [`oneTBB`](https://github.com/oneapi-src/oneTBB) on Linux 64-bit (`x86_64`) to `$HOME` directory (change if needed!):
+
+```bash
+source $TBB/env/vars.sh intel64
+
+export TBB_INC="$TBB/include"
+export TBB_LIB="$TBB/lib/intel64/gcc4.8"
+```
+
+- Build the development version of `RcppParallel`:
+
+```r
+install.packages("remotes")
+remotes::install_github("RcppCore/RcppParallel")
+```
+
+
### License
-The RcppParallel package is made available under the [GPLv2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html).
+The RcppParallel package is made available under the [GPLv2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) license.
-The TinyThread library is licensed under the [zlib/libpng](http://www.opensource.org/licenses/zlib-license.php) license as described [here](https://gitorious.org/tinythread/tinythreadpp/source/master:README.txt).
+The [TinyThread library](https://tinythreadpp.bitsnbites.eu/) is licensed under the [zlib/libpng](https://opensource.org/licenses/zlib-license.php) license.
-The Intel TBB Library is licensed under the Apache 2.0 (as described at https://www.threadingbuildingblocks.org/faq/10).
+The Intel TBB Library is licensed under the Apache 2.0 license, as described at https://github.com/oneapi-src/oneTBB/blob/master/LICENSE.txt.
diff --git a/RcppParallel.Rproj b/RcppParallel.Rproj
index aa82b53fb..2970ea06c 100644
--- a/RcppParallel.Rproj
+++ b/RcppParallel.Rproj
@@ -1,4 +1,5 @@
Version: 1.0
+ProjectId: 8e3d73b0-404c-42f5-b2ef-46f759f65dd4
RestoreWorkspace: No
SaveWorkspace: No
@@ -12,6 +13,10 @@ Encoding: UTF-8
RnwWeave: Sweave
LaTeX: pdfLaTeX
+AutoAppendNewline: Yes
+
BuildType: Package
-PackageInstallArgs: --with-keep.source --clean
+PackageCleanBeforeInstall: No
+PackageInstallArgs: --with-keep.source
PackageCheckArgs: --as-cran
+PackageRoxygenize: rd,collate,namespace
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index c6c14384e..000000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,45 +0,0 @@
-# DO NOT CHANGE the "init" and "install" sections below
-
-# Download script file from GitHub
-init:
- ps: |
- $ErrorActionPreference = "Stop"
- Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1"
- Import-Module '..\appveyor-tool.ps1'
-
-install:
- ps: Bootstrap
-
-cache:
- - C:\RLibrary
-
-# Adapt as necessary starting from here
-
-build_script:
- - travis-tool.sh install_deps
-
-test_script:
- - travis-tool.sh run_tests
-
-on_failure:
- - 7z a failure.zip *.Rcheck\*
- - appveyor PushArtifact failure.zip
-
-artifacts:
- - path: '*.Rcheck\**\*.log'
- name: Logs
-
- - path: '*.Rcheck\**\*.out'
- name: Logs
-
- - path: '*.Rcheck\**\*.fail'
- name: Logs
-
- - path: '*.Rcheck\**\*.Rout'
- name: Logs
-
- - path: '\*_*.tar.gz'
- name: Bits
-
- - path: '\*_*.zip'
- name: Bits
diff --git a/cleanup b/cleanup
index d271eb4d7..ddbda5cf6 100755
--- a/cleanup
+++ b/cleanup
@@ -1,3 +1,3 @@
#!/usr/bin/env sh
-: ${R_HOME=`R RHOME`}
-"${R_HOME}/bin/Rscript" tools/config.R cleanup
+: "${R_HOME=`R RHOME`}"
+"${R_HOME}/bin/Rscript" tools/config.R cleanup "$@"
diff --git a/cleanup.win b/cleanup.win
index 7128030cc..918a2f0c8 100755
--- a/cleanup.win
+++ b/cleanup.win
@@ -1,2 +1,2 @@
#!/usr/bin/env sh
-"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" tools/config.R cleanup
+"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" tools/config.R cleanup "$@"
diff --git a/configure b/configure
index aed1519d6..b08715386 100755
--- a/configure
+++ b/configure
@@ -1,3 +1,3 @@
#!/usr/bin/env sh
-: ${R_HOME=`R RHOME`}
-"${R_HOME}/bin/Rscript" tools/config.R configure
+: "${R_HOME=`R RHOME`}"
+"${R_HOME}/bin/Rscript" tools/config.R configure "$@"
diff --git a/configure.win b/configure.win
index c83ab78b5..a47d1205c 100755
--- a/configure.win
+++ b/configure.win
@@ -1,2 +1,2 @@
#!/usr/bin/env sh
-"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" tools/config.R configure
+"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" tools/config.R configure "$@"
diff --git a/inst/.gitignore b/inst/.gitignore
index c3af85790..93f665e4d 100644
--- a/inst/.gitignore
+++ b/inst/.gitignore
@@ -1 +1,2 @@
lib/
+libs/
diff --git a/inst/NEWS b/inst/NEWS
deleted file mode 100644
index 4b2d2208f..000000000
--- a/inst/NEWS
+++ /dev/null
@@ -1,43 +0,0 @@
-RcppParallel 4.4.0
-------------------------------------------------------------------------
-
-* Respect user-defined compiler settings (e.g. from ~/.R/Makevars).
-* Remove TBB's attempts to suppress compiler diagnostics.
-* Allow setting the number of threads to use via RCPP_PARALLEL_NUM_THREADS
- environment variable.
-* Update to TBB 2018 Update 1.
-* Add native registration of compiled functions.
-
-RcppParallel 4.3.20
-------------------------------------------------------------------------
-
-* Add support for Rtools 3.3 w/ GCC 4.9
-
-RcppParallel 4.3.14
-------------------------------------------------------------------------
-
-* Add support for TBB on Solaris
-* Fix failure to compile on OS X Snow Leopard R toolchain
-* Add const and non-const operator[] for RMatrix class
-
-RcppParallel 4.3.8
-------------------------------------------------------------------------
-
-* Add tbbmalloc library
-* Correctly pass clang to TBB configure when R is using clang
-
-RcppParallel 4.3.6
-------------------------------------------------------------------------
-
-* Support for TBB on Windows
-
-RcppParallel 4.3.3
-------------------------------------------------------------------------
-
-* Update to TBB 4.3 (fixes clang compilation error in platform.h)
-* Forward CXX to TBB Makefile
-
-RcppParallel 4.2.5
-------------------------------------------------------------------------
-
-* Initial release
diff --git a/inst/include/.gitignore b/inst/include/.gitignore
new file mode 100644
index 000000000..4c130be3e
--- /dev/null
+++ b/inst/include/.gitignore
@@ -0,0 +1,7 @@
+
+# These TBB libraries are copied in at configure time.
+/index.html
+/oneapi
+/serial
+/tbb
+
diff --git a/inst/include/RcppParallel.h b/inst/include/RcppParallel.h
index 9b7da04dd..87d6eb5ca 100644
--- a/inst/include/RcppParallel.h
+++ b/inst/include/RcppParallel.h
@@ -6,50 +6,76 @@
#include "RcppParallel/TinyThread.h"
// Use TBB only where it's known to compile and work correctly
-// (NOTE: Windows TBB is temporarily opt-in for packages for
+// (NOTE: Windows TBB is temporarily opt-in for packages for
// compatibility with CRAN packages not previously configured
// to link to TBB in Makevars.win)
#ifndef RCPP_PARALLEL_USE_TBB
-#if defined(__APPLE__) || defined(__gnu_linux__) || ((defined(__sun) && defined(__SVR4) && !defined(__sparc)))
-#define RCPP_PARALLEL_USE_TBB 1
-#include "RcppParallel/TBB.h"
-#else
-#define RCPP_PARALLEL_USE_TBB 0
-#endif
+# if defined(__APPLE__) || defined(__gnu_linux__) || (defined(__sun) && defined(__SVR4) && !defined(__sparc))
+# define RCPP_PARALLEL_USE_TBB 1
+# else
+# define RCPP_PARALLEL_USE_TBB 0
+# endif
#endif
#if RCPP_PARALLEL_USE_TBB
- #include "RcppParallel/TBB.h"
+# include "RcppParallel/TBB.h"
#endif
+#include "RcppParallel/Backend.h"
#include "RcppParallel/RVector.h"
#include "RcppParallel/RMatrix.h"
namespace RcppParallel {
-inline void parallelFor(std::size_t begin, std::size_t end,
- Worker& worker, std::size_t grainSize = 1) {
-
+inline void parallelFor(std::size_t begin,
+ std::size_t end,
+ Worker& worker,
+ std::size_t grainSize = 1,
+ int numThreads = -1)
+{
+ grainSize = resolveValue("RCPP_PARALLEL_GRAIN_SIZE", grainSize, std::size_t(1));
+ numThreads = resolveValue("RCPP_PARALLEL_NUM_THREADS", numThreads, -1);
+
#if RCPP_PARALLEL_USE_TBB
- tbbParallelFor(begin, end, worker, grainSize);
+ if (internal::backend() == internal::BACKEND_TBB)
+ tbbParallelFor(begin, end, worker, grainSize, numThreads);
+ else
+ ttParallelFor(begin, end, worker, grainSize);
#else
ttParallelFor(begin, end, worker, grainSize);
#endif
-
}
template
-inline void parallelReduce(std::size_t begin, std::size_t end,
- Reducer& reducer, std::size_t grainSize = 1) {
-
+inline void parallelReduce(std::size_t begin,
+ std::size_t end,
+ Reducer& reducer,
+ std::size_t grainSize = 1,
+ int numThreads = -1)
+{
+ grainSize = resolveValue("RCPP_PARALLEL_GRAIN_SIZE", grainSize, std::size_t(1));
+ numThreads = resolveValue("RCPP_PARALLEL_NUM_THREADS", numThreads, -1);
+
#if RCPP_PARALLEL_USE_TBB
- tbbParallelReduce(begin, end, reducer, grainSize);
+ if (internal::backend() == internal::BACKEND_TBB)
+ tbbParallelReduce(begin, end, reducer, grainSize, numThreads);
+ else
+ ttParallelReduce(begin, end, reducer, grainSize);
#else
ttParallelReduce(begin, end, reducer, grainSize);
#endif
-
}
-} // namespace RcppParallel
+} // end namespace RcppParallel
+
+// TRUE and FALSE macros that may come with system headers on some systems
+// But conflict with R.h (R_ext/Boolean.h)
+// TRUE and FALSE macros should be undef in RcppParallel.h
+#ifdef TRUE
+ #undef TRUE
+#endif
+#ifdef FALSE
+ #undef FALSE
+#endif
#endif // __RCPP_PARALLEL__
diff --git a/inst/include/RcppParallel/Backend.h b/inst/include/RcppParallel/Backend.h
new file mode 100644
index 000000000..13971b9e0
--- /dev/null
+++ b/inst/include/RcppParallel/Backend.h
@@ -0,0 +1,84 @@
+
+#ifndef __RCPP_PARALLEL_BACKEND__
+#define __RCPP_PARALLEL_BACKEND__
+
+#include
+#include
+
+extern "C" {
+void REprintf(const char*, ...);
+}
+
+namespace RcppParallel {
+namespace internal {
+
+enum backend_type {
+ BACKEND_TBB,
+ BACKEND_TINYTHREAD
+};
+
+#if RCPP_PARALLEL_USE_TBB
+
+inline backend_type defaultBackend()
+{
+ return BACKEND_TBB;
+}
+
+#else
+
+inline backend_type defaultBackend()
+{
+ return BACKEND_TINYTHREAD;
+}
+
+#endif
+
+inline const char* backendToString(backend_type backend)
+{
+ switch (backend)
+ {
+ case BACKEND_TBB:
+ return "tbb";
+ case BACKEND_TINYTHREAD:
+ return "tinythread";
+ }
+
+ // shouldn't be reached but need to silence compiler warnings
+ return "tbb";
+}
+
+inline backend_type backend()
+{
+ const char* requestedBackend = std::getenv("RCPP_PARALLEL_BACKEND");
+ if (requestedBackend == NULL)
+ {
+ return defaultBackend();
+ }
+ else if (std::strcmp(requestedBackend, "tbb") == 0)
+ {
+#if RCPP_PARALLEL_USE_TBB
+ return BACKEND_TBB;
+#else
+ const char* msg =
+ "tbb backend is not available; using tinythread instead";
+
+ REprintf("%s\n", msg);
+ return BACKEND_TINYTHREAD;
+#endif
+ }
+ else if (strcmp(requestedBackend, "tinythread") == 0)
+ {
+ return BACKEND_TINYTHREAD;
+ }
+ else
+ {
+ const char* fmt = "unknown parallel backend '%s'; using '%s' instead\n";
+ REprintf(fmt, requestedBackend, backendToString(defaultBackend()));
+ return defaultBackend();
+ }
+}
+
+} // namespace internal
+} // namespace RcppParallel
+
+#endif /* __RCPP_PARALLEL_BACKEND__ */
diff --git a/inst/include/RcppParallel/Common.h b/inst/include/RcppParallel/Common.h
index b14d3f0cb..ae2b1327d 100644
--- a/inst/include/RcppParallel/Common.h
+++ b/inst/include/RcppParallel/Common.h
@@ -1,34 +1,86 @@
#ifndef __RCPP_PARALLEL_COMMON__
#define __RCPP_PARALLEL_COMMON__
+#include
#include
+#include
+
+#include
+#include
+#include
+#include
namespace RcppParallel {
+template
+inline int resolveValue(const char* envvar,
+ T requestedValue,
+ U defaultValue)
+{
+ // if the requested value is non-zero and not the default, we can use it
+ bool useRequestedValue =
+ requestedValue != static_cast(defaultValue) &&
+ requestedValue > 0;
+
+ if (useRequestedValue)
+ return requestedValue;
+
+ // otherwise, try reading the default from associated envvar
+ // if the environment variable is unset, use the default
+ const char* var = getenv(envvar);
+ if (var == NULL)
+ return defaultValue;
+
+ // try to convert the string to a number
+ // if an error occurs during conversion, just use default
+ errno = 0;
+ char* end;
+ long value = strtol(var, &end, 10);
+
+ // check for conversion failure
+ if (end == var || *end != '\0' || errno == ERANGE)
+ return defaultValue;
+
+ // okay, return the parsed environment variable value
+ return value;
+}
+
+// Tag type used for disambiguating splitting constructors
+struct Split {};
+
// Work executed within a background thread. We implement dynamic
// dispatch using vtables so we can have a stable type to cast
// to from the void* passed to the worker thread (required because
// the tinythreads interface allows to pass only a void* to the
// thread main rather than a generic type / template)
-
-struct Worker
-{
+struct Worker
+{
// construct and destruct (delete virtually)
Worker() {}
virtual ~Worker() {}
-
+
// dispatch work over a range of values
- virtual void operator()(std::size_t begin, std::size_t end) = 0;
-
- // disable copying and assignment
+ virtual void operator()(std::size_t begin, std::size_t end) = 0;
+
private:
+ // disable copying and assignment
Worker(const Worker&);
void operator=(const Worker&);
};
-// Tag type used for disambiguating splitting constructors
+// Used for controlling the stack size for threads / tasks within a scope.
+class ThreadStackSizeControl
+{
+public:
+ ThreadStackSizeControl();
+ ~ThreadStackSizeControl();
+
+private:
+ // COPYING: not copyable
+ ThreadStackSizeControl(const ThreadStackSizeControl&);
+ ThreadStackSizeControl& operator=(const ThreadStackSizeControl&);
+};
-struct Split {};
} // namespace RcppParallel
diff --git a/inst/include/RcppParallel/RMatrix.h b/inst/include/RcppParallel/RMatrix.h
index f4d57c01a..576be720f 100644
--- a/inst/include/RcppParallel/RMatrix.h
+++ b/inst/include/RcppParallel/RMatrix.h
@@ -14,16 +14,21 @@ class RMatrix {
public:
template
- class row_iterator
- : public std::iterator {
+ class row_iterator {
public:
- inline row_iterator(Row& row, std::size_t i)
+ using iterator_category = std::random_access_iterator_tag;
+ using value_type = V;
+ using difference_type = std::size_t;
+ using pointer = value_type*;
+ using reference = value_type&;
+
+ inline row_iterator(Row& row, difference_type i)
: start_(row.start_), parentNrow_(row.parent_.nrow()), index_(i)
{
}
- inline row_iterator(std::size_t start, std::size_t parentNrow, std::size_t index)
+ inline row_iterator(pointer start, difference_type parentNrow, difference_type index)
: start_(start), parentNrow_(parentNrow), index_(index)
{
}
@@ -57,23 +62,23 @@ class RMatrix {
return tmp ;
}
- row_iterator operator+(std::size_t n) const {
+ row_iterator operator+(difference_type n) const {
return row_iterator(start_, parentNrow_ ,index_ + n ) ;
}
- row_iterator operator-(std::size_t n) const {
+ row_iterator operator-(difference_type n) const {
return row_iterator(start_, parentNrow_, index_ - n ) ;
}
- std::size_t operator+(const row_iterator& other) const {
+ difference_type operator+(const row_iterator& other) const {
return index_ + other.index_;
}
- std::size_t operator-(const row_iterator& other) const {
+ difference_type operator-(const row_iterator& other) const {
return index_ - other.index_ ;
}
- row_iterator& operator+=(std::size_t n) { index_ += n ; return *this; }
- row_iterator& operator-=(std::size_t n) { index_ -= n ; return *this; }
+ row_iterator& operator+=(difference_type n) { index_ += n ; return *this; }
+ row_iterator& operator-=(difference_type n) { index_ -= n ; return *this; }
bool operator==(const row_iterator& other) const { return index_ == other.index_; }
bool operator!=(const row_iterator& other) const { return index_ != other.index_; }
@@ -83,16 +88,16 @@ class RMatrix {
bool operator>=(const row_iterator& other) const { return index_ >= other.index_; }
- inline V& operator*() { return start_[index_ * parentNrow_]; }
+ inline reference operator*() { return start_[index_ * parentNrow_]; }
- inline V* operator->() { return &(start_[index_ * parentNrow_]); }
+ inline pointer operator->() { return &(start_[index_ * parentNrow_]); }
- inline V& operator[](int i) { return start_[(index_+i) * parentNrow_]; }
+ inline reference operator[](int i) { return start_[(index_+i) * parentNrow_]; }
private:
- V* start_;
- std::size_t parentNrow_;
- std::size_t index_;
+ pointer start_;
+ difference_type parentNrow_;
+ difference_type index_;
};
typedef row_iterator iterator;
@@ -204,7 +209,7 @@ class RMatrix {
{
}
- inline RMatrix(const T* data, std::size_t nrow, std::size_t ncol)
+ inline RMatrix(T* data, std::size_t nrow, std::size_t ncol)
: data_(data), nrow_(nrow), ncol_(ncol)
{
}
diff --git a/inst/include/RcppParallel/TBB.h b/inst/include/RcppParallel/TBB.h
index 0d72178bb..5ac5722d8 100644
--- a/inst/include/RcppParallel/TBB.h
+++ b/inst/include/RcppParallel/TBB.h
@@ -3,74 +3,162 @@
#include "Common.h"
-#include
-#include
+#ifndef TBB_PREVIEW_GLOBAL_CONTROL
+# define TBB_PREVIEW_GLOBAL_CONTROL 1
+#endif
-namespace RcppParallel {
+// For compatibility with existing packages on CRAN.
+#include "tbb/blocked_range.h"
+#include "tbb/concurrent_unordered_set.h"
+#include "tbb/concurrent_unordered_map.h"
+#include "tbb/global_control.h"
+#include "tbb/mutex.h"
+#include "tbb/parallel_for.h"
+#include "tbb/parallel_for_each.h"
+#include "tbb/parallel_reduce.h"
+#include "tbb/parallel_sort.h"
+#include "tbb/spin_mutex.h"
-namespace {
+// For compatibility with older R packages.
+namespace tbb {
-struct TBBWorker
-{
- explicit TBBWorker(Worker& worker) : worker_(worker) {}
+#ifndef __TBB_task_scheduler_init_H
+#define __TBB_task_scheduler_init_H
+
+class task_scheduler_init {
- void operator()(const tbb::blocked_range& r) const {
- worker_(r.begin(), r.end());
+public:
+ task_scheduler_init(
+ int number_of_threads = -1,
+ std::size_t stack_size = 0)
+ {
}
-
-private:
- Worker& worker_;
+
+ static int default_num_threads()
+ {
+ return 2;
+ }
+
+ static const int automatic = -1;
+ static const int deferred = -2;
+
};
-template
-struct TBBReducer
-{
- explicit TBBReducer(Reducer& reducer)
- : pSplitReducer_(NULL), reducer_(reducer)
+#endif
+
+} // end namespace tbb
+
+
+namespace RcppParallel {
+
+// This class is primarily used to implement type erasure. The goals here were:
+//
+// 1. Hide the tbb symbols / implementation details from client R packages.
+// That is, they should get the tools they need only via RcppParallel.
+//
+// 2. Do this in a way that preserves binary compatibility with pre-existing
+// classes that make use of parallelReduce().
+//
+// 3. Ensure that those packages, when re-compiled without source changes,
+// can still function as expected.
+//
+// The downside here is that all the indirection through std::function<>
+// and the requirement for RTTI is probably expensive, but I couldn't find
+// a better way forward that could also preserve binary compatibility with
+// existing pre-built pacakges.
+//
+// Hopefully, in a future release, we can do away with this wrapper, once
+// packages have been rebuilt and no longer implicitly depend on TBB internals.
+struct ReducerWrapper {
+
+ template
+ ReducerWrapper(T* reducer)
+ {
+ self_ = reinterpret_cast(reducer);
+ owned_ = false;
+
+ work_ = [&](void* self, std::size_t begin, std::size_t end)
+ {
+ (*reinterpret_cast(self))(begin, end);
+ };
+
+ split_ = [&](void* object, Split split)
+ {
+ return new T(*reinterpret_cast(object), split);
+ };
+
+ join_ = [&](void* self, void* other)
+ {
+ (*reinterpret_cast(self)).join(*reinterpret_cast(other));
+ };
+
+ deleter_ = [&](void* object)
+ {
+ delete (T*) object;
+ };
+ }
+
+ ~ReducerWrapper()
{
+ if (owned_)
+ {
+ deleter_(self_);
+ self_ = nullptr;
+ }
}
-
- TBBReducer(TBBReducer& tbbReducer, tbb::split)
- : pSplitReducer_(new Reducer(tbbReducer.reducer_, RcppParallel::Split())),
- reducer_(*pSplitReducer_)
+
+ void operator()(std::size_t begin, std::size_t end) const
{
+ work_(self_, begin, end);
}
-
- virtual ~TBBReducer() { delete pSplitReducer_; }
- void operator()(const tbb::blocked_range& r) {
- reducer_(r.begin(), r.end());
+ ReducerWrapper(const ReducerWrapper& rhs, Split split)
+ {
+ self_ = rhs.split_(rhs.self_, split);
+ owned_ = true;
+
+ work_ = rhs.work_;
+ split_ = rhs.split_;
+ join_ = rhs.join_;
+ deleter_ = rhs.deleter_;
}
-
- void join(const TBBReducer& tbbReducer) {
- reducer_.join(tbbReducer.reducer_);
+
+ void join(const ReducerWrapper& rhs) const
+ {
+ join_(self_, rhs.self_);
}
-
+
private:
- Reducer* pSplitReducer_;
- Reducer& reducer_;
+ void* self_ = nullptr;
+ bool owned_ = false;
+
+ std::function work_;
+ std::function split_;
+ std::function join_;
+ std::function deleter_;
};
-
-} // anonymous namespace
+void tbbParallelFor(std::size_t begin,
+ std::size_t end,
+ Worker& worker,
+ std::size_t grainSize = 1,
+ int numThreads = -1);
-inline void tbbParallelFor(std::size_t begin, std::size_t end,
- Worker& worker, std::size_t grainSize = 1) {
-
- TBBWorker tbbWorker(worker);
-
- tbb::parallel_for(tbb::blocked_range(begin, end, grainSize),
- tbbWorker);
-}
+void tbbParallelReduceImpl(std::size_t begin,
+ std::size_t end,
+ ReducerWrapper& wrapper,
+ std::size_t grainSize = 1,
+ int numThreads = -1);
template
-inline void tbbParallelReduce(std::size_t begin, std::size_t end,
- Reducer& reducer, std::size_t grainSize = 1) {
-
- TBBReducer tbbReducer(reducer);
-
- tbb::parallel_reduce(tbb::blocked_range(begin, end, grainSize),
- tbbReducer);
+void tbbParallelReduce(std::size_t begin,
+ std::size_t end,
+ Reducer& reducer,
+ std::size_t grainSize = 1,
+ int numThreads = -1)
+{
+ ReducerWrapper wrapper(&reducer);
+ tbbParallelReduceImpl(begin, end, wrapper, grainSize, numThreads);
}
} // namespace RcppParallel
diff --git a/inst/include/RcppParallel/TinyThread.h b/inst/include/RcppParallel/TinyThread.h
index 54d55b310..dfa3dcb73 100644
--- a/inst/include/RcppParallel/TinyThread.h
+++ b/inst/include/RcppParallel/TinyThread.h
@@ -2,12 +2,12 @@
#define __RCPP_PARALLEL_TINYTHREAD__
#include
+#include
#include "Common.h"
#include
-#include
#include
@@ -89,10 +89,15 @@ std::vector splitInputRange(const IndexRange& range,
// allocate ranges
std::vector ranges;
std::size_t begin = range.begin();
+ std::size_t end = begin;
while (begin < range.end()) {
- std::size_t end = std::min(begin + grainSize, range.end());
- ranges.push_back(IndexRange(begin, end));
- begin = end;
+ if ((range.end() - (begin + grainSize)) < grainSize)
+ end = range.end();
+ else
+ end = std::min(begin + grainSize, range.end());
+
+ ranges.push_back(IndexRange(begin, end));
+ begin = end;
}
// return ranges
@@ -102,19 +107,19 @@ std::vector splitInputRange(const IndexRange& range,
} // anonymous namespace
// Execute the Worker over the IndexRange in parallel
-inline void ttParallelFor(std::size_t begin, std::size_t end,
- Worker& worker, std::size_t grainSize = 1) {
-
- using namespace tthread;
-
+inline void ttParallelFor(std::size_t begin,
+ std::size_t end,
+ Worker& worker,
+ std::size_t grainSize = 1)
+{
// split the work
IndexRange inputRange(begin, end);
std::vector ranges = splitInputRange(inputRange, grainSize);
// create threads
- std::vector threads;
+ std::vector threads;
for (std::size_t i = 0; i
-inline void ttParallelReduce(std::size_t begin, std::size_t end,
- Reducer& reducer, std::size_t grainSize = 1) {
-
- using namespace tthread;
-
+inline void ttParallelReduce(std::size_t begin,
+ std::size_t end,
+ Reducer& reducer,
+ std::size_t grainSize = 1)
+{
// split the work
IndexRange inputRange(begin, end);
std::vector ranges = splitInputRange(inputRange, grainSize);
// create threads (split for each thread and track the allocated workers)
- std::vector threads;
+ std::vector threads;
std::vector workers;
for (std::size_t i = 0; i
-
-
-Overview
-Include files for Intel® Threading Building Blocks (Intel® TBB).
-
-Directories
-
-- tbb
-
- Include files for Intel TBB classes and functions.
-
- serial/tbb
-
- Include files for a sequential implementation of the parallel_for algorithm.
-
-
-
-Up to parent directory
-
-Copyright © 2005-2017 Intel Corporation. All Rights Reserved.
-
-Intel is a registered trademark or trademark of Intel Corporation
-or its subsidiaries in the United States and other countries.
-
-* Other names and brands may be claimed as the property of others.
-
-