首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在RcppParallel中调用用户定义的函数?

如何在RcppParallel中调用用户定义的函数?
EN

Stack Overflow用户
提问于 2015-06-11 21:03:53
回答 1查看 1.6K关注 0票数 7

http://gallery.rcpp.org/articles/parallel-distance-matrix/的启发,我尝试使用RcppParallel在高维参数空间中运行蛮力搜索,以便使用多线程进行回溯测试。我陷入了如何在struct部件中调用自定义函数的问题。想法是这样的:

首先,在row中创建参数矩阵NumericMatrix params_mat,并使用带有List, NumericVector, CharacterVector数据类型的反测试数据,比如List Data_1, NumericVector Data_2, CharacterVector Data_3, ...,这些数据对于每个参数场景params_vec都是静态的(注意,这是params_mat行)。

接下来,定义返回测试函数,该函数输出一个向量,该向量包含3个关键变量,用于评估策略性能。

下面是我的params_matBacktesting_Fun的一个例子,它们分别可以在R和Rcpp中运行。

代码语言:javascript
复制
//[[Rcpp::export]]
NumericMatrix data_frame_rcpp(const Rcpp::List& list_params) 
{
  NumericMatrix res = list_params[0];
  return res;
}

# R codes to generate params_mat
params <- expand.grid (x_1=seq(1,100,1), x_2=seq(3,100,2), ..., x_n=seq(4,200,1));                           
list_params = list(ts(params));
tmp_params_data = data_frame_rcpp(list_params);                                              
params_mat = matrix(tmp_params_data, ncol = ncol(tmp_params_data), dimnames = NULL); 
params_vec = params_mat[ii,];

# User-defined Rcpp codes for backtesting
NumericVector Backtesting_Fun (List Data_1, NumericVector Data_2, CharacterVector Data_3, ..., NumericVector params_vec)
{
  // Main function parts to run backtesting for each params_vec scenario.
  ... etc

  // save 3 key result variables together with each params_vec (just a simple illustration).
  NumericVector res = NumericVector::create(params_vec[0],...,params_vec[size-1],
                                            key_1, key_2, key_3); 
  return res;
}

当然,我们需要用RVector类型重写/修改原始的Rcpp Backtesting_Fun,然后使用以下RcppParallel代码在struct Backtest_parallel中调用Backtesting_Fun

代码语言:javascript
复制
// [[Rcpp::depends(RcppParallel)]]
#include <RcppParallel.h>
using namespace RcppParallel;

RVector<double> Backtesting_Fun (const RVector<double> Data_1, const RVector<double> Data_2, 
                                const RVector<string> Data_3,..., const RVector<double> params_vec)
{
   // Main function parts to run backtesting for each params_vec scenario.
   ... etc;

   // save 3 key result variables together with each params_vec
   ... etc; 

   return res;
}

struct Backtest_parallel : public Worker 
{       
   // input matrix to read from
   const RVector<List> Data_1;
   const RVector<double> Data_2;
   const RVector<string> Data_3;
   ...
   const RMatrix<double> params_mat;

   // output matrix to write to
   RMatrix<double> rmat;

   // initialize from Rcpp input and output matrixes (the RMatrix class
   // can be automatically converted to from the Rcpp matrix type)
   Backtest_parallel(const List Data_1, const NumericVector Data_2, 
   const CharacterVector Data_3, ..., const NumericMatrix params_mat)
      : Data_1(Data_1), Data_2(Data_2), Data_3(Data_3), ..., params_mat(params_mat) {}

   // function call operator that work for the specified range (begin/end)
   void operator()(std::size_t begin, std::size_t end) 
   {
      for (std::size_t ii = begin; ii < end; i++) 
      {
         // params rows that we will operate on
         RMatrix<double>::Row params_row = params_mat.row(ii);

         // Run the backtesting function defined above
         RVector<double> res = Backtesting_Fun(Data_1, Data_2, ..., params_row)
         for (std::size_t jj = 0; jj < res.length(); jj++) 
         {
            // write to output matrix
            rmat(ii,jj) = res[jj];
         }
      }
   }
};

// [[Rcpp::export]]
NumericMatrix rcpp_parallel_backtest(List Data_1, NumericVector Data_2, CharacterVector Data_3,
                                     ..., NumericMatrix params_mat) 
{      
   // allocate the matrix we will return
   NumericMatrix rmat(params_mat.nrow(), params_mat.nrow()+3);

   // create the worker
   Backtest_parallel backtest_parallel(Data_1, Date_2, ..., params_mat);

   // call it with parallelFor
   parallelFor(0, rmat.nrow(), backtest_parallel);

   return rmat;
}

以下是我的问题:

  1. RVector是否包含List数据类型,或者RcppParallel中是否存在包含List的特定容器;
  2. Backtesting_Fun中,输入应该是RVector/RMatrix类型,这是否意味着我们真的需要将带有NumericVector的原始Rcpp主代码转换为RVector

或者在RcppParallel中有什么更好的方法来实现并行计算呢?提前谢谢。

编辑

  1. 我看了关于RcppPararrel在http://gallery.rcpp.org/articles/parallel-matrix-transform/http://gallery.rcpp.org/articles/parallel-inner-product/中的其他例子,struct operator()中的常见思想是使用指针来操作operator()的数据输入,那么在我的例子中,有什么方法可以用指针输入来构建用户定义的函数呢?
  2. 如果上述方法不起作用,是否可以使用wrapRVector/RMatrix转换回Rcpp数据类型,即operator()中的NumericVector..,以便用户定义的函数Backtesting_Fun的输入类型保持不变。
EN

回答 1

Stack Overflow用户

发布于 2015-07-07 22:52:16

我想我可能会找到解决这个问题的另一种方法:关键是使用线程安全访问器在struct中包含变量,并将RVector / RMatrix保留在外部主函数中,以便parallelFor能够正常工作,这是并行algo中最重要的部分。以下是我的方法:

  1. List 摆脱了数据类型:相反,我们可以通过使用NumericVector / NumericMatrix容器来转换List变量,并记录其相应的索引,以便子向量/子矩阵将指向与列表元素相同的元素。
  2. RcppParallel Github中所提到的,将RVector / RMatrix 转换为 arma::vec / arma::mat:,C++ Armadillo在struct的操作符中是线程安全的。在这里,我使用这个想法修改了基于RcppParallel的并行距离矩阵计算中给出的示例,这个想法几乎保持了相同的测试速度。 结构JsDistance :公共工作者{ const RMatrix tmp_MAT;//输入矩阵从RMatrix tmp_rmat读取;//输出矩阵写入std::size_t row_size,col_size;//将全局输入/输出转换为R-矩阵/R-向量类型JsDistance(const数字矩阵& matrix_input,数字矩阵& matrix_output,std::size_t row_size,std::size_t col_size):tmp_MAT(matrix_input),tmp_rmat(matrix_output),row_size(row_size),col_size(col_size) {} //将Rcpp函数//将RVector转换为arma类型,并在并行计算arma::mat (){ RMatrix tmp_mat =tmp_MAT中共享折叠arma数据;MAT(tmp_mat.begin(),row_size,col_size,false);返回MAT;}col_size运算符(std::size_t begin,std::size_t end) { for (std::size_t i= begin;I< end;i++) { for (std::size_t j= 0;j

正如我们所看到的,operator中的数据类型将是C++ arma,现在我们可以安全和快速地调用我们的用户定义的函数,直接使用对象而不是指针,这可能不是泛型的,也不是很容易设计的。

现在,这个parallelFor结构将在并行计算中共享相同的数据源,而不需要额外的副本,然后我们可以使用上述问题中的思想为反测试做一些小小的改变。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30791410

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档