2014-10-07 62 views
1

下面的玩具例子同居parallelFor工作正常(f2f1的並行版本):RcppArmadillo和RcppParallel

// [[Rcpp::depends(RcppParallel)]] 
// [[Rcpp::depends(RcppArmadillo)]] 
#include <RcppArmadillo.h> 
#include <RcppParallel.h> 
#include <iostream> 
#define vector NumericVector 

using namespace Rcpp; 
using namespace RcppParallel; 


// compute values i/i+1 for i = 0 to n-1 
// [[Rcpp::export]] 
vector f1(int n) { 
    vector x(n); 
    for(int i = 0; i < n; i++) x[i] = (double) i/ (i+1); 
    return x; 
} 

struct mytry : public Worker { 
    vector output; 

    mytry(vector out) : output(out) {} 

    void operator()(std::size_t begin, std::size_t end) { 
    for(int i = begin; i < end; i++) output[i] = (double) i/ (i+1); 
    } 

}; 

// [[Rcpp::export]] 
vector f2(int n) { 
    vector x(n); 
    mytry A(x); 
    parallelFor(0, n, A); 
    return x; 
} 

但是,如果我取代#define vector NumericVector通過#define vector arma::vec這不起作用了。代碼編譯並運行,f1沒問題,但由f2返回的向量只包含未初始化的值。

非常感謝您的任何澄清。

+1

應該將'arma :: vec'作爲該類的參考成員嗎? (這適用於'Rcpp'情況,因爲R的向量只是指針上的代理對象,所以你仍然可以訪問相同的對象) – 2014-10-07 15:42:58

+0

謝謝,我會嘗試。 – Elvis 2014-10-07 20:41:46

+1

@KevinUshey沒關係,兩個放置好的'&'並運行:準確地說,用'mytry'(vector out)替換vector vector;'mytry(vector out):'output (vector&out):output(out){}'。你會將你的評論作爲答案嗎?我很高興接受它。因爲有一天我不太可能成爲唯一能夠解決這個問題的新手,我認爲這是值得的。 – Elvis 2014-10-08 07:30:07

回答

3

這裏的問題 - 你的班級應該通過引用而不是價值觀來引導向量。

這是因爲,當使用RcppParallel時,通常會爲某個對象預先分配內存,然後填充該對象 - 因此並行工作人員應該引用要填充的對象的引用。

所以你的工人應該像(正如你指出):

struct mytry : public Worker { 
    vector& output; 

    mytry(vector& out) : output(out) {} 

    void operator()(std::size_t begin, std::size_t end) { 
    for(int i = begin; i < end; i++) output[i] = (double) i/ (i+1); 
    } 

注意這(也許令人驚訝的)爲RCPP載體,因爲他們已經只是「代理」的對象 - 只是對象封裝指向數據的指針。當你通過值傳遞一個Rcpp向量時,你複製指針(不是底層數據!)加上一些額外的向量位(例如​​向量的長度) - 所以'複製'保留對同一數據結構的引用。

當您使用更經典的矢量時, arma::vecstd::vector,當通過值傳遞給工作人員時,您真的在將一個全新的矢量複製到類中,然後填充該(臨時的,複製的)矢量 - 因此原始矢量實際上不會被填充。