diff --git a/NAMESPACE b/NAMESPACE index 4a219cf..d359139 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -11,6 +11,7 @@ S3method(tibble::as_tibble,fcwtr_scalogram) export(du) export(fcwt) export(fcwt_batch) +export(openmp_enabled) export(u) importFrom(graphics,plot) importFrom(utils,setTxtProgressBar) diff --git a/NEWS.md b/NEWS.md index 4228256..53e1530 100644 --- a/NEWS.md +++ b/NEWS.md @@ -18,6 +18,8 @@ - add more convenience S3 methods: `print()`, `[]`, `as.matrix()`, `rbind()`, `as_tibble()`. +- `openmp_enabled()`: new function to check for OpenMP support. + - add a [package logo](https://lschneiderbauer.github.io/fCWTr/logo.svg) # fcwtr 0.2.1 diff --git a/R/cpp11.R b/R/cpp11.R index 1e75e84..9efe60e 100644 --- a/R/cpp11.R +++ b/R/cpp11.R @@ -1,5 +1,9 @@ # Generated by cpp11: do not edit by hand +has_openmp <- function() { + .Call(`_fCWTr_has_openmp`) +} + fcwt_raw <- function(signal, fs, f0, f1, fn, sigma, nthreads, scaletype, optplans, abs) { .Call(`_fCWTr_fcwt_raw`, signal, fs, f0, f1, fn, sigma, nthreads, scaletype, optplans, abs) } diff --git a/R/fcwt.R b/R/fcwt.R index 025a78b..c74e697 100644 --- a/R/fcwt.R +++ b/R/fcwt.R @@ -63,7 +63,9 @@ #' #' @param n_threads #' Number of threads used by the computation, if supported by your platform. -#' Defaults to 2 threads (to accomodate CRAN requirements). +#' Defaults to 2 threads (to accommodate CRAN requirements). +#' If [openmp_enabled()] returns `FALSE`, this argument is ignored, and +#' only a single thread is used. #' #' @return #' The spectogram, a numeric real-valued matrix with dimensions diff --git a/R/openmp.R b/R/openmp.R new file mode 100644 index 0000000..92c1ec3 --- /dev/null +++ b/R/openmp.R @@ -0,0 +1,28 @@ + +#' Check for OpenMP support +#' +#' This function checks if OpenMP support is enabled. It is responsible for +#' the multithreading capabilities of [fcwt()]. If OpenMP is not enabled +#' the parameter `n_threads` of [fcwt()] is ignored. +#' +#' @details +#' OpenMP can be used by the underlying fCWT library if +#' * the fftw library on your platform was compiled with OpenMP support and +#' * the fCWTr package itself was compiled with OpenMP support. +#' +#' When using pre-built package binaries (like it is typical when you are using +#' R on Windows), whether or not these conditions are met, depend on the (CRAN) +#' build server. They cannot be influenced by the package author. +#' +#' If the user is building the R package yourself, the user needs to make sure +#' that the fftw library on her platform are built with OpenMP support. +#' The fCWTr package is configured to use OpenMP if fftw-OpenMP support is +#' available. +#' +#' @return ( `TRUE` | `FALSE` ) +#' Returns `TRUE` if OpenMP support is enabled, `FALSE` otherwise. +#' +#' @export +openmp_enabled <- function() { + has_openmp() +} diff --git a/_pkgdown.yml b/_pkgdown.yml index 0e5f652..a32334a 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -21,6 +21,9 @@ reference: - print.fcwtr_scalogram - plot.fcwtr_scalogram - autoplot.fcwtr_scalogram +- title: "Multithreading support" + contents: + - openmp_enabled - title: "Sample data" desc: > Sample signal data mainly used to generate examples. The signals consist diff --git a/man/fcwt.Rd b/man/fcwt.Rd index 3570b47..c43b741 100644 --- a/man/fcwt.Rd +++ b/man/fcwt.Rd @@ -58,7 +58,9 @@ is less then \eqn{4 \Sigma_t}. Values that fall into that range are removed if \code{remove_coi = TRUE}.} \item{n_threads}{Number of threads used by the computation, if supported by your platform. -Defaults to 2 threads (to accomodate CRAN requirements).} +Defaults to 2 threads (to accommodate CRAN requirements). +If \code{\link[=openmp_enabled]{openmp_enabled()}} returns \code{FALSE}, this argument is ignored, and +only a single thread is used.} } \value{ The spectogram, a numeric real-valued matrix with dimensions diff --git a/man/fcwt_batch.Rd b/man/fcwt_batch.Rd index 7dacd0c..91f2907 100644 --- a/man/fcwt_batch.Rd +++ b/man/fcwt_batch.Rd @@ -64,7 +64,9 @@ memory constrainty (boundary effects become larger the smaller the batch size).} \item{n_threads}{Number of threads used by the computation, if supported by your platform. -Defaults to 2 threads (to accomodate CRAN requirements).} +Defaults to 2 threads (to accommodate CRAN requirements). +If \code{\link[=openmp_enabled]{openmp_enabled()}} returns \code{FALSE}, this argument is ignored, and +only a single thread is used.} \item{progress_bar}{Monitoring progress can sometimes be useful when performing time consuming operations. Setting \code{progress_bar = TRUE} enables printing a progress diff --git a/man/openmp_enabled.Rd b/man/openmp_enabled.Rd new file mode 100644 index 0000000..a0faeb0 --- /dev/null +++ b/man/openmp_enabled.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/openmp.R +\name{openmp_enabled} +\alias{openmp_enabled} +\title{Check for OpenMP support} +\usage{ +openmp_enabled() +} +\value{ +( \code{TRUE} | \code{FALSE} ) +Returns \code{TRUE} if OpenMP support is enabled, \code{FALSE} otherwise. +} +\description{ +This function checks if OpenMP support is enabled. It is responsible for +the multithreading capabilities of \code{\link[=fcwt]{fcwt()}}. If OpenMP is not enabled +the parameter \code{n_threads} of \code{\link[=fcwt]{fcwt()}} is ignored. +} +\details{ +OpenMP can be used by the underlying fCWT library if +\itemize{ +\item the fftw library on your platform was compiled with OpenMP support and +\item the fCWTr package itself was compiled with OpenMP support. +} + +When using pre-built package binaries (like it is typical when you are using +R on Windows), whether or not these conditions are met, depend on the (CRAN) +build server. They cannot be influenced by the package author. + +If the user is building the R package yourself, the user needs to make sure +that the fftw library on her platform are built with OpenMP support. +The fCWTr package is configured to use OpenMP if fftw-OpenMP support is +available. +} diff --git a/src/cpp11.cpp b/src/cpp11.cpp index f103ebd..42e5281 100644 --- a/src/cpp11.cpp +++ b/src/cpp11.cpp @@ -5,6 +5,13 @@ #include "cpp11/declarations.hpp" #include +// interface_fcwt.cpp +cpp11::r_bool has_openmp(); +extern "C" SEXP _fCWTr_has_openmp() { + BEGIN_CPP11 + return cpp11::as_sexp(has_openmp()); + END_CPP11 +} // interface_fcwt.cpp std::vector fcwt_raw(std::vector signal, int fs, double f0, double f1, int fn, double sigma, int nthreads, bool scaletype, bool optplans, bool abs); extern "C" SEXP _fCWTr_fcwt_raw(SEXP signal, SEXP fs, SEXP f0, SEXP f1, SEXP fn, SEXP sigma, SEXP nthreads, SEXP scaletype, SEXP optplans, SEXP abs) { @@ -15,7 +22,8 @@ extern "C" SEXP _fCWTr_fcwt_raw(SEXP signal, SEXP fs, SEXP f0, SEXP f1, SEXP fn, extern "C" { static const R_CallMethodDef CallEntries[] = { - {"_fCWTr_fcwt_raw", (DL_FUNC) &_fCWTr_fcwt_raw, 10}, + {"_fCWTr_fcwt_raw", (DL_FUNC) &_fCWTr_fcwt_raw, 10}, + {"_fCWTr_has_openmp", (DL_FUNC) &_fCWTr_has_openmp, 0}, {NULL, NULL, 0} }; } diff --git a/src/interface_fcwt.cpp b/src/interface_fcwt.cpp index e092a0a..f8a181b 100644 --- a/src/interface_fcwt.cpp +++ b/src/interface_fcwt.cpp @@ -19,6 +19,15 @@ float dbl_to_float(const double &dbl) { return static_cast(dbl); } +[[cpp11::register]] +cpp11::r_bool has_openmp() { + #ifdef SINGLE_THREAD + return(false); + #else + return(true); + #endif +} + [[cpp11::register]] std::vector fcwt_raw( std::vector signal, diff --git a/tests/testthat/test-openmp.R b/tests/testthat/test-openmp.R new file mode 100644 index 0000000..57bb0db --- /dev/null +++ b/tests/testthat/test-openmp.R @@ -0,0 +1,5 @@ +test_that("openmp() works", { + expect_true( + openmp_enabled() == TRUE | openmp_enabled() == FALSE + ) +})