Zainspirowany przez Artical http://gallery.rcpp.org/articles/parallel-distance-matrix/, próbuję użyć RcppParallel, aby przeprowadzić przeszukiwanie w trybie brute-force w wielowymiarowej przestrzeni parametrycznej do testowania wstecznego za pomocą wielowątkowych. Utknąłem w tym, jak wywołać zdefiniowaną przez siebie funkcję w części struct
. Chodzi o to, w następujący sposób:Jak wywołać funkcję zdefiniowaną przez użytkownika w RcppParallel?
pierwsze, stworzenie parametrycznego matrycy NumericMatrix params_mat
w R pierwszy i wykorzystuje dane analizy historycznej z List, NumericVector, CharacterVector
typu danych, takich jak List Data_1, NumericVector Data_2, CharacterVector Data_3, ...
, które są na stałe do każdego parametrycznej scenariuszu params_vec
(Należy zauważyć, że jest to rząd params_mat
).
Następnie należy zdefiniować funkcję analizy historycznej, która wyprowadza wektor składający się z 3 zmiennych kluczowych w celu oceny skuteczności strategii.
Oto przykład moich params_mat
i Backtesting_Fun
, które można uruchomić odpowiednio w R i 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;
}
Oczywiście musimy przepisać/zmodyfikować oryginalny RCPP Backtesting_Fun
z typów RVector/RMatrix, a następnie użyć następujących RcppParallel
kody zadzwonić Backtesting_Fun
w 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;
}
Oto moje pytania:
Can
RVector
zawieraList
typ danych, lub czy istnieje jakiś konkretny pojemnik o numerzeRcppParallel
, który może zawieraćList
;W
Backtesting_Fun
, wejście powinno byćRVector/RMatrix
rodzaje, to znaczy, że naprawdę trzeba konwertować orginal RCPP główne kody zNumericVector
wRVector
?
Czy jest jakiś lepszy sposób na równoległe obliczenia dla mojego przypadku w RcppParallel? Z góry dziękuję.
EDIT:
patrzę na innych przykładach dotyczących RcppPararrel w http://gallery.rcpp.org/articles/parallel-matrix-transform/, http://gallery.rcpp.org/articles/parallel-inner-product/, wspólna idea w
struct operator()
jest wykorzystanie wskaźników do manipulowania wprowadzanie danych dooperator()
, więc jest jakiś sposób zbudować w moim przypadku funkcję zdefiniowaną przez użytkownika z wejściami do wskaźnika?Jeśli powyższy sposób nie zadziała, to jest możliwe, aby korzystać z
wrap
przekonwertowaćRVector/RMatrix
powrotem do RCPP typ danych, to znaczyNumericVector..
woperator()
tak, że typy wejściowe zdefiniowanej przez użytkownika funkcjiBacktesting_Fun
mogą pozostać niezmienione.
Prawdopodobnie najprawdopodobniej uzyskasz odpowiedź, jeśli podasz mniejszy, kompletny przykład (bez "..." w twoim funkcjach). – nrussell
Dzięki za propozycję @nrussell, zaktualizuję pytanie prostym i dokładnym przykładem wkrótce – Alvin