2014-12-17 2 views
2

Я написал следующий код, чтобы научиться использовать RcppParallel. Это просто игрушечный пример.Несбалансированность стека с RcppParallel

// [[Rcpp::depends(RcppParallel)]] 
#include <Rcpp.h> 
#include <RcppParallel.h> 
#include <iostream> 
using namespace Rcpp; 
using namespace RcppParallel; 


struct Lapin : public Worker { 
    // input pars 
    const NumericVector input; 
    const size_t dim; 

    // outputs a matrix 
    NumericMatrix output; 

    // two constructors 
    Lapin(const NumericVector input, const int dim) : input(input), dim(dim), output(NumericMatrix(dim,dim)) {} 

    Lapin(const Lapin & jeannot, Split) : input(jeannot.input), dim(jeannot.dim), output(NumericMatrix(dim,dim)) {} 

    // the working operator 
    void operator()(size_t begin, size_t end) { 
    for(size_t k = begin; k < end; k++) { 
     for(size_t i = 0; i < dim; i++) { 
     for(size_t j = 0; j < dim; j++) { 
      output(i,j) += input(k)+i+j; 
     } 
     } 
    } 
    } 

    // the join 
    void join(const Lapin & peter) { 
    output += peter.output; 
    } 
}; 

// [[Rcpp::export]] 
NumericMatrix f(NumericVector A, size_t dim) { 
    Lapin groumf(A, dim); 
    parallelReduce(0, A.length(), groumf); 
    return groumf.output; 
} 

Вот что происходит в R, после sourceCpp-ки его:

> f(rep(1,1100), 5) 
    [,1] [,2] [,3] [,4] [,5] 
[1,] 1100 2200 3300 4400 5500 
[2,] 2200 3300 4400 5500 6600 
[3,] 3300 4400 5500 6600 7700 
[4,] 4400 5500 6600 7700 8800 
[5,] 5500 6600 7700 8800 9900 
> sourceCpp("parallel-matrix-reduce.cpp") 
> f(rep(1,1100), 5) 
Warning: stack imbalance in '.Call', 6 then 11 
    [,1] [,2] [,3] [,4] [,5] 
[1,] 1100 2200 3300 4400 5500 
[2,] 2200 3300 4400 5500 6600 
[3,] 3300 4400 5500 6600 7700 
[4,] 4400 5500 6600 7700 8800 
[5,] 5500 6600 7700 8800 9900 

Обратите внимание, что поведение является eratic: иногда, я не имею никакого предупреждения вообще, иногда при первом запуске ... Я думаю, что моя информация сессии может быть здесь полезной:

> sessionInfo() 
R version 3.1.2 (2014-10-31) 
Platform: x86_64-redhat-linux-gnu (64-bit) 

locale: 
[1] LC_CTYPE=en_US.UTF-8  LC_NUMERIC=C    
[3] LC_TIME=fr_FR.UTF-8  LC_COLLATE=en_US.UTF-8  
[5] LC_MONETARY=fr_FR.UTF-8 LC_MESSAGES=en_US.UTF-8 
[7] LC_PAPER=fr_FR.UTF-8  LC_NAME=C     
[9] LC_ADDRESS=C    LC_TELEPHONE=C    
[11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C  

attached base packages: 
[1] stats  graphics grDevices utils  datasets methods base  

other attached packages: 
[1] Rcpp_0.11.3 

loaded via a namespace (and not attached): 
[1] RcppParallel_4.3.3 tools_3.1.2  

Я благодарю вас за все ваши ответы и комментарии.

EDIT Как объясняет Дирк, это связано с использованием типов R в Работнике, что смущает сборщик мусора. Я решил проблему, используя вместо этого матрицы Армадилло (я был немного смущен RMatrix). Вот исправленный код:

// [[Rcpp::depends(RcppParallel)]] 
// [[Rcpp::depends(RcppArmadillo)]] 
#include <RcppArmadillo.h> 
#include <RcppParallel.h> 
#include <iostream> 
using namespace Rcpp; 
using namespace RcppParallel; 


struct Lapin : public Worker { 
    // input pars 
    const arma::vec input; 
    const size_t dim; 

    // outputs a matrix 
    arma::mat output; 

    // two constructors 
    Lapin(const arma::vec input, const int dim) : input(input), dim(dim), output(arma::mat(dim,dim)) { 
    output.zeros(); 
    } 

    Lapin(const Lapin & jeannot, Split) : input(jeannot.input), dim(jeannot.dim), output(arma::mat(dim,dim)) { 
    output.zeros(); 
    } 

    // the working operator 
    void operator()(size_t begin, size_t end) { 
    for(size_t k = begin; k < end; k++) { 
     for(size_t i = 0; i < dim; i++) { 
     for(size_t j = 0; j < dim; j++) { 
      output(i,j) += input(k)+i+j; 
     } 
     } 
    } 
    } 
    // the join 
    void join(const Lapin & peter) { 
    output += peter.output; 
    } 
}; 

// [[Rcpp::export]] 
arma::mat f(arma::vec & A, size_t dim) { 
    Lapin groumf(A, dim); 
    parallelReduce(0, A.size(), groumf); 
    return groumf.output; 
} 
+1

Не знаете, насколько это актуально, но предупреждение о дисбалансе стека кратко описано в разделе 5.9.1 из [R internals] (http://cran.r-project.org/doc/manuals/R-exts.html #Вывоз мусора). – nrussell

+1

Спасибо, бит, это не очень помогает. Не используйте PROTECT и UNPROTECT напрямую, оставляя их Rcpp и RcppParallel ... – Elvis

ответ

2

Посмотрите более внимательно на example such as the parallel distance из Rcpp галереи.

It не использование NumericMatrix, но RMatrix<double>. Я бы сделал то же самое здесь и в целом выступал за то, чтобы не полагаться на контакт с R-типами при работе с параллельными сегментами.

+0

Большое спасибо Dirk. Я должен признать, что я пропустил эту деталь, о которой ясно говорится в примере. Я попробую это и дам вам знать. Я немного удивлен, так как этот код хорошо работает на моем настольном компьютере, но не в моем «вычислительном кластере», знаете ли вы, известно ли, что это поведение зависит от архитектуры? – Elvis

+1

Спасибо за последующий и отредактированный ответ. –

+0

Бах, я хотел сказать _edited вопрос, содержащий ваш ответ. –

Смежные вопросы