0

Building off the example here Parallel Worker in namespace, I would like to employ function pointers with the Parallel Worker.

The code below produces an error along the lines of: "cannot initialize a new value of type (**) with a return value of (*)"

ExampleInternal.h

#ifndef ExampleInternal_H
#define ExampleInternal_H

namespace ExampleInternal{

#include <RcppArmadillo.h>
#include <RcppParallel.h>
#include <Rcpp.h>
#include <memory>

double myfuncA(arma::vec vec_in);

double myfuncB(arma::vec vec_in);

typedef double (*funcPtr)(arma::vec);

std::shared_ptr<funcPtr> selectfunc(std::string abc){
  if(abc == "A"){
    return   std::make_shared<funcPtr>(new funcPtr(&ExampleInternal::myfuncA));
  }else {
    return   std::make_shared<funcPtr>(new funcPtr(&ExampleInternal::myfuncB));
  }

}

struct PARALLEL_WORKER : RcppParallel::Worker{
  const arma::vec &input;
  std::shared_ptr<funcPtr> &Ptr;
  arma::vec &output;
  PARALLEL_WORKER( const arma::vec &input, std::shared_ptr<funcPtr> &Ptr, arma::vec &output);
  void operator()(std::size_t begin, std::size_t end);
};

}

#endif

myfuncA.cpp

#include <RcppArmadillo.h>
#include <RcppParallel.h>
#include "ExampleInternal.h"

using namespace arma;

namespace ExampleInternal{

double myfuncA(arma::vec vec_in){

  int Len = arma::size(vec_in)[0];
  return (vec_in[0] +vec_in[1])/Len;
}

} // Close namespace

myfuncB.cpp

#include <RcppArmadillo.h>
#include <RcppParallel.h>
#include "ExampleInternal.h"

using namespace arma;

namespace ExampleInternal{

double myfuncB(arma::vec vec_in){

  int Len = arma::size(vec_in)[0];
  return (vec_in[0] +vec_in[1])*Len;
}

} // Close namespace

Parallel_worker.cpp

#include <RcppArmadillo.h>
#include <RcppParallel.h>
#include <random>
#include <memory>
#include "ExampleInternal.h"

using namespace RcppParallel;
using namespace ExampleInternal;

namespace ExampleInternal{

PARALLEL_WORKER::PARALLEL_WORKER(const arma::vec &input,  std::shared_ptr<ExampleInternal::funcPtr> &Ptr, arma::vec &output) : input(input), Ptr(Ptr), output(output) {}
  void PARALLEL_WORKER::operator()(std::size_t begin, std::size_t end){


    std::mt19937 engine(1);

    // Create a loop that runs through a selected section of the total Boot_reps
    for( int k = begin; k < end; k ++){
      engine.seed(k);
      arma::vec index = input;
      std::shuffle( index.begin(), index.end(), engine);

      output[k] = Ptr(index);
    }
  }

} //Close Namespace

Parallel_func.cpp

#include <RcppArmadillo.h>
#include <RcppParallel.h>
#include <memory>
#include "ExampleInternal.h"
using namespace ExampleInternal;


// [[Rcpp::export]]
arma::vec Parallelfunc(int Len_in, std::string func_letter){

  std::shared_ptr<funcPtr> df = ExampleInternal::selectfunc(func_letter);

  arma::vec input = arma::regspace(0, 500);
  arma::vec output(Len_in);

  ExampleInternal::PARALLEL_WORKER parallel_woker(input, df, output);
  parallelFor( 0, Len_in, parallel_woker);
  return output;
}

You may also need a makevars to specify c++11, on mac:

CXX_STD = CXX11
PKG_LIBS += $(shell ${R_HOME}/bin/Rscript -e "RcppParallel::RcppParallelLibs()")
2
  • Are you sure RcppParallel is necessary to show this error? Have you tried using std::function instead of function pointers? Commented Mar 13, 2019 at 15:56
  • 1
    I haven't gone through everything but one thing that is immediately weird is you should be using raw pointers for function pointers, not shared pointers. There is no point in making a shared_ptr as your functions are not going anywhere, so you don't have to track ownership. Commented Mar 13, 2019 at 20:15

1 Answer 1

0

Ok this works. And the shared_ptr is not needed.

ExampleInternal.h

#ifndef ExampleInternal_H
#define ExampleInternal_H

namespace ExampleInternal{

#include <RcppArmadillo.h>
#include <RcppParallel.h>
#include <Rcpp.h>
#include <memory>

 double myfuncA(arma::vec vec_in);

 double myfuncB(arma::vec vec_in);

typedef double (*funcPtr)(arma::vec);

ExampleInternal::funcPtr func_select(int abc);

struct PARALLEL_WORKER : RcppParallel::Worker{
  const arma::vec &input;
  ExampleInternal::funcPtr &Ptr;
  arma::vec &output;
  PARALLEL_WORKER( const arma::vec &input, ExampleInternal::funcPtr &Ptr, arma::vec &output);
  void operator()(std::size_t begin, std::size_t end);
};

}

#endif

func_select.cpp

#include <RcppArmadillo.h>
#include <RcppParallel.h>
#include "ExampleInternal.h"

namespace ExampleInternal{

ExampleInternal::funcPtr func_select(int abc){

  ExampleInternal::funcPtr df;

  if(abc == 1){
    df = &ExampleInternal::myfuncA;
  }else{
    df = &ExampleInternal::myfuncB;
  }
  return df;
}

} //close namespace

Parallel_func.cpp

#include <RcppArmadillo.h>
#include <RcppParallel.h>
#include <memory>
#include "ExampleInternal.h"
using namespace ExampleInternal;

// [[Rcpp::export]]
arma::vec Parallelfunc(int Len_in, int func_num){

  ExampleInternal::funcPtr point = ExampleInternal::func_select(func_num);

  arma::vec input = arma::regspace(0, 500);
  arma::vec output(Len_in);

  ExampleInternal::PARALLEL_WORKER parallel_woker(input, point, output);
  parallelFor( 0, Len_in, parallel_woker);
  return output;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.