2013-09-22 22 views
4

我有以下功能RCPP函數可以使用Ubuntu的,但在Windows不能正常工作和Mac

fun <- cxxfunction(
    signature(x="numeric", y="numeric",N="interger", w="numeric", p="numeric"), 
    plugin="RcppArmadillo", 
    includes=c("#include <stdlib.h>", "#include <cmath>","#include <numeric>","#include <algorithm>","#include <vector>"), 
    body=' 
     using namespace Rcpp; 
    RNGScope scope; 

     NumericVector xa(x); 
     NumericVector ya(y); 
     int Na = as<int>(N); 
     int n_xa = xa.size(), n_ya = ya.size(); 
     arma::mat wa = Rcpp::as<arma::mat>(w); 
     Rcpp::NumericMatrix n(p); //one column to each x[i]/y 
     NumericVector limite(n_xa); 
     arma::mat z(n_ya, n_xa); 
     arma::mat beta(n_ya, n_xa); 
     arma::colvec one(xa.begin(), xa.size()); 
     arma::colvec betaM(ya.begin(), ya.size()); 
     arma::colvec betaP(ya.begin(), ya.size()); 
     arma::colvec Prob(ya.begin(), ya.size()); 
     arma::colvec betaC(ya.begin(), ya.size()); 
     z.col(0) = arma::zeros<arma::mat>(n_ya, 1); 
     NumericVector nV(n_ya); 
     NumericVector nT(n_ya); 

     int i, j, randLR; 

      for (i=0; i<n_xa; i++) { 
       for (j=0; j<n_ya; j++) { 
        z(j,i) = 0; 
       } 
       randLR = rand() % n_ya; 
     // randonly initialize z 
       z(randLR,i)=1; 
       limite(i) = i; 
       one(i) = 1; 
      } 
    // the number of ways can be produced 
      beta = wa * z; 
      one = beta * one; 


     int k, l,l2, pos; 
     NumericMatrix prob_table(n_xa, Na); 
     NumericMatrix class_table(n_xa, Na); 

    int oldval; 
      for(k=0; k<Na; k++){ 

       // limite = f(limite, n_xa); 
     std::random_shuffle(limite.begin(),limite.end()); 
       for (l=0; l<n_xa; l++) { 
        l2=limite(l);  
     // trick, where the z.col came from 
        betaM = one - wa * z.col(l2); 
      // sum delta and normalize 
      Prob = betaM; 
        std::transform(Prob.begin(), Prob.end(), Prob.begin(), std::bind2nd(std::plus<double>(),1)); 
        std::transform(Prob.begin(), Prob.end(), Prob.begin(), std::bind2nd(std::divides<double>(),std::accumulate(Prob.begin(), Prob.end(), 0.0))); 

        nV = n(_, l2); 
        std::transform(nV.begin(), nV.end(), nV.begin(), std::bind2nd(std::divides<double>(),std::accumulate(nV.begin(), nV.end(), 0.0))); 
      // multipling the the likelihoods 
        int nP; 
        for (nP=0; nP<betaP.size(); nP++) { 
          betaP(nP) = Prob(nP)*nV(nP); 
      if(z(nP, l2)==1){ 
       oldval = nP; 
      } 

     } 

         // continuing control 
         if (std::accumulate(betaP.begin(), betaP.end(), 0.0) > 0) { 
          std::transform(betaP.begin(), betaP.end(), betaP.begin(), std::bind2nd(std::divides<double>(),std::accumulate(betaP.begin(), betaP.end(), 0.0))); 
         } 
         else { 
          // std::transform(betaP.begin(), betaP.end(), betaP.begin(), std::bind2nd(std::plus<double>(),1)); 
         } 
         // a way to sample according a distribution, based on rogers 
      double base = ::Rf_runif(0,1); 

         std::partial_sum (betaP.begin(), betaP.end(), betaC.begin()); 
         int sz = betaC.size(); 
         int idx; 
         for (idx=0; idx<sz; idx++) { 
          if(betaC[idx] > base) { 
           pos = idx; 
           break; 
          } 
         } 


      if(pos!=oldval){ 
         one = betaM - wa * z.col(l2); 
       int nP; 
          for (nP=0; nP<betaP.size(); nP++) { 
        z(nP, l2) = 0; 
         } 
         z(pos, l2) = 1; 
         one = betaM + wa * z.col(l2); 
     }  

        prob_table(l2,k) = betaP(pos); 
        pos = pos + 1; 
        class_table(l2,k) = pos; 
       } 
} 

//  betaP = z.col(l2); 
     return Rcpp::List::create(Rcpp::Named("beta")=beta, Rcpp::Named("l2")=l2,Rcpp::Named("z")=z, Rcpp::Named("oldval")=oldval, Rcpp::Named("pos")=pos, Rcpp::Named("limite")=limite, Rcpp::Named("n")=nV, Rcpp::Named("betaM")=betaM, Rcpp::Named("betaP")=betaP, Rcpp::Named("Prob")=Prob,Rcpp::Named("prob_table")=prob_table, Rcpp::Named("class_table")=class_table); 
     ' 
) 

在所有的操作系​​統,64位,8 GB的RAM,我加載代碼

library(inline) 
source("fun.R") 

對於一個小例子,函數可以在所有系統中完美運行,但是當問題的大小增加時,窗口和mac的增加似乎要高出幾個數量級。

的作品小例子:

varx <- 1:100 
vary <- 1:200 
w <- matrix(sample(0:1, 200^2, replace=TRUE), 200, 200) 
wm <- matrix(abs(rnorm(200*100, 0.5, 0.5)), 200, 100) 
system.time(conn <- fun(varx, vary, 5000, w, wm)) 

大的例子,只能在Linux上:

https://dl.dropboxusercontent.com/u/10712588/var1_teste.rda https://dl.dropboxusercontent.com/u/10712588/var2_teste.rda

load("var1_teste.rda") 
load("var2_teste.rda") 
varx <- 1:ncol(wl$wm) 
vary <- 1:nrow(wl$wm) 
system.time(conn <- fun(varx, vary, 5000, w, wl$wm)) 

在Ubuntu上需要花費30分鐘,在Windows或Mac它需要2天,沒有完成,有人有線索?操作系統有沒有區別?

回答

6

您是否考慮先用較小的問題進行測試?

您是否考慮重新構建現有的RcppArmadillo示例之一以檢查您測試的所有系統上的可行性?

此外,隨着更新的Rcpp發佈,'Rcpp屬性'功能允許您更簡單地完成任務。考慮:

R> cppFunction('arma::mat op(arma::colvec x) { return x*x.t(); }', 
+    depends="RcppArmadillo") 
R> op(1:3) 
    [,1] [,2] [,3] 
[1,] 1 2 3 
[2,] 2 4 6 
[3,] 3 6 9 
R> 

其中I使用一個呼叫和一個(包裹)行以創建犰狳C++函數,以產生一個列向量的外積。

+0

嗨Drik,感謝您的回答,事實上,我已經測試了一個小例子,我將在這個問題中添加這個小的可重複的例子。對於一個小例子,函數在所有系統中運行都很完美,但是當問題的大小增加時,窗口和mac的增加似乎要高出幾個數量級。我只是想知道是不是一些系統要求,我沒有注意,因爲我只是使用Ubuntu的。我會考慮稍後閱讀新的Rcpp版本,謝謝。 – user1265067

+0

名稱是'Dirk',所以我偶爾也會錯誤地輸入它。否則,我在Ubuntu上開發它,並在所有三種操作系統上使用相當廣泛 - 錯誤可能出現在您的代碼中。 –

+0

嗨德克,對不起,錯了。我真的不認爲有一個「錯誤」,因爲該函數的結果是正確的,這個小例子甚至在我的virtualbox機器32位窗口中運行。我只是想知道是否有一些特定的RcppArmadillo操作,您在Windows上觀察到的速度較慢? – user1265067

相關問題