Ispirato allo snodo http://gallery.rcpp.org/articles/parallel-distance-matrix/, provo a utilizzare RcppParallel per eseguire la ricerca di forza bruta nello spazio parametrico ad alta dimensionalità per il backtesting utilizzando i multithread. Sono bloccato in come chiamare una funzione auto-definita nella parte struct
. L'idea è così:Come chiamare la funzione definita dall'utente in RcppParallel?
Innanzitutto, creare una matrice parametrica NumericMatrix params_mat
in R prima, e utilizzare i dati backtesting con List, NumericVector, CharacterVector
tipo di dati, come List Data_1, NumericVector Data_2, CharacterVector Data_3, ...
, che sono statici per ogni scenario parametrico params_vec
(Si noti che è la fila di params_mat
).
Successivamente, definire la funzione di backtesting che genera un vettore che consiste di 3 variabili chiave per valutare le prestazioni della strategia.
Ecco un esempio del mio params_mat
e Backtesting_Fun
che può essere eseguito in R e Rcpp, rispettivamente.
//[[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;
}
Certamente abbiamo bisogno di riscrivere/modificare l'originale Rcpp Backtesting_Fun
con i tipi RVector/RMatrix, e quindi utilizzare i seguenti RcppParallel
codici di chiamare 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;
}
Ecco le mie domande:
Can
RVector
contieneList
tipo di dati o c'è un contenitore specifico inRcppParallel
per contenereList
;Nel
Backtesting_Fun
, l'ingresso dovrebbe essereRVector/RMatrix
tipi, significa che abbiamo davvero bisogno di convertire i codici orginal principali Rcpp conNumericVector
inRVector
?
Oppure c'è un modo migliore per eseguire il calcolo parallelo per il mio caso in RcppParallel? Grazie in anticipo.
EDIT:
Guardo gli altri esempi per quanto riguarda RcppPararrel in http://gallery.rcpp.org/articles/parallel-matrix-transform/, http://gallery.rcpp.org/articles/parallel-inner-product/, l'idea comune in
struct operator()
è quello di utilizzare i puntatori per manipolare l'input dei dati peroperator()
, quindi c'è qualche modo costruire una funzione definita dall'utente nel mio caso con gli input del puntatore?Se il modo precedente non funziona, è possibile l'uso
wrap
convertireRVector/RMatrix
nuovamente dentro Rcpp tipo di dati, cioè, inNumericVector..
operator()
modo che i tipi di ingresso della funzione definita dall'utenteBacktesting_Fun
può rimanere invariata.
Probabilmente avrai più possibilità di ottenere una risposta se fornisci un esempio più piccolo, completo (senza '...' s nelle tue funzioni). – nrussell
Grazie per il suggerimento @nrussell, aggiornerò presto la domanda con un esempio semplice ed esatto – Alvin