如何在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中调用用户定义的函数? 的相关文章

  • 嵌入式系统中的malloc [重复]

    这个问题在这里已经有答案了 我正在使用嵌入式系统 该应用程序在 AT91SAMxxxx 和 cortex m3 lpc17xxx 上运行 我正在研究动态内存分配 因为它会极大地改变应用程序的外观 并给我更多的力量 我认为我唯一真正的路线是为
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 如何针对 Nancy 中的 Active Directory 进行身份验证?

    这是一篇过时的文章 但是http msdn microsoft com en us library ff650308 aspx paght000026 step3 http msdn microsoft com en us library
  • c# Asp.NET MVC 使用FileStreamResult下载excel文件

    我需要构建一个方法 它将接收模型 从中构建excel 构建和接收部分完成没有问题 然后使用内存流导出 让用户下载它 不将其保存在服务器上 我是 ASP NET 和 MVC 的新手 所以我找到了指南并将其构建为教程项目 public File
  • 按名称包含在单个对象中的多个列对 data.frame 进行排序?

    我想排序一个data frame由多列组成 理想情况下使用基础 R 无需任何外部包 尽管如果有必要 就这样吧 读过如何按列对数据框进行排序 https stackoverflow com questions 1296646 how to s
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 使用 LINQ 查找列表中特定类型的第一个元素

    使用 LINQ 和 C 在元素列表中查找特定类型的第一个项目的最短表示法是什么 var first yourCollection OfType
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • 是否有比 lex/flex 更好(更现代)的工具来生成 C++ 分词器?

    我最近将源文件解析添加到现有工具中 该工具从复杂的命令行参数生成输出文件 命令行参数变得如此复杂 以至于我们开始允许它们作为一个文件提供 该文件被解析为一个非常大的命令行 但语法仍然很尴尬 因此我添加了使用更合理的语法解析源文件的功能 我使
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • R中data.frame(列表)的列平均值

    Data https i stack imgur com ZYsmv jpg 请 我需要计算此 data frame 中维吉尼亚币 Sepal Length 列的平均值 Sepal Length Sepal Width Petal Leng
  • AccessViolationException 未处理

    我正在尝试使用史蒂夫 桑德森的博客文章 http blog stevensanderson com 2010 01 28 editing a variable length list aspnet mvc 2 style 为了在我的 ASP
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • 在 R 中读入原始二进制数据并将其转换为整数

    我有一个二进制文件 其中包含编码为不同长度 主要是 2 4 字节 的有符号或无符号整数的数值 为了处理这些数据 我将文件的所需部分读取为raw向量与readBin 然后尝试将其转换为十进制 问题是 R的内置函数有限制 我不太明白 比如没有l
  • 如何将字符串“07:35”(HH:MM) 转换为 TimeSpan

    我想知道是否有办法将 24 小时时间格式的字符串转换为 TimeSpan 现在我有一种 旧时尚风格 string stringTime 07 35 string values stringTime Split TimeSpan ts new
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co

随机推荐

  • 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 我