Добавление указателей на функции в Parallel Worker - PullRequest
0 голосов
/ 13 марта 2019

Основываясь на примере здесь Parallel Worker в пространстве имен , я хотел бы использовать указатели функций с Parallel Worker.

Приведенный ниже код выдает ошибку в строках: «не может инициализировать новое значение типа (**) с возвращаемым значением (*)»

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;
}

Вам также может понадобиться makevars для указания c ++ 11 на mac:

CXX_STD = CXX11
PKG_LIBS += $(shell ${R_HOME}/bin/Rscript -e "RcppParallel::RcppParallelLibs()")

1 Ответ

0 голосов
/ 14 марта 2019

Хорошо, это работает. И shared_ptr не нужен.

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;
}
...