Skip to content

Commit

Permalink
interim release to help with future binary compatibility (#234)
Browse files Browse the repository at this point in the history
* rearrange a bit

* no more inline stack size control

* move parallel-for stuff into cpp

* move parallel reducer out of header

* revert some test changes

* prepare for release

* need to link to RcppParallel in plugin on Windows

* compiler warnings

* Update DESCRIPTION
  • Loading branch information
kevinushey authored Jan 28, 2025
1 parent 0b136ce commit 762a579
Show file tree
Hide file tree
Showing 13 changed files with 433 additions and 304 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: RcppParallel
Type: Package
Title: Parallel Programming Tools for 'Rcpp'
Version: 5.1.9.9000
Version: 5.1.10.9000
Authors@R: c(
person("Kevin", "Ushey", role = c("aut", "cre"), email = "[email protected]",
comment = c(ORCID = "0000-0003-2880-7407")),
Expand Down
6 changes: 6 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
implementation. In practice, this implies that RcppParallel will now only
provide a TBB backend with R (>= 4.2.0).

## 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.
Expand Down
18 changes: 9 additions & 9 deletions R/flags.R
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@

#' 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).
#'
Expand Down
38 changes: 19 additions & 19 deletions R/tbb.R
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@

#' 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( name, ".dll"),
"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) {
Expand All @@ -49,12 +49,12 @@ tbbLibraryPath <- function(name = NULL) {
return(tbbName)

}

}

tbbCxxFlags <- function() {
if (!TBB_ENABLED)

if (!TBB_ENABLED)
return("-DRCPP_PARALLEL_USE_TBB=0")

flags <- c("-DRCPP_PARALLEL_USE_TBB=1")
Expand All @@ -66,7 +66,7 @@ tbbCxxFlags <- function() {
flags <- c(flags, "-DTBB_USE_GCC_BUILTINS")
}
}

# if TBB_INC is set, apply those library paths
tbbInc <- Sys.getenv("TBB_INC", unset = TBB_INC)
if (!file.exists(tbbInc)) {
Expand All @@ -86,10 +86,10 @@ tbbCxxFlags <- function() {
flags <- c(flags, paste0("-I", asBuildPath(tbbInc)))

}

# return flags as string
paste(flags, collapse = " ")

}

# Return the linker flags required for TBB on this platform
Expand Down Expand Up @@ -120,20 +120,20 @@ tbbLdFlags <- function() {
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")

}
2 changes: 1 addition & 1 deletion R/zzz.R
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ loadTbbLibrary <- function(name) {

# load RcppParallel library if available
if (.Platform$OS.type != "windows") {
.dllInfo <<- library.dynam("RcppParallel", pkgname, libname)
.dllInfo <<- library.dynam("RcppParallel", pkgname, libname, local = FALSE)
}

}
Expand Down
5 changes: 4 additions & 1 deletion RcppParallel.Rproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ Encoding: UTF-8
RnwWeave: Sweave
LaTeX: pdfLaTeX

AutoAppendNewline: Yes
StripTrailingWhitespace: Yes

BuildType: Package
PackageCleanBeforeInstall: No
PackageInstallArgs: --with-keep.source --clean
PackageInstallArgs: --with-keep.source
PackageCheckArgs: --as-cran
PackageRoxygenize: rd,collate,namespace
14 changes: 7 additions & 7 deletions inst/include/RcppParallel.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#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
Expand All @@ -31,14 +31,14 @@
namespace RcppParallel {

inline void parallelFor(std::size_t begin,
std::size_t end,
std::size_t end,
Worker& worker,
std::size_t grainSize = 1,
int numThreads = -1)
{
grainSize = resolveValue("RCPP_PARALLEL_GRAIN_SIZE", grainSize, 1u);
grainSize = resolveValue("RCPP_PARALLEL_GRAIN_SIZE", grainSize, std::size_t(1));
numThreads = resolveValue("RCPP_PARALLEL_NUM_THREADS", numThreads, -1);

#if RCPP_PARALLEL_USE_TBB
if (internal::backend() == internal::BACKEND_TBB)
tbbParallelFor(begin, end, worker, grainSize, numThreads);
Expand All @@ -51,14 +51,14 @@ inline void parallelFor(std::size_t begin,

template <typename Reducer>
inline void parallelReduce(std::size_t begin,
std::size_t end,
std::size_t end,
Reducer& reducer,
std::size_t grainSize = 1,
int numThreads = -1)
{
grainSize = resolveValue("RCPP_PARALLEL_GRAIN_SIZE", grainSize, 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
if (internal::backend() == internal::BACKEND_TBB)
tbbParallelReduce(begin, end, reducer, grainSize, numThreads);
Expand Down
40 changes: 26 additions & 14 deletions inst/include/RcppParallel/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,51 +19,63 @@ inline int resolveValue(const char* envvar,

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

// 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

Expand Down
Loading

0 comments on commit 762a579

Please sign in to comment.