Rcpp:使用模板函数时发生错误

时间:2016-09-10 03:50:01

标签: c++ templates rcpp r-bigmemory

我正在修改我的biglasso包以适应big.matrix的不同数据类型。当前版本仅支持double类型。源代码为here

我所做的只是简单地添加template标题,并对以big.matrix作为输入的函数进行必要的更改。下面的函数是一个示例:xpMat是指向big.matrix的指针。

template<typename T>
double crossprod_bm(XPtr<BigMatrix> xpMat, double *y_, int *row_idx_, double center_, 
                               double scale_, int n_row, int j) {
  // Previous code:
  // MatrixAccessor<double> xAcc(*xpMat);
  // double *xCol = xAcc[j];
  MatrixAccessor<T> xAcc(*xpMat);
  T *xCol = xAcc[j];

  double sum = 0.0;
  double sum_xy = 0.0;
  double sum_y = 0.0;
  for (int i=0; i < n_row; i++) {
    // row_idx only used by xP, not by y;
    sum_xy = sum_xy + xCol[row_idx_[i]] * y_[i];
    sum_y = sum_y + y_[i];
  }
  sum = (sum_xy - center_ * sum_y) / scale_;

  return sum;
}

但是,在我进行更改后,R包无法编译。以下是错误消息。对我说它与crossprod_bm有关的东西出了问题:

Symbol not found: __Z12crossprod_bmIdEdN4Rcpp4XPtrI9BigMatrixNS0_15PreserveStorageEXadL_ZNS0_25standard_delete_finalizerIS2_EEvPT_EEEEPdPiddii

谁能告诉我这些错误是什么?这些错误与类型转换有关吗?我假设计算中的类型转换可以自动完成。

非常感谢你!

clang-omp++ -I/Library/Frameworks/R.framework/Resources/include -DNDEBUG  -I/usr/local/include -I/usr/local/include/freetype2 -I/opt/X11/include -I"/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcpp/include" -I"/Library/Frameworks/R.framework/Versions/3.3/Resources/library/RcppArmadillo/include" -I"/Library/Frameworks/R.framework/Versions/3.3/Resources/library/bigmemory/include" -I"/Library/Frameworks/R.framework/Versions/3.3/Resources/library/BH/include"  -fopenmp -std=c++11 -O3 -funroll-loops -fPIC  -Wall -mtune=core2 -g -O2  -c gaussian_hsr.cpp -o gaussian_hsr.o
clang-omp++ -I/Library/Frameworks/R.framework/Resources/include -DNDEBUG  -I/usr/local/include -I/usr/local/include/freetype2 -I/opt/X11/include -I"/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcpp/include" -I"/Library/Frameworks/R.framework/Versions/3.3/Resources/library/RcppArmadillo/include" -I"/Library/Frameworks/R.framework/Versions/3.3/Resources/library/bigmemory/include" -I"/Library/Frameworks/R.framework/Versions/3.3/Resources/library/BH/include"  -fopenmp -std=c++11 -O3 -funroll-loops -fPIC  -Wall -mtune=core2 -g -O2  -c gaussian_hsr_dome.cpp -o gaussian_hsr_dome.o
clang-omp++ -I/Library/Frameworks/R.framework/Resources/include -DNDEBUG  -I/usr/local/include -I/usr/local/include/freetype2 -I/opt/X11/include -I"/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcpp/include" -I"/Library/Frameworks/R.framework/Versions/3.3/Resources/library/RcppArmadillo/include" -I"/Library/Frameworks/R.framework/Versions/3.3/Resources/library/bigmemory/include" -I"/Library/Frameworks/R.framework/Versions/3.3/Resources/library/BH/include"  -fopenmp -std=c++11 -O3 -funroll-loops -fPIC  -Wall -mtune=core2 -g -O2  -c utilities.cpp -o utilities.o
clang-omp++ -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_module -multiply_defined suppress -L/Library/Frameworks/R.framework/Resources/lib -L/usr/local/lib -o biglasso.so binomial_hsr.o binomial_hsr_approx.o gaussian_edpp.o gaussian_hsr.o gaussian_hsr_dome.o utilities.o -fopenmp -lgomp -F/Library/Frameworks/R.framework/.. -framework R -Wl,-framework -Wl,CoreFoundation
installing to /Users/yazeng/GitHub/biglasso.Rcheck/biglasso/libs
** R
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
Error in dyn.load(file, DLLpath = DLLpath, ...) : 
  unable to load shared object '/Users/yazeng/GitHub/biglasso.Rcheck/biglasso/libs/biglasso.so':
  dlopen(/Users/yazeng/GitHub/biglasso.Rcheck/biglasso/libs/biglasso.so, 6): Symbol not found: __Z12crossprod_bmIdEdN4Rcpp4XPtrI9BigMatrixNS0_15PreserveStorageEXadL_ZNS0_25standard_delete_finalizerIS2_EEvPT_EEEEPdPiddii
  Referenced from: /Users/yazeng/GitHub/biglasso.Rcheck/biglasso/libs/biglasso.so
  Expected in: flat namespace
 in /Users/yazeng/GitHub/biglasso.Rcheck/biglasso/libs/biglasso.so
Error: loading failed
Execution halted
ERROR: loading failed
* removing ‘/Users/yazeng/GitHub/biglasso.Rcheck/biglasso’

[更新以响应@Coatless]

我确实有调度员,如下。

template<typename T>  
List cdfit_gaussian_edpp_cpp(XPtr<BigMatrix> xMat,
                             SEXP y_, SEXP row_idx_, SEXP lambda_, 
                                    SEXP nlambda_, SEXP lam_scale_,
                                    SEXP lambda_min_, SEXP alpha_, 
                                    SEXP user_, SEXP eps_, SEXP max_iter_, 
                                    SEXP multiplier_, SEXP dfmax_, 
                                    SEXP ncore_, SEXP verbose_);

RcppExport SEXP cdfit_gaussian_edpp(SEXP X_, SEXP y_, SEXP row_idx_, SEXP lambda_, 
                                    SEXP nlambda_, SEXP lam_scale_,
                                    SEXP lambda_min_, SEXP alpha_, 
                                    SEXP user_, SEXP eps_, SEXP max_iter_, 
                                    SEXP multiplier_, SEXP dfmax_, 
                                    SEXP ncore_, SEXP verbose_) {
  XPtr<BigMatrix> xMat(X_);
  int xtype = xMat->matrix_type();

  switch(xtype)
  {
  case 2:
    return cdfit_gaussian_edpp_cpp<short>(xMat, y_, row_idx_, lambda_,nlambda_, 
                                         lam_scale_, lambda_min_,alpha_, 
                                         user_, eps_, max_iter_, multiplier_, 
                                         dfmax_, ncore_, verbose_);
  case 4:
    return cdfit_gaussian_edpp_cpp<int>(xMat, 
                                       y_, row_idx_, lambda_,nlambda_, 
                                       lam_scale_, lambda_min_,alpha_, 
                                       user_, eps_, max_iter_, multiplier_, 
                                       dfmax_, ncore_, verbose_);
  case 6:
    return cdfit_gaussian_edpp_cpp<float>(xMat,
                                         y_, row_idx_, lambda_,nlambda_, 
                                         lam_scale_, lambda_min_,alpha_, 
                                         user_, eps_, max_iter_, multiplier_, 
                                         dfmax_, ncore_, verbose_);
  case 8:
    return cdfit_gaussian_edpp_cpp<double>(xMat,
                                          y_, row_idx_, lambda_,nlambda_, 
                                          lam_scale_, lambda_min_,alpha_, 
                                          user_, eps_, max_iter_, multiplier_, 
                                          dfmax_, ncore_, verbose_);
  default:
    throw Rcpp::exception("the type defined for big.matrix is not supported!");
  }
}

template<typename T>  
List cdfit_gaussian_edpp_cpp(XPtr<BigMatrix> xMat,
                             SEXP y_, SEXP row_idx_, SEXP lambda_, 
                                    SEXP nlambda_, SEXP lam_scale_,
                                    SEXP lambda_min_, SEXP alpha_, 
                                    SEXP user_, SEXP eps_, SEXP max_iter_, 
                                    SEXP multiplier_, SEXP dfmax_, 
                                    SEXP ncore_, SEXP verbose_) {
...    
// Within this function, need call lower-level functions, e.g. crossprod_bm 
double res = crossprod_bm<T>(xMat, y, row_idx, ...)
...


}

[结束更新]

[更新2]

我将所有更改都提交到GitHub,以便您可以看到整个图片。如果您能提出任何意见,我将不胜感激。

[更新2]

[更新3]

我认为cdfit_gaussian_edpp_cpp应该返回Rcpp::List。我纠正了这个(如上所述),但仍然有类似的错误。

似乎我的代码中的模板一定出现问题,可能是定义模板?调用模板?

如果我不使用模板,一切都会成功!例如,如果我将错误消息中捕获的函数恢复为不是模板函数,那么会发生的是错误中不会捕获该函数。但是下一个模板函数将被捕获并出现类似的错误消息。

然而,另一方面,我试图关注an example using Rcpp and bigmemory。我更改了模板功能,如下所示,这与我在包中使用模板的方式类似。但它的确有效!这让我觉得我正确使用模板。

我真的很困惑,感谢任何专家指出这个错误!非常感谢你!

// Logic for BigColSums.
template <typename T>
vector<int> BigColSums2(XPtr<BigMatrix> pMat) {

  // Create the vector we'll store the column sums in.
  MatrixAccessor<T> mat(*pMat);
  vector<int> colSums(pMat->ncol());
  for (size_t i=0; i < pMat->ncol(); i++) {
    for (size_t j=0; j < pMat->ncol(); j++) {
      colSums[i] += mat[i][j];
    }
  }
  return colSums;
}

// Dispatch function for BigColSums
//
// [[Rcpp::export]]
NumericVector BigColSums(SEXP pBigMat) {
  // First we have to tell Rcpp what class to use for big.matrix objects.
  // This object stores the attributes of the big.matrix object passed to it
  // by R.
  XPtr<BigMatrix> xpMat(pBigMat);

  // To access values in the big.matrix, we need to create a MatrixAccessor
  // object of the appropriate type. Note that in every case we are still
  // returning a NumericVector: this is because big.matrix objects only store
  // numeric values in R, even if their type is set to 'char'. The types
  // simply correspond to the number of bytes used for each element.
  switch(xpMat->matrix_type()) {
  case 1:
    return Rcpp::wrap(BigColSums2<char>(xpMat));
  case 2:
    return Rcpp::wrap(BigColSums2<short>(xpMat));
  case 4:
    return Rcpp::wrap(BigColSums2<int>(xpMat));
  case 8:
    return Rcpp::wrap(BigColSums2<double>(xpMat));
  // case 1:
  //   return BigColSums<char>(xpMat);
  // case 2:
  //   return BigColSums<short>(xpMat);
  // case 4:
  //   return BigColSums<int>(xpMat);
  // case 8:
  //   return BigColSums<double>(xpMat);
  default:
    // This case should never be encountered unless the implementation of
    // big.matrix changes, but is necessary to implement shut up compiler
    // warnings.
    throw Rcpp::exception("unknown type detected for big.matrix object!");
  }
}

[更新3]

0 个答案:

没有答案