Lấy cảm hứng từ nghệ thuật http://gallery.rcpp.org/articles/parallel-distance-matrix/, tôi cố gắng sử dụng RcppParallel để chạy tìm kiếm brute-force trong không gian tham số chiều cao để backtesting bằng cách sử dụng multithreads. Tôi bị kẹt trong cách gọi một chức năng tự xác định trong phần struct
. Ý tưởng là như thế này:Cách gọi hàm do người dùng định nghĩa trong RcppParallel?
Đầu tiên, tạo một ma trận tham số NumericMatrix params_mat
trong R đầu tiên, và sử dụng dữ liệu backtesting với List, NumericVector, CharacterVector
datatype, chẳng hạn như List Data_1, NumericVector Data_2, CharacterVector Data_3, ...
, mà là tĩnh cho mỗi kịch bản tham số params_vec
(Lưu ý rằng nó là hàng của params_mat
).
Tiếp theo, xác định hàm backtesting xuất ra một vectơ bao gồm 3 biến quan trọng để đánh giá hiệu suất chiến lược.
Dưới đây là ví dụ về số params_mat
và Backtesting_Fun
có thể chạy tương ứng với R và 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;
}
Chắc chắn chúng ta cần phải viết lại/sửa đổi bản gốc Rcpp Backtesting_Fun
với các loại RVector/RMatrix, và sau đó sử dụng RcppParallel
mã sau để gọi Backtesting_Fun
trong 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;
}
Dưới đây là những câu hỏi của tôi:
Có thể
RVector
chứaList
kiểu dữ liệu hoặc có bất kỳ thùng chứa cụ thể nào trongRcppParallel
để chứaList
;Trong
Backtesting_Fun
, đầu vào nênRVector/RMatrix
loại, điều đó có nghĩa là chúng ta thực sự cần phải chuyển đổi ban đầu mã chính Rcpp vớiNumericVector
vàoRVector
?
Hoặc có cách nào tốt hơn để thực hiện tính toán song song cho trường hợp của tôi trong RcppParallel không? Cảm ơn trước.
EDIT:
tôi nhìn vào các ví dụ khác về RcppPararrel trong http://gallery.rcpp.org/articles/parallel-matrix-transform/, http://gallery.rcpp.org/articles/parallel-inner-product/, ý tưởng phổ biến ở
struct operator()
là sử dụng con trỏ để thao tác các dữ liệu đầu vào chooperator()
, như vậy là có cách nào thế nào để xây dựng một hàm do người dùng định nghĩa trong trường hợp của tôi với các đầu vào con trỏ?Nếu cách trên không hoạt động, nó là khả thi để sử dụng
wrap
để chuyển đổiRVector/RMatrix
trở lại vào Rcpp datatype, nghĩa là,NumericVector..
trongoperator()
để các loại đầu vào của chức năng người dùng định nghĩaBacktesting_Fun
có thể vẫn không thay đổi.
Có thể bạn sẽ có nhiều khả năng nhận được câu trả lời nếu bạn cung cấp ví dụ nhỏ hơn, đầy đủ (không có '...' s trong chức năng của bạn). – nrussell
Cảm ơn bạn đã đề xuất @nrussell, tôi sẽ sớm cập nhật câu hỏi với ví dụ đơn giản và chính xác – Alvin