Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Substitute openMP using RcppParallel #7

Closed
YunyiShen opened this issue Dec 8, 2020 · 4 comments
Closed

Substitute openMP using RcppParallel #7

YunyiShen opened this issue Dec 8, 2020 · 4 comments

Comments

@YunyiShen
Copy link

YunyiShen commented Dec 8, 2020

Thanks for the package!

It seems not all users have openMP installed and it cannot be done within R. Plus the omp support is not yet stable for R>4.0 (e.g. here). RcppParallel library seems to be an alternative? For example, the rowSums_svd_like_impl function in /src/rowSums.cppcan be written as

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>

// [[Rcpp::depends(RcppParallel)]]
#include <RcppParallel.h>
using namespace RcppParallel;
using namespace Rcpp;
using namespace arma;
using namespace std;

// use RcppParallel for parallel

struct rowSum_worker : public Worker
{
  const arma::mat &U;
  const arma::mat &DVt;
  const int &n;
  arma::vec res; // output

  rowSum_worker(const arma::mat &U,
                const arma::mat &DVt,
                const int &n) : U(U), DVt(DVt), n(n),
                                res(arma::vec(n, fill::zeros)) {}

  void operator()(std::size_t begin, std::size_t end)
  {
    for (int i = begin; i < end; ++i)
    {
      res(i) = arma::accu(U.row(i) * DVt);
    }
  }
};

// [[Rcpp::export]]
arma::vec rowSums_svd_like_impl_cpp(
    const arma::mat &U,
    const arma::rowvec &d,
    const arma::mat &V )
{

  int n = U.n_rows;
  arma::mat DVt = arma::diagmat(d) * V.t();

  rowSum_worker hardworking(U, DVt, n);
  parallelFor(0, n, hardworking);
  return (hardworking.res);
}

with an R wrapper:

rowSums_svd_like_impl <- function(U, d, V, num_threads) {
    setThreadOptions(numThreads = num_threads)
    res <- rowSums_svd_like_impl_cpp(U, d, V)
    defaultNumThreads()
    return(res)
}

This alternative seemed to work on my branch. Minor changes need to be made to import RcppParallel

@alexpghayes
Copy link
Contributor

I definitely do want to make this change, but I want to understand RcppParallel better beforehand. If you have any resources on RcppParallel you can point me to, or in general resources on approaches to parallelization that run nicely on all platforms, I would love to see them.

@YunyiShen
Copy link
Author

YunyiShen commented Dec 18, 2020

I definitely do want to make this change, but I want to understand RcppParallel better beforehand. If you have any resources on RcppParallel you can point me to, or in general resources on approaches to parallelization that run nicely on all platforms, I would love to see them.

I usually work with RcppParallel, which works well across platforms and also work well together with armadillo (but not very well directly with base Rcpp classes, you need to use RcppParallel's accessors classes). It's great to start with the introduction. This StackOverflow helped me a lot before. I made a branch here that substituted opneMP with RcppParallel for LRMF3 and here for fastadi. Let me know if you want a PR to see them locally.

@alexpghayes
Copy link
Contributor

alexpghayes commented Dec 18, 2020 via email

@alexpghayes
Copy link
Contributor

Moving compiled code to fastadi to quarantine it there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants