Skip to content

Commit befe4d0

Browse files
committed
Merge pull request #12 from RcppCore/feature/windows-tbb
Enable support for TBB on windows
2 parents 29ab791 + 538323c commit befe4d0

File tree

15 files changed

+248
-78
lines changed

15 files changed

+248
-78
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
.Rhistory
33
.RData
44
.DS_Store
5+
src-i386/
6+
src-x64/

DESCRIPTION

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
Package: RcppParallel
22
Type: Package
33
Title: Parallel Programming Tools for Rcpp
4-
Version: 4.3.3
5-
Date: 2014-10-20
6-
Author: JJ Allaire; Romain Francois; Intel, Inc.; Marcus Geelnard
7-
Maintainer: JJ Allaire <[email protected]>
4+
Version: 4.3.4
5+
Date: 2015-04-04
6+
Authors@R: c(
7+
person("JJ", "Allaire", role = c("aut", "cre"), email = "[email protected]"),
8+
person("Romain", "Francois", role = c("aut", "cph")),
9+
person("Gregory", "Vandenbrouck", role = "aut"),
10+
person("Marcus", "Geelnard", role = c("aut", "cph"),
11+
comment = "TinyThread library, http://tinythreadpp.bitsnbites.eu/"),
12+
person(family = "RStudio", role = "cph"),
13+
person(family = "Intel", role = c("aut", "cph"),
14+
comment = "Intel TBB library, https://www.threadingbuildingblocks.org/"),
15+
person(family = "Microsoft", role = "cph")
16+
)
817
Description: High level functions for doing parallel programming with Rcpp.
918
For example, the parallelFor function can be used to convert the work of
1019
a standard serial "for" loop into a parallel one and the parallelReduce
@@ -13,5 +22,7 @@ Suggests: Rcpp, testthat
1322
SystemRequirements: GNU make
1423
License: GPL-2
1524
Collate:
25+
'build.R'
26+
'hooks.R'
1627
'options.R'
1728

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export(setThreadOptions)
22
export(defaultNumThreads)
3+
export(RcppParallelLibs)
34

NEWS

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
RcppParallel 4.3.1
1+
RcppParallel 4.3.4
2+
------------------------------------------------------------------------
3+
4+
* Support for TBB on Windows
5+
6+
RcppParallel 4.3.3
27
------------------------------------------------------------------------
38

49
* Update to TBB 4.3 (fixes clang compilation error in platform.h)

R/build.R

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
2+
3+
# Output the LD flags for building against TBB. These flags are propagated
4+
# to sourceCpp via the inlineCxxPlugin (defined below) and to packages
5+
# via a line in Makevars.win like this:
6+
#
7+
# PKG_LIBS += $(shell "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "RcppParallel::LdFlags()")
8+
#
9+
# Note that this is only required for Windows builds (on Linux and OS X no
10+
# explicit link to TBB is required).
11+
RcppParallelLibs <- function() {
12+
cat(tbbLdFlags())
13+
}
14+
15+
16+
# Inline plugin used by sourceCpp to link to the TBB library
17+
inlineCxxPlugin <- function() {
18+
list(
19+
env = list(PKG_LIBS = tbbLdFlags()),
20+
includes = "#include <RcppParallel.h>",
21+
LinkingTo = "RcppParallel",
22+
body = function( x ) x,
23+
Depends = "RcppParallel"
24+
)
25+
}
26+
27+
28+
# Return the linker flags requried for TBB on this platform
29+
tbbLdFlags <- function() {
30+
# on Windows we need to explicitly link against tbb.dll
31+
if (Sys.info()['sysname'] == "Windows") {
32+
tbb <- tbbLibPath()
33+
paste("-L", asBuildPath(dirname(tbb)), " -ltbb", sep="")
34+
} else {
35+
""
36+
}
37+
}
38+
39+
40+
# Determine the platform-specific path to the TBB library
41+
tbbLibPath <- function() {
42+
sysname <- Sys.info()['sysname']
43+
tbbSupported <- list(
44+
"Darwin" = "libtbb.dylib",
45+
"Linux" = "libtbb.so.2",
46+
"Windows" = "tbb.dll"
47+
)
48+
if (sysname %in% names(tbbSupported)) {
49+
libDir <- "lib/"
50+
if (sysname == "Windows")
51+
libDir <- paste(libDir, .Platform$r_arch, "/", sep="")
52+
system.file(paste(libDir, tbbSupported[[sysname]], sep = ""),
53+
package = "RcppParallel")
54+
} else {
55+
NULL
56+
}
57+
}
58+
59+
60+
# Helper function to ape the behavior of the R build system
61+
# when providing paths to libraries
62+
asBuildPath <- function(path) {
63+
if (.Platform$OS.type == "windows") {
64+
path <- normalizePath(path)
65+
if (grepl(' ', path, fixed=TRUE))
66+
path <- utils::shortPathName(path)
67+
path <- gsub("\\\\", "/", path)
68+
}
69+
return(path)
70+
}

R/hooks.R

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
dllInfo <- NULL
3+
4+
5+
.onLoad <- function(libname, pkgname) {
6+
7+
# load tbb on supported platforms
8+
tbb <- tbbLibPath()
9+
if (!is.null(tbb)) {
10+
if (!file.exists(tbb)) {
11+
warning(paste("TBB library", tbb, "not found."))
12+
} else {
13+
dllInfo <<- dyn.load(tbb, local = FALSE, now = TRUE)
14+
}
15+
}
16+
17+
# load the package library
18+
library.dynam("RcppParallel", pkgname, libname)
19+
20+
# set default thread options
21+
setThreadOptions()
22+
}
23+
24+
.onUnload <- function(libpath) {
25+
26+
# unload the package library
27+
library.dynam.unload("RcppParallel", libpath)
28+
29+
# unload tbb if we loaded it
30+
if (!is.null(dllInfo))
31+
dyn.unload(dllInfo[["path"]])
32+
}

R/options.R

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,5 @@
11

22

3-
dllInfo <- NULL
4-
5-
.onLoad <- function(libname, pkgname) {
6-
7-
# load tbb if we aren't on windows
8-
sysname <- Sys.info()['sysname']
9-
if (sysname %in% c("Linux", "Darwin")) {
10-
if (sysname == "Darwin")
11-
ext = ".dylib"
12-
else if (sysname == "Linux")
13-
ext = ".so.2"
14-
dll <- system.file(paste("lib/libtbb", ext, sep = ""), package = "RcppParallel")
15-
dllInfo <<- dyn.load(dll, local = FALSE, now = TRUE)
16-
}
17-
18-
# load the package library
19-
library.dynam("RcppParallel", pkgname, libname)
20-
21-
# set default thread options
22-
setThreadOptions()
23-
}
24-
25-
.onUnload <- function(libpath) {
26-
27-
# unload the package library
28-
library.dynam.unload("RcppParallel", libpath)
29-
30-
# unload tbb if we loaded it (i.e. aren't on windows)
31-
if (!is.null(dllInfo))
32-
dyn.unload(dllInfo[["path"]])
33-
}
34-
353
setThreadOptions <- function(numThreads = "auto", stackSize = "auto") {
364

375
# validate and resolve numThreads
@@ -50,7 +18,8 @@ setThreadOptions <- function(numThreads = "auto", stackSize = "auto") {
5018
else
5119
stackSize <- as.integer(stackSize)
5220

53-
if (Sys.info()['sysname'] %in% c("Linux", "Darwin")) {
21+
# Call setThreadOptions if using tbb
22+
if (!is.null(dllInfo)) {
5423
invisible(.Call("setThreadOptions", numThreads, stackSize,
5524
PACKAGE = "RcppParallel"))
5625
}

README.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
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.
44

5-
The high level interface enables safe and robust parallel programming without direct manipulation of operating system threads. The underlying implementation differs by platform: on Linux and Mac systems the [Intel TBB](https://www.threadingbuildingblocks.org/) (Threading Building Blocks) are used while on Windows systems the [TinyThread](http://tinythreadpp.bitsnbites.eu/) library is used.
5+
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.
66

77
### Examples
88

@@ -16,8 +16,6 @@ Here are links to some examples that illustrate using RcppParallel. Performance
1616

1717
[Parallel Inner Product](http://gallery.rcpp.org/articles/parallel-inner-product/) --- Demonstrates using `parallelReduce` to compute the inner product of two vectors in parallel. In this example the parallel version performs 2.5x faster than the serial version.
1818

19-
Note that the benchmark times above are for the TBB back-end (Posix systems only). Performance on Windows will be about 30-50% slower as a result of less sophisticated thread scheduling.
20-
2119
### Usage
2220

2321
You can install the RcppParallel package from CRAN as follows:
@@ -37,17 +35,25 @@ You can use the RcppParallel library from within a standalone C++ source file as
3735

3836
#### Packages
3937

40-
If you want to use RcppParallel from within an R package you add the following to your DESCRIPTION file:
38+
If you want to use RcppParallel from within an R package you add the following to your **DESCRIPTION** file:
4139

4240
```yaml
4341
Imports: RcppParallel
4442
LinkingTo: RcppParallel
4543
```
4644
47-
And the following to your NAMESPACE file:
45+
And the following to your **NAMESPACE** file:
4846
49-
```s
50-
import(RcppParallel)
47+
```R
48+
importFrom(RcppParallel, RcppParallelLibs)
49+
```
50+
51+
Finally, for Windows builds you'll need the following in **src\\Makevars.win**
52+
to ensure that your package can link against the TBB DLL:
53+
54+
```makefile
55+
PKG_LIBS += $(shell "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" \
56+
-e "RcppParallel::RcppParallelLibs()")
5157
```
5258

5359
### License

inst/include/RcppParallel.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,16 @@
77

88
// Use TBB only where it's known to compile and work correctly
99
#ifndef RCPP_PARALLEL_USE_TBB
10-
#if defined(__APPLE__) || defined(__gnu_linux__)
11-
#define RCPP_PARALLEL_USE_TBB 1
12-
#include "RcppParallel/TBB.h"
10+
#if defined(_WIN32) || defined(__APPLE__) || defined(__gnu_linux__)
11+
#define RCPP_PARALLEL_USE_TBB 1
12+
#include "RcppParallel/TBB.h"
1313
#else
14-
#define RCPP_PARALLEL_USE_TBB 0
14+
#define RCPP_PARALLEL_USE_TBB 0
15+
#endif
1516
#endif
17+
18+
#if RCPP_PARALLEL_USE_TBB
19+
#include "RcppParallel/TBB.h"
1620
#endif
1721

1822
#include "RcppParallel/RVector.h"

man/RcppParallelLibs.Rd

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
\name{RcppParallelLibs}
2+
\alias{RcppParallelLibs}
3+
\alias{RcppParallelLibs}
4+
\title{
5+
Linker flags for RcppParallel
6+
}
7+
\description{
8+
Output the linker flags required to link to RcppParallel. On
9+
Windows this includes the underlying TBB library, on other
10+
platforms no linker flags are required.
11+
}
12+
\usage{
13+
RcppParallelLibs()
14+
}
15+
\details{
16+
This function is typically called from \code{Makevars.win} as follows:
17+
18+
\code{PKG_LIBS += $(shell "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "RcppParallel::RcppParallelLibs()")}
19+
20+
}
21+
22+
\value{
23+
Returns \code{NULL} invisibly. The function is not called for it's
24+
return value rather for the side effect of outputting the linker
25+
flags.
26+
}
27+

src/Makevars

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,67 @@ CXX_STD = CXX11
33

44
PKG_CPPFLAGS += -I../inst/include/
55

6-
UNAME := $(shell uname)
6+
ifeq ($(OS), Windows_NT)
7+
8+
USE_TBB=Windows
9+
TBB_COPY_PATTERN=tbb.dll
10+
11+
else
12+
13+
UNAME := $(shell uname)
14+
TBB_COPY_PATTERN=libtbb.*
15+
ifeq ($(UNAME), Darwin)
16+
USE_TBB=Mac
17+
endif
18+
ifeq ($(UNAME), Linux)
19+
USE_TBB=Linux
20+
endif
21+
# Note: regular MinGW not supported
722

8-
ifeq ($(UNAME), Darwin)
9-
USE_TBB=yes
10-
endif
11-
ifeq ($(UNAME), Linux)
12-
USE_TBB=yes
1323
endif
1424

1525
ifdef USE_TBB
1626

27+
MAKE_ARGS := CXXFLAGS=-DTBB_NO_LEGACY=1 tbb_release tbb_build_prefix=lib
28+
29+
# What I really want is startswith but this doesn't appear to be available
30+
ifneq (,$(findstring clang,$(CC)))
31+
MAKE_ARGS += compiler=clang
32+
33+
endif
34+
35+
ifeq ($(USE_TBB), Windows)
36+
37+
# rtools: turn on hacks to compensate for make and shell differences rtools<=>MinGW
38+
# compiler: overwrite default (which is cl = MS compiler)
39+
MAKE_ARGS += rtools=true compiler=gcc
40+
ifeq ("$(WIN)", "64")
41+
# TBB defaults to ia32
42+
MAKE_ARGS += arch=intel64
43+
ARCH_DIR="x64/"
44+
else
45+
ARCH_DIR="i386/"
46+
endif
47+
48+
# Linker needs access to the tbb dll; otherwise you get errors such as:
49+
# "undefined reference to `tbb::task_scheduler_init::terminate()'"
50+
PKG_LIBS += -L../inst/lib/$(ARCH_DIR) -ltbb
51+
52+
endif
53+
1754
.PHONY: all tbb
1855

19-
all: $(SHLIB) tbb
56+
# Order is important in Windows' case. See PKG_LIBS above
57+
all: tbb $(SHLIB)
2058

2159
tbb:
22-
mkdir -p ../inst/lib
23-
if [[ "$(CC)" == clang* ]]; then \
24-
(cd tbb/src; make compiler=clang CXXFLAGS=-DTBB_NO_LEGACY=1 tbb_release tbb_build_prefix=lib) \
25-
else \
26-
(cd tbb/src; make CXXFLAGS=-DTBB_NO_LEGACY=1 tbb_release tbb_build_prefix=lib) \
27-
fi
28-
cp tbb/build/lib_release/libtbb.* ../inst/lib
60+
mkdir -p ../inst/lib/$(ARCH_DIR)
61+
( cd tbb/src; make $(MAKE_ARGS) )
62+
cp tbb/build/lib_release/$(TBB_COPY_PATTERN) ../inst/lib/$(ARCH_DIR)
2963

3064
clean:
3165
(cd tbb/src; make clean)
3266

3367
endif
3468

3569

36-

src/Makevars.win

Lines changed: 0 additions & 6 deletions
This file was deleted.

0 commit comments

Comments
 (0)