RcppEigen - 从内联到包中的.cpp函数,“Map” [英] RcppEigen - going from inline to a .cpp function in a package and "Map"

查看:516
本文介绍了RcppEigen - 从内联到包中的.cpp函数,“Map”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一切似乎都在我的包,但我想检查是否步骤,使它是正确的和关于内存使用地图。 (这是一个简单的例子,在内联示例和 fastLm()示例之间。)



是一个内联函数,它获得一个矩阵的每一列的最大值:

  library(Rcpp); 
library(inline);
library(RcppEigen);

maxOverColCpp< - '
使用Eigen :: Map;
使用Eigen :: MatrixXd;

//从R $映射双矩阵AA
const Map< MatrixXd> A(作为< Map< MatrixXd>(AA));

//评估和列向最大输入A
const MatrixXd Amax(A.colwise()。maxCoeff());
return wrap(Amax);
'

rcppeigen_max_over_columns< - cxxfunction(signature(AA =matrix),maxOverColCpp,plugin =RcppEigen)

然后更改函数以将其包含在现有的R包中,我重写了如下代码,保存在 rcppeigen_max_over_columns.cpp 在现有R程序包中的一个新 src 文件夹中:

  //我们只包括RcppEigen.h,它为我们拉扯Rcpp.h 
#include< RcppEigen.h>

//通过depends属性,我们告诉Rcpp为
// RcppEigen创建钩子,以便构建过程知道该做什么
//
// [[Rcpp :: depends(RcppEigen)]]

//通过exports属性我们告诉Rcpp使这个函数
//可从R
//
// [[Rcpp :: export]]
Eigen :: MatrixXd rcppeigen_max_over_columns(const Eigen :: MatrixXd& A){
Eigen :: MatrixXd Amax = A.colwise()。maxCoeff ;
return Amax;
}

(实际上它有点长了, 。)



然后:




  • FILE与以下行:



    导入:Rcpp(> = 0.11.3),RcppEigen(> = 0.3.2.2.0)



    LinkingTo:Rcpp,RcppEigen


  • 使用以下行修改NAMESPACE文件:



    useDynLib(toyRpackage)



    import(RcppEigen)



    importFrom(Rcpp,evalCpp)

  • Rcpp :: compileAttributes pkgdir =toyRpackage,verbose = getOption(verbose))




R CMD check R CMD build




  • 第一个问题是,将RcppEigen函数包含到现有R包中的过程是否正确? (我完全忽略任何 Makevars 文件或任何 .h 文件 - 我真的不知道他们做什么。我也试着复制 RcppEigen.package.skeleteon()设置,但我添加了我的函数)


  • 第二个问题是,我是否知道这个问题是否可以解决?需要在 rcppeigen_max_over_columns.cpp 中的某处使用Map,以便在将矩阵从R传递到C ++时不会复制矩阵?




我知道这是一个初学者的问题,但我有一些麻烦理解.cpp文件中的语法,因为我不知道任何C ++。我想也许这个问题可能会帮助别人谁也试图添加一个简单的功能到自己的包。 :)



此外,如果你对RcppArmadillo使用RcppEigen有任何强烈的感觉,请让我知道。我阅读了 http://thread.gmane.org/gmane.comp.lang .r.rcpp / 3522 。对于我的例子,最大列的列,RcppEigen似乎更快,不知道为什么。

解决方案


第一个问题是,将RcppEigen函数包含到现有R包中的这个过程是否正确? (我完全忽略任何Makevars文件或任何.h文件 - 我真的不知道他们做什么...也不真正理解NAMESPACE文件的更改,我试图复制RcppEigen.package.skeleteon )设置,但我添加我的功能到一个现有的包。所以这是很好知道如果我错过了一些可能是一个问题,以后是可以的。)


对于使用相对简单的C ++代码的基本R包,您不需要包含头文件,或自定义Makevars / Makefile或类似的东西。如果你构建更复杂的东西,你可能需要一个Makefile / Makevars来帮助处理构建过程,并且可能想使用头文件将接口与实现分离 - 但是你必须深入到底并拿起一些C ++书,因为有很多东西要学习。



换句话说 - 你所做的是完全正常的。对于简单的情况,只需在 src / 目录中使用 .cpp 文件c> Rcpp ,属性和其他同级包处理其余)


第二个问题是我是否需要一个Map在rcppeigen_max_over_columns.cpp中的某个地方,以便矩阵不会被复制,当它从R传递到C ++?


除非您特别使用可以重用底层数据的构造函数,否则将R对象传递给(非 - Rcpp )类时,数据几乎总是被复制。我不知道Eigen是否有一个可以重用内存的构造函数,但我建议除非你知道它很重要,不要担心它(因为复制一个范围的数据是通常很快)


Everything seems to work in my package, but I wanted to check if the steps to make it were correct and about memory use using "Map". (It's a simple example, somewhere in-between the inline examples and the fastLm() example.)

Here is an inline function that takes the maximum over each column of a matrix:

library(Rcpp); 
library(inline); 
library(RcppEigen);

maxOverColCpp <- '
    using Eigen::Map;
    using Eigen::MatrixXd;

   // Map the double matrix AA from R
   const Map<MatrixXd> A(as<Map<MatrixXd> >(AA));

   // evaluate and columnwise maximum entry of A
   const MatrixXd Amax(A.colwise().maxCoeff());
   return wrap(Amax);
'

rcppeigen_max_over_columns <- cxxfunction(signature(AA = "matrix"), maxOverColCpp, plugin = "RcppEigen")

Then to change the function to include it in an existing R package, I rewrote the code as follows, saved it in rcppeigen_max_over_columns.cpp in a new src folder in an existing R package:

// we only include RcppEigen.h which pulls Rcpp.h in for us
#include <RcppEigen.h>

// via the depends attribute we tell Rcpp to create hooks for
// RcppEigen so that the build process will know what to do
//
// [[Rcpp::depends(RcppEigen)]]

// via the exports attribute we tell Rcpp to make this function
// available from R
//
// [[Rcpp::export]]
Eigen::MatrixXd rcppeigen_max_over_columns(const Eigen::MatrixXd & A){
    Eigen::MatrixXd Amax = A.colwise().maxCoeff();
    return Amax;
}

(In fact it was a bit longer as I also needed to include finding the maximum over rows.)

Then:

  • modified the DESCRIPTION FILE with the lines:

    Imports: Rcpp (>= 0.11.3), RcppEigen (>= 0.3.2.2.0)

    LinkingTo: Rcpp, RcppEigen

  • modified the NAMESPACE file with the lines:

    useDynLib(toyRpackage)

    import(RcppEigen)

    importFrom(Rcpp, evalCpp)

  • in R terminal, typed this, which I assume glues the R and C++:

    Rcpp::compileAttributes(pkgdir="toyRpackage", verbose=getOption("verbose"))

Then as for a regular package, I did R CMD check and R CMD build.

  • First question is whether this process for including an RcppEigen function into an existing R package is correct? (I completely ignored any Makevars files or any .h files -- I don't really know what they do... Also don't really understand the changes to the NAMESPACE file. I tried to copy the RcppEigen.package.skeleteon() set-up but I am adding my function to an existing package. So it would be good to know if it's okay in case I missed something that could be a problem later.)

  • Second question is whether I need a "Map" somewhere in rcppeigen_max_over_columns.cpp so that the matrix isn't copied when it's passed from R to C++?

I know it's a beginner question, but I'm having some trouble understanding the syntax in .cpp files as I don't know any C++. I thought maybe this question might help someone else who is also trying to add a simple function to their package. :)

Also, if you have any strong feelings about using RcppEigen over RcppArmadillo, please let me know. I read http://thread.gmane.org/gmane.comp.lang.r.rcpp/3522 which was useful. For my example of taking max over columns, RcppEigen seems much faster, not sure why.

解决方案

First question is whether this process for including an RcppEigen function into an existing R package is correct? (I completely ignored any Makevars files or any .h files -- I don't really know what they do... Also don't really understand the changes to the NAMESPACE file. I tried to copy the RcppEigen.package.skeleteon() set-up but I am adding my function to an existing package. So it would be good to know if it's okay in case I missed something that could be a problem later.)

For basic R packages with relatively simple C++ code, you do not need to include header files, or a custom Makevars / Makefile or anything like that. If you build something more complicated, you might need a Makefile / Makevars to help handle the build process, and might want to use header files to separate the interface from the implementation -- but for that you'll have to dive in the deep end and pick up some C++ books, because there's a lot to learn.

In other words -- what you're doing is perfectly fine. For simple cases, it's fine to just use .cpp files in the src/ directory (and let Rcpp, attributes, and its other sibling packages handle the rest)

Second question is whether I need a "Map" somewhere in rcppeigen_max_over_columns.cpp so that the matrix isn't copied when it's passed from R to C++?

Well, data will almost always be copied when transferring an R object to a (non-Rcpp) class, unless you specifically use a constructor that can re-use the underlying data. I am not aware of whether Eigen has a constructor that can re-use memory, but I would suggest that unless you know that it matters, don't worry about it (because copying a range of data is typically quite fast)

这篇关于RcppEigen - 从内联到包中的.cpp函数,“Map”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆