Skip to content

Commit

Permalink
version 1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
BerriJ authored and cran-robot committed Mar 6, 2024
0 parents commit cbd2bf6
Show file tree
Hide file tree
Showing 19 changed files with 1,338 additions and 0 deletions.
27 changes: 27 additions & 0 deletions DESCRIPTION
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
18 changes: 18 additions & 0 deletions MD5
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
6 changes: 6 additions & 0 deletions NAMESPACE
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)
10 changes: 10 additions & 0 deletions NEWS.md
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
53 changes: 53 additions & 0 deletions R/RcppExports.R
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)
}

5 changes: 5 additions & 0 deletions R/package.R
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
102 changes: 102 additions & 0 deletions README.md
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.

0 comments on commit cbd2bf6

Please sign in to comment.