-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit cbd2bf6
Showing
19 changed files
with
1,338 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
Package: rcpptimer | ||
Type: Package | ||
Title: 'Rcpp' Tic-Toc Timer with 'OpenMP' Support | ||
Version: 1.0.0 | ||
Date: 2024-02-29 | ||
Authors@R: c( | ||
person(given = "Jonathan", | ||
family = "Berrisch", | ||
role = c("aut", "cre"), | ||
email = "Jonathan@Berrisch.biz", | ||
comment = c(ORCID = "0000-0002-4944-9074"))) | ||
Description: Provides 'Rcpp' bindings for 'cpptimer', a simple tic-toc timer class for benchmarking 'C++' code <https://github.com/BerriJ/cpptimer>. It's not just simple, it's blazing fast! This sleek tic-toc timer class supports overlapping timers as well as 'OpenMP' parallelism <https://www.openmp.org/>. It boasts a microsecond-level time resolution. We did not find any overhead of the timer itself at this resolution. Results (with summary statistics) are automatically passed back to 'R' as a data frame. | ||
URL: https://rcpptimer.berrisch.biz | ||
License: GPL (>= 3) | ||
Encoding: UTF-8 | ||
Imports: Rcpp | ||
LinkingTo: Rcpp | ||
RoxygenNote: 7.3.1 | ||
Suggests: testthat (>= 3.0.0) | ||
Config/testthat/edition: 3 | ||
Language: en-US | ||
NeedsCompilation: yes | ||
Packaged: 2024-03-01 20:00:04 UTC; vscode | ||
Author: Jonathan Berrisch [aut, cre] (<https://orcid.org/0000-0002-4944-9074>) | ||
Maintainer: Jonathan Berrisch <Jonathan@Berrisch.biz> | ||
Repository: CRAN | ||
Date/Publication: 2024-03-05 10:40:06 UTC |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
faadeca883cf56b7ff67ffeebc23a481 *DESCRIPTION | ||
4aabfcbf4e92208542829bf4a45e35e8 *NAMESPACE | ||
1de59792b871d8882d4c4fc6f17bc02f *NEWS.md | ||
9d01228e1641aa7ebc5f2df4c3c1dbb0 *R/RcppExports.R | ||
11e706f16d1b0fb731d81f601a64ada0 *R/package.R | ||
7b21a0d9234e44a9e6f3ef4c44f685d5 *README.md | ||
1ebbd3e34237af26da5dc08a4e440464 *inst/include/cpptimer/LICENSE | ||
69cbb9e2f794d1bb44a5d6e2e0950257 *inst/include/cpptimer/README.md | ||
cdf9c2e54a4e914fc11ec1c0ff2ca818 *inst/include/cpptimer/cpptimer.h | ||
cf9438d029787dce91ce358a527a7363 *inst/include/rcpptimer.h | ||
c8d6802f3df1d9760f2b15c6c9c8daaf *man/fibonacci.Rd | ||
cf65a98fcf724a50385ac378116e9dbe *man/fibonacci_omp.Rd | ||
ce2c3134cfc6f3f344e98ad6d5022d2f *src/Makevars | ||
657ceb64c962dd262d085de9668f8d96 *src/Makevars.win | ||
611eecf22c6f401e51563dfe193c2937 *src/RcppExports.cpp | ||
a40d192f45e09c4c24ed4c1fae5dea67 *src/fibonacci.cpp | ||
f3bd93b3a3c8ae369ab2c835fd29d796 *tests/testthat.R | ||
aae583fe9843ab060a90875a08aba5d7 *tests/testthat/test_rcppclock.R |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Generated by roxygen2: do not edit by hand | ||
|
||
export(fibonacci) | ||
export(fibonacci_omp) | ||
import(Rcpp) | ||
useDynLib(rcpptimer, .registration = TRUE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
rcpptimer 1.0.0 | ||
============== | ||
|
||
This is the initial release of `rcpptimer`. It is based on `RcppClock` but contains a number of improvements: | ||
- OpenMP support | ||
- Auomatically returns results to R as soon as the C++ Object goes out of scope | ||
- Fast computation of Mean and Standard Deviation of the results in C++ | ||
- Uses `tic` and `toc` instead of `tick` and `tock` to be consistent with R's `tictoc` package | ||
- Allways reports microseconds resolution | ||
- Many more performance improvements |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Generated by using Rcpp::compileAttributes() -> do not edit by hand | ||
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 | ||
|
||
#' Simple rcpptimer example | ||
#' | ||
#' Time the computation of Fibonacci numbers | ||
#' | ||
#' @details | ||
#' The function being timed is the following: | ||
#' | ||
#' \code{int fib(int n) { return ((n <= 1) ? n : fib(n - 1) + fib(n - 2)); }} | ||
#' | ||
#' Runtime for computations less than \code{n = 15} is nearly unmeasurable. | ||
#' | ||
#' @param n vector giving integers for which to compute the Fibonacci sum | ||
#' @return vector of integers giving the Fibonacci sum for each element in | ||
#' \code{n} | ||
#' @export | ||
#' @examples | ||
#' \donttest{ | ||
#' fibonacci(n = rep(10*(1:4), 10)) | ||
#' # this function creates a global environment variable "times" | ||
#' times | ||
#' } | ||
fibonacci <- function(n) { | ||
.Call(`_rcpptimer_fibonacci`, n) | ||
} | ||
|
||
#' Simple rcpptimer example using OpenMP | ||
#' | ||
#' Time the multithreaded computation of Fibonacci numbers | ||
#' | ||
#' @details | ||
#' The function being timed is the following: | ||
#' | ||
#' \code{int fib(int n) { return ((n <= 1) ? n : fib(n - 1) + fib(n - 2)); }} | ||
#' | ||
#' Runtime for computations less than \code{n = 15} is nearly unmeasurable. | ||
#' | ||
#' @param n vector giving integers for which to compute the Fibonacci sum | ||
#' @return vector of integers giving the Fibonacci sum for each element in | ||
#' \code{n} | ||
#' @export | ||
#' @examples | ||
#' \donttest{ | ||
#' fibonacci_omp(n = rep(10*(1:4), 10)) | ||
#' # this function creates a global environment variable "times" | ||
#' times | ||
#' } | ||
fibonacci_omp <- function(n) { | ||
.Call(`_rcpptimer_fibonacci_omp`, n) | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## usethis namespace: start | ||
#' @useDynLib rcpptimer, .registration = TRUE | ||
#' @import Rcpp | ||
## usethis namespace: end | ||
NULL |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
# RcppTimeR - Rcpp Tic-Toc Timer with OpenMP Support | ||
|
||
This R Package provides Rcpp bindings for [cpptimer](https://github.com/BerriJ/cpptimer), a simple tic-toc timer class for benchmarking C++ code. It's not just simple, it's blazing fast! This sleek tic-toc timer class supports overlapping timers as well as OpenMP parallelism. It boasts a microsecond-level time resolution. We did not find any overhead of the timer itself at this resolution. Results (with summary statistics) are automatically passed back to R as a data frame. | ||
|
||
|
||
## Install | ||
|
||
Install rcpptimer from CRAN. | ||
|
||
``` | ||
install.packages("rcpptimer") | ||
``` | ||
|
||
## The Rcpp side of things | ||
|
||
Link it in your `DESCRIPTION` file or with `//[[Rcpp::depends(rcpptimer)]]`, and load the header library into individual `.cpp` files with `#include <rcpptimer.h>`. Then create an instance of the Rcpp::Clock class and use: | ||
|
||
`.tic(std::string)` to start a new timer. `.toc(std::string)` to stop the timer. | ||
|
||
```c++ | ||
//[[Rcpp::depends(rcpptimer)]] | ||
#include <rcpptimer.h> | ||
|
||
std::vector<int> fibonacci(std::vector<int> n) | ||
{ | ||
Rcpp::Timer timer; // Or Rcpp::Timer timer("my_name"); to assign a custom name | ||
// to the returned dataframe (default is 'times') | ||
timer.tic("fib_body"); // Start timer measuring the whole function | ||
std::vector<int> results = n; | ||
|
||
for (int i = 0; i < n.size(); ++i) | ||
{ | ||
// Start a timer for each fibonacci number | ||
timer.tic("fib_" + std::to_string(n[i])); | ||
results[i] = fib(n[i]); | ||
// Stop the timer for each fibonacci number | ||
timer.toc("fib_" + std::to_string(n[i])); | ||
} | ||
// Stop the timer measuring the whole function | ||
timer.toc("fib_body"); | ||
return (results); | ||
} | ||
``` | ||
Multiple timers with the same name (i.e. in a loop) will be grouped and we report the Mean and Standard Deviation for them. The results will be automatically passed to R as the `timer` instance goes out of scope. You don't need to worry about return statements. | ||
## The R side of things | ||
On the R end, we can now observe the `times` object that was silently passed to the global environment: | ||
```r | ||
[R] fibonacci(n = rep(10 * (1:4), 10)) | ||
[R] times | ||
Name Milliseconds SD Count | ||
1 fib_10 0.002 0.001 10 | ||
2 fib_20 0.048 0.011 10 | ||
3 fib_30 5.382 0.070 10 | ||
4 fib_40 658.280 1.520 10 | ||
5 fib_body 6637.259 0.000 1 | ||
``` | ||
|
||
## OpenMP Support | ||
|
||
Since we added OpenMP support, we also have an OpenMP version of the `fibonacci` function: | ||
|
||
```c++ | ||
std::vector<int> fibonacci_omp(std::vector<int> n) | ||
{ | ||
|
||
Rcpp::Timer timer; | ||
timer.tic("fib_body"); | ||
std::vector<int> results = n; | ||
|
||
#pragma omp parallel for | ||
for (int i = 0; i < n.size(); ++i) | ||
{ | ||
timer.tic("fib_" + std::to_string(n[i])); | ||
results[i] = fib(n[i]); | ||
timer.toc("fib_" + std::to_string(n[i])); | ||
} | ||
timer.toc("fib_body"); | ||
return (results); | ||
} | ||
``` | ||
Nothing has to be changed with respect to your `timer` instance. The timings show that the OpenMP version is significantly faster (fib_body): | ||
```r | ||
Name Milliseconds SD Count | ||
1 fib_10 0.022 0.031 10 | ||
2 fib_20 0.132 0.057 10 | ||
3 fib_30 8.728 2.583 10 | ||
4 fib_40 779.942 91.569 10 | ||
5 fib_body 908.919 0.000 1 | ||
``` | ||
|
||
## Limitations | ||
|
||
Processes taking less than a microsecond cannot be timed. | ||
|
||
## Acknowledgments | ||
|
||
This package (and the underlying [cpptimer](https://github.com/BerriJ/cpptimer) class) was inspired by [zdebruine](https://github.com/zdebruine)'s [RcppClock](https://github.com/zdebruine/RcppClock). I used that package a lot and wanted to add OpenMP support, alter the process of calculating summary statistics, and apply a series of other small adjustments. I hope you find it useful. |
Oops, something went wrong.