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

2024-05-10

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

首先,创建参数矩阵NumericMatrix params_mat首先在 R 中,并使用回测数据List, NumericVector, CharacterVector数据类型,例如List Data_1, NumericVector Data_2, CharacterVector Data_3, ...,对于每个参数场景都是静态的params_vec(注意,这是一行params_mat).

接下来,定义回测函数,输出由 3 个关键变量组成的向量来评估策略性能。

这是我的一个例子params_mat and Backtesting_Fun可以分别在 R 和 Rcpp 中运行。

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

当然我们需要重写/修改原来的RcppBacktesting_Fun与 RVector/RMatrix 类型,然后使用以下RcppParallel调用代码Backtesting_Fun in struct Backtest_parallel:

// [[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. Can RVector包含List数据类型,或者是否有任何特定的容器RcppParallel包含装有List;

  2. In the Backtesting_Fun,输入应该是RVector/RMatrix类型,这是否意味着我们真的需要将原始 Rcpp 主代码转换为NumericVector into RVector?

或者有没有更好的方法可以在 RcppParallel 中为我的情况进行并行计算?提前致谢。

EDIT:

  1. 我查看了有关 RcppParallel 的其他示例http://gallery.rcpp.org/articles/parallel-matrix-transform/ http://gallery.rcpp.org/articles/parallel-matrix-transform/, http://gallery.rcpp.org/articles/parallel-inner-product/ http://gallery.rcpp.org/articles/parallel-inner-product/,共同的想法是struct operator()是使用指针来操作数据输入operator(),那么在我的例子中,有没有办法使用指针输入构建用户定义的函数?

  2. 如果以上方法不行的话是否可以使用wrap转换RVector/RMatrix返回 Rcpp 数据类型,即NumericVector.. in operator()这样用户定义函数的输入类型Backtesting_Fun可以保持不变。


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

  1. 摆脱List数据类型: 相反,我们可以将List变量通过使用NumericVector / NumericMatrix容器并记录其相应的索引,以便子向量/子矩阵将指向与列表元素相同的元素。

  2. Convert RVector / RMatrix into arma::vec / arma::mat: 如中提到的Rcpp并行Github http://rcppcore.github.io/RcppParallel/, C++ Armadillo在结构体的运算符中是线程安全的。这里我修改一下给出的例子使用 RcppParallel 进行并行距离矩阵计算 http://gallery.rcpp.org/articles/parallel-distance-matrix/通过使用这个想法,几乎保持相同的测试速度。

    struct JsDistance : public Worker
    {
      const RMatrix<double> tmp_MAT;  // input matrix to read from
      RMatrix<double> tmp_rmat;       // output matrix to write to
      std::size_t row_size, col_size;
    
      // Convert global input/output into RMatrix/RVector type
      JsDistance(const NumericMatrix& matrix_input, NumericMatrix& 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) {}
    
      // convert RVector/RMatrix into arma type for Rcpp function
      // and the follwing arma data will be shared in parallel computing
      arma::mat convert()
      {
        RMatrix<double> tmp_mat = tmp_MAT;
        arma::mat MAT(tmp_mat.begin(), row_size, col_size, false);
        return MAT;
      }
    
    
      void operator()(std::size_t begin, std::size_t end)
      {
        for (std::size_t i = begin; i < end; i++)
        {
          for (std::size_t j = 0; j < i; j++)
          {
            // rows we will operate on
            arma::mat MAT = convert();
            arma::rowvec row1 = MAT.row(i);          // get the row of arma matrix
            arma::rowvec row2 = MAT.row(j);
    
            // compute the average using std::tranform from the STL
            std::vector<double> avg(row1.n_elem);
            std::transform(row1.begin(), row1.end(), // input range 1
                           row2.begin(),             // input range 2
                           avg.begin(),              // output range
                           average);                 // function to apply
    
            // calculate divergences
            double d1 = kl_divergence(row1.begin(), row1.end(), avg.begin());
            double d2 = kl_divergence(row2.begin(), row2.end(), avg.begin());
    
            // write to output matrix
            tmp_rmat(i,j) = sqrt(.5 * (d1 + d2));
          }
        }
      }
    };
    
    // [[Rcpp::export]]
    NumericMatrix rcpp_parallel_js_distance_modify(const Rcpp::NumericMatrix& matrix_input, int N_cores)
    {
      // allocate the matrix we will return
      NumericMatrix matrix_output(matrix_input.nrow(), matrix_input.nrow());
      std::size_t row_size = matrix_input.nrow();
      std::size_t col_size = matrix_input.ncol();
    
      // create the worker
      JsDistance jsDistance(matrix_input, matrix_output, row_size, col_size);
    
      // call it with parallelFor
      parallelFor(0, matrix_input.nrow(), jsDistance, matrix_input.nrow()/N_cores);           // parallelFor with grain size setting
    
      return matrix_output;
     }
    
     // Example compare: 
     n_row = 1E3;
     n_col = 1E2;
     m = matrix(runif(n_row*n_col), nrow = n_row, ncol = n_col);
     m = m/rowSums(m);
    
     res <- benchmark(rcpp_parallel_js_distance(m, 6),
             rcpp_parallel_js_distance_orignal(m, 6),
             order="relative")
     res[,1:4];
    
     #test                                    #elapsed   #relative
     rcpp_parallel_js_distance_orignal(m, 6)  128.069    1.000
     rcpp_parallel_js_distance(m, 6)          129.210    1.009
    

正如我们所看到的,其中的数据类型operatorC++ arma,现在我们可以直接使用对象而不是仅使用指针来安全快速地调用用户定义的函数,这可能不通用或易于设计。

现在,这个parallelFor结构体在并行计算中会共享相同的数据源,无需额外的副本,然后我们可以利用上个问题中提到的想法做一些轻微的改变来进行回测。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在RcppParallel中调用用户定义的函数? 的相关文章

  • “x[] <- as.integer(x)”是什么意思

    当我阅读 R 手册时 我遇到了如下代码行 从 R 手册中的 colSums 复制 x lt cbind x1 3 x2 c 4 1 2 5 dimnames x 1 lt letters 1 8 x lt as integer x 有人能告
  • std::call_once 可重入且线程安全吗?

    std call once http en cppreference com w cpp thread call once是线程安全的 但它也是可重入的吗 我使用 VS2012 调试和发布 进行的测试表明 调用std call once从单
  • 使用 glmnet 纠正 n 个数据集上的 n 个 LASSO 回归的输出(严格来说是所选的特征/变量)

    注意 这是对上一个问题 https stackoverflow com questions 75006466 how to replicate my results from running n lassos iteratively usi
  • 如何使用 SOAP 且不使用 WSE 在 .NET 中签署 Amazon Web 服务请求

    亚马逊产品广告 API 以前称为 Amazon Associates Web Service 或 Amazon AWS 实施了一项新规则 即自 2009 年 8 月 15 日起 向其发送的所有 Web 服务请求都必须经过签名 他们在其网站上
  • R:使用数据框 A 中某个日期之前的值填充数据框 B 中的行

    这可能非常复杂 我怀疑需要先进的知识 我现在有两种不同类型的 data frames 我需要组合 数据 数据框A 按患者 ID 列出所有输血日期 每次输血均由单独的行表示 患者可以进行多次输血 不同的患者可以在同一天进行输血 Patient
  • 如何制作可启动程序?

    所以 这个问题可能看起来很奇怪 但假设我编译了 int main void int x 3 int y 4 int z x y 是否可以让CPU这样运行 如何 例如 这允许我写入监视器吗 如果我没记错的话 内存中有些地方可以写入要显示的内容
  • 使用 ggplot 为各个图例值选择所选颜色(HSV 或 HCL 或 RGB)

    我有一个类似这样的数据集 data lt read table text Me EE PE DE TE DEE CE 1 1 1 4 5 2000 0 50 0 2547 0 69 2 1 2 2 4 3000 NA 0 5896 2 56
  • R ggplot:加权 CDF

    我想使用绘制加权 CDFggplot 一些旧的非 SO 讨论 例如this https stat ethz ch pipermail r help 2012 October 337288 html从 2012 年起 建议这是不可能的 但我想
  • 将表(行)与 OpenXML SDK 2.5 保持在一起

    我想在 Word 文档中生成多个表 每行 2 行 但我想将这两行保留在一起 如果可能的话 new KeepNext 第一行不起作用 new KeepNext 第一行的最后一段不起作用 new CantSplit 放在桌子上不起作用 在所有情
  • 访问 ascx 文件中的母版页控件

    我有一个母版页文件 其中包含 2 个面板控件中的 2 个菜单 我还使用控件来检查用户是否登录并获取用户类型 根据我想要显示 隐藏面板的类型 控件本身不在母版页中引用 而是通过 CMS 系统动态引用 我想在用户控件中使用findcontrol
  • 消除垂直线ggplot

    这个问题以前曾被问过 但答案并不总是明确或很复杂 我希望 ggplot2 的新版本能够带来更简单的解决方案 如何仅消除 ggplot 的垂直线而不消除轴刻度线或标签 这对于条形图来说确实很好 因为它可以消除图形中一些不必要的干扰 这里有一些
  • C# 编译器不会优化不必要的强制转换

    前几天 在写答案的时候这个问题 https stackoverflow com questions 2208315 why is any slower than contains在这里 关于溢出 我对 C 编译器感到有点惊讶 它没有按照我的
  • 根据对象变量搜索对象列表

    我有一个对象列表 这些对象具有三个变量 ID 名称和值 这个列表中可能有很多对象 我需要根据ID或Name找到一个对象 并更改值 例子 class objec public string Name public int UID public
  • 引用/指针失效到底是什么?

    我找不到任何定义指针 引用无效在标准中 我问这个问题是因为我刚刚发现 C 11 禁止字符串的写时复制 COW 据我了解 如果应用了 COW 那么p仍然是一个有效的指针并且r以下命令后的有效参考 std string s abc std st
  • 如何使用 NPOI 按地址(A1、A2)获取 Excel 单元格值

    我有一个 Excel 单元格地址 例如 A1 A2 如何使用 C 中的 NPOI 框架以编程方式访问此单元格 我找到的一些 Java POI 示例代码 CellReference cr new CellReference A1 row my
  • 如何从 Rx Subscribe 回调异步函数?

    我想回调 Rx 订阅中的异步函数 例如 像那样 public class Consumer private readonly Service service new Service public ReplaySubject
  • 从 SpatialPolygons 和其他 sp 类中提取要素坐标

    Package sp为不同的空间概念 点 线 多边形 提供了许多类 对于某些类 访问要素坐标很简单 例如SpatialLines 所有示例均取自相应课程的帮助页面 l1 cbind c 1 2 3 c 3 2 2 l1a cbind l1
  • 在 OpenGL 中渲染纹理 1 到 1

    所以我想做的是使用 OpenGL 和 C 将纹理渲染到平面上 作为显示图像的一种方式 但是我需要确保在渲染纹理时没有对纹理进行任何处理 抗锯齿 插值 平滑 模糊等 这是 OpenGL 处理渲染纹理的默认方式吗 或者是否需要设置一些标志才能禁
  • ASP.NET MVC 路由:如何从 URL 中省略“索引”

    我有一个名为 StuffController 的控制器 具有无参数索引操作 我希望从表单中的 URL 调用此操作mysite com stuff 我的控制器定义为 public class StuffController BaseContr
  • 在 C#.NET 中安全删除文件

    在我正在做的一个项目中 我想为用户提供 安全 删除文件的选项 例如 用随机位或 0 覆盖它 在 C NET 中是否有一种简单的方法可以做到这一点 效果如何 你可以调用系统内部删除 http technet microsoft com en

随机推荐

  • Express js 错误:“express 已弃用 res.sendfile:请改用 res.sendFile”

    设置路径的正确方法是什么 在我的应用程序中 我使用此代码设置发送文件的路径 app get function req res get put post delete res sendfile dirname client views ind
  • 张量流急切模块错误

    我的操作系统是 Ubuntu 16 04 Python版本是3 5 张量流版本是14 0 当我尝试为 TF Eager 模块编写简单代码时 import tensorflow as tf import tensorflow contrib
  • 我应该害怕使用 UDP 进行客户端/服务器广播通话吗?

    我在过去的两天里阅读了每一篇StackOverflow问题和答案 以及googling当然 关于印地TCP and UDP协议 以便决定在我的用户应用程序和 Windows 服务之间的通信方法中应该使用哪一种 从我目前所看到的来看 UDP是
  • 为什么 [].push([]) 返回 1? [复制]

    这个问题在这里已经有答案了 为什么这会返回 1 push outputs 1 push 返回数组的新长度 one push two returns 2 array length is 2 one two push something ret
  • 将活动工作表作为电子邮件附件从 Google 工作表发送

    我有一个谷歌表单 可以捕获电子表格中的响应 目前 每次做出新响应时 它都会创建一个新工作表 我现在尝试将 邮寄活动工作表脚本 添加到创建新工作表的现有脚本中 但是我收到错误 请求失败https docs google com spreads
  • 什么是 C++11 扩展 [-Wc++11-extensions]

    我需要一些帮助来了解此错误发生的位置 警告 非静态数据成员的类内初始化是 C 11 扩展 Wc 11 extensions 这是它来自的代码部分 typedef struct Hand bool straight false bool fl
  • /WEB-INF 中的 JSP 返回“HTTP 状态 404 请求的资源不可用”

    我创建了一个 JSP 文件 sample jsp This is jsp program 我把它放在这里samplejsp项目 samplejsp WebContent WEB INF sample jsp 我通过以下网址打开了它 http
  • Java泛型类型

    当我有一个界面时 public interface Foo
  • RemoveEventListener 在 Firefox 版本 58 中不起作用

    但它在 Chrome 中有效 这是我的 UI EventBus 代码 原型 addEventListener方法是一样的 只不过remove换成了add UI EventBus removeEventListener function ob
  • 在javascript中我们如何识别一个对象是Hash还是Array?

    我的 JSON 调用的输出可以是数组或哈希 我如何区分这两者 现代浏览器支持Array isArray obj method See MDN https developer mozilla org en US docs Web JavaSc
  • scrapy python 请求未定义

    我在这里找到了答案 code for site in sites Link site xpath a href extract CompleteLink urlparse urljoin response url Link yield Re
  • 转换 Java -> Grails ... 如何加载这些属性?

    我正在将 Java Web 应用程序转换为 Grails 1 2 1 在我的 Java 应用程序中 我有一个从 properties 文件加载属性的单例 我已经看到我可以将其加载到 Config groovy conf 文件中 如果我的属性
  • 关闭应用程序后如何调试

    我正在尝试重现问题 这需要在特定位置关闭并重新打开我的应用程序 这是我的问题 1 如何查看我的日志 使用NSLog命令 当我的 iPhone 未连接到 XCode 时 2 是否可以将iPhone模拟器的特定位置 例如市中心 设置为默认位置
  • 是否可以在 Apple M1 计算机上安装 Weblogic 12.2.1.4?

    我一直在寻找有关这方面的信息 但没有找到任何信息 我认为 Oracle 站点上没有可用于在 Apple M1 设备上安装 Weblogic 12 2 1 X 的版本 但也许可以使用 Rosetta 2 来完成此操作 有人尝试过吗 我不能 因
  • 如何访问 gem5 线程统计信息?

    我希望在我的一些工作中使用 gem5 并且对其功能有一个非常普遍的问题 我的问题是 使用 gem5 我可以获得有关单个线程的行为 系统资源使用情况的统计信息 无论是 SE 还是 FS 模式 例如 如果我的应用程序中运行 2 个线程 我是否可
  • 为什么将未使用的返回值转换为 void?

    int fn void whatever void fn 是否有任何理由将未使用的返回值强制转换为 void 或者我认为这完全是浪费时间 David s answer https stackoverflow com questions 68
  • Tkinter 绑定 Mac OS“command+q”

    当我按 Command q 时 我试图 停止 根窗口退出 但这是不可能的 其他快捷键在我的 Mac 操作系统上有效 即使在 Windows Linux 中 Alt F4 绑定也可以 捕获 但在 Mac 操作系统中对我来说是不可能的 有任何想
  • Python“self”关键字[重复]

    这个问题在这里已经有答案了 我是 Python 新手 通常使用 C 最近几天开始使用它 在类中 是否需要在对该类的数据成员和方法的任何调用前添加前缀 因此 如果我在该类中调用方法或从该类获取值 我需要使用self method or sel
  • 监控 Java 应用程序上的锁争用

    我正在尝试创建一个小基准 在 Groovy 中 以显示几个同步方法上的高线程争用 当监控自愿上下文切换时 应该会出现高争用 在 Linux 中 这可以通过 pidstat 来实现 程序如下 class Res private int n s
  • 如何在RcppParallel中调用用户定义的函数?

    受到文章的启发http gallery rcpp org articles parallel distance matrix http gallery rcpp org articles parallel distance matrix 我