I'm pretty the sure the Rcpp / RcppArmadillo way is to reuse memory whenever the types match between the as'ed containers, and copy if type coercion makes sense. Ie, an R integer vector --> an Rcpp IntegerVector would reuse the same memory, while an R integer vector --> an Rcpp NumericVector would require a copy and a coercion from integer to numeric. Similar things will apply between R and RcppArmadillo. Just remember that with R, numeric <-> double, integer <-> signed int.
A simple example to illustrate (also shows how you can discover these things yourself): --- #include <Rcpp.h> // [[Rcpp::export]] Rcpp::NumericVector test_numeric(Rcpp::NumericVector x) { x = x + 1; return x; } // [[Rcpp::export]] Rcpp::IntegerVector test_integer(Rcpp::IntegerVector x) { x = x + 1; return x; } /*** R x <- c(1, 2, 3) test_numeric(x) ## returns c(2, 3, 4) print(x) ## x is now c(2, 3, 4) test_integer(x) ## returns c(3, 4, 5) print(x) ## x is still c(2, 3, 4) */ --- Since this thread has become rather long, I suggest generating your own minimal examples whenever you need to discover / be certain whether you're reusing memory or forcing a copy. -Kevin On Sat, Jun 8, 2013 at 12:22 PM, Simon Zehnder <szehn...@uni-bonn.de> wrote: > Hi Romain, > > I considered the implicit use of Rcpp::as<>() inside of the arma::mat() > constructor. My target was to reuse memory and try to use a very simple > setting, i.e. (at least in my opinion) not too much lines of code. > > You answered to my question > > "On the other side I then assume, that the Rcpp:as<class M>() function > makes a cast and therefore creates a copy with new allocated memory of the > type included in M? Therefore a reuse of memory with this function is not > possible": > > Depends what is M, but most of the time yes, as<> copies data. > > What I then tried, was this: > > setClass("myclass", representation(par = "list")) > l <- list(lambda = array(0, dim = c(10,2))) > mclass <- new("myclass", par = l) > cfunction <- cxxfunction(signature(myClass_R = "array"), body = 'Rcpp::S4 > myclass(myClass_R); Rcpp::List parL((SEXP) myclass.slot("par")); arma::mat > armaPar(Rcpp::as<Rcpp::NumericMatrix>(parL["lambda"]).begin(), 10, 2, > false, true); armaPar(0,0) = 1.2 ;return Rcpp::wrap(myclass);', plugin = > "RcppArmadillo") > cfunction(mclass) > An object of class "myclass" > Slot "par": > $lambda > [,1] [,2] > [1,] 1.2 0 > [2,] 0.0 0 > [3,] 0.0 0 > [4,] 0.0 0 > [5,] 0.0 0 > [6,] 0.0 0 > [7,] 0.0 0 > [8,] 0.0 0 > [9,] 0.0 0 > [10,] 0.0 0 > > So, it seems, that calling Rcpp::as<>() implicitly inside the arma::mat() > constructor, enables the reuse of memory with only a few lines of code, > which is pretty nice. So in case of M being Rcpp::NumericMatrix, > Rcpp::as<>() seems not to copy data. But it also could be, that I > misunderstood your answer above, or that we were talking about two > different things there. In this case please apologize my confusion. > > > Best > > Simon > > > On Jun 8, 2013, at 8:08 AM, Romain Francois <rom...@r-enthusiasts.com> > wrote: > > > Le 07/06/13 16:07, Simon Zehnder a écrit : > >> Hi Romain, > >> > >> thanks for this precise answer. So the suggested methods below will > work without making a copy of the object. > > > > yes > > > >> What is about the implicit call of Rcpp::as<>() inside arma::mat()? It > is a very convenient way to create an arma object reusing memory and it > seems to work just fine. > > > > I don't know what you are talking about. > > > >> Best > >> > >> Simon > >> On Jun 7, 2013, at 3:47 PM, Romain Francois <rom...@r-enthusiasts.com> > wrote: > >> > >>> Le 07/06/13 15:14, Simon Zehnder a écrit : > >>>> Hi Romain, hi Dirk, > >>>> > >>>> sorry for posting here again, but I found something in some way > connected to this discussion - and pretty interesting concerning the > Rcpp::as<>() function: > >>>> > >>>> 1. I create a class containing a list: > >>>> > >>>> setClass("myclass", representation(par = "list")) > >>>> > >>>> l <- list(lambda = array(0, dim = c(10,2))) > >>>> > >>>> mclass <- new("myclass", par = l) > >>>> > >>>> 2. I compile a C++ function, that should reuse the memory of 'lambda' > inside the list: > >>>> > >>>> library(inline) > >>>> cfunction <- cxxfunction(signature(myClass_R = "array"), body = > 'Rcpp::S4 myclass(myClass_R); Rcpp::List parL((SEXP) myclass.slot("par")); > arma::mat armaPar(parL["lambda"].begin(), 10, 2, false, true); armaPar(0,0) > = 1.2 ;return Rcpp::wrap(myclass);', plugin = "RcppArmadillo") > >>>> > >>>> I get an error: > >>>> > >>>> Error in compileCode(f, code, language = language, verbose = verbose) > : > >>>> Compilation ERROR, function(s)/method(s) not created! > file6fc2ab39965.cpp: In function ‘SEXPREC* file6fc2ab39965(SEXP)’: > >>>> file6fc2ab39965.cpp:30:109: error: ‘Rcpp::Vector<19>::NameProxy’ has > no member named ‘begin’ > >>>> Rcpp::S4 myclass(myClass_R); Rcpp::List parL((SEXP) > myclass.slot("par")); arma::umat armaPar(parL["lambda"].begin(), 100, 10, > false, true); armaPar(0,0) = 1.2 ;return Rcpp::wrap(myclass); > >>> > >>> What you get from doing parL["lambda"] is an object of class > NameProxy, it will be converted to the appropioate class later. NameProxy > have no .begin method. > >>> > >>> Do this: > >>> > >>> NumericVector tmp = parL["lambda"] ; > >>> arma::mat armaPar(tmp.begin(), 10, 2, false, true); > >>> > >>> This will not make copies of the data. > >>> > >>> If thius feels like too much to type, just stuff this into a function: > >>> > >>> inline arma::mat convert( SEXP x ){ > >>> NumericVector tmp = parL["lambda"] ; > >>> return arma::mat(tmp.begin(), 10, 2, false, true); > >>> } > >>> > >>> and call : > >>> > >>> arma::mat armaPar = convert( parL["lambda"] ) ; > >>> > >>> There is a chance convert won't make a copy thanks to RVO. > >>> ^ > >>>> make: *** [file6fc2ab39965.o] Error 1 > >>>> In addition: Warning message: > >>>> running command '/Library/Frameworks/R.framework/Resources/bin/R CMD > SHLIB file6fc2ab39965.cpp 2> file6fc2ab39965.cpp.err.txt' had status 1 > >>>> > >>>> ----------------------------------------------------------- > >>>> > >>>> It seems, that the SEXP inside the List is not yet an > Rcpp::NumericMatrix, so I make it explicit to the arma::mat() constructor: > >>>> > >>>> cfunction <- cxxfunction(signature(myClass_R = "array"), body = > 'Rcpp::S4 myclass(myClass_R); Rcpp::List parL((SEXP) myclass.slot("par")); > arma::mat armaPar(Rcpp::as<Rcpp::NumericMatrix>(parL["lambda"]).begin(), > 100, 10, false, true); armaPar(0,0) = 1.2 ;return Rcpp::wrap(myclass);', > plugin = "RcppArmadillo") > >>>> > >>>> That compiles. > >>>> > >>>> If we let it run it gives us: > >>>> > >>>> cfunction(mclass) > >>>> An object of class "myclass" > >>>> Slot "par": > >>>> $lambda > >>>> [,1] [,2] > >>>> [1,] 1.2 0 > >>>> [2,] 0.0 0 > >>>> [3,] 0.0 0 > >>>> [4,] 0.0 0 > >>>> [5,] 0.0 0 > >>>> [6,] 0.0 0 > >>>> [7,] 0.0 0 > >>>> [8,] 0.0 0 > >>>> [9,] 0.0 0 > >>>> [10,] 0.0 0 > >>>> > >>>> So, we can see, that implicitly calling Rcpp::as<>() inside the > constructor arma::mat() avoids a copy by Rcpp::as<>() - which is just > beautiful! > >>>> > >>>> > >>>> Best > >>>> > >>>> Simon > >>>> > >>>> > >>>> > >>>> > >>>> > >>>> On Jun 7, 2013, at 1:19 PM, Simon Zehnder <szehn...@uni-bonn.de> > wrote: > >>>> > >>>>> Thank you Romain! > >>>>> > >>>>> All clear now! > >>>>> > >>>>> > >>>>> Best > >>>>> > >>>>> Simon > >>>>> > >>>>> On Jun 7, 2013, at 1:13 PM, Romain Francois < > rom...@r-enthusiasts.com> wrote: > >>>>> > >>>>>> Le 07/06/13 13:09, Simon Zehnder a écrit : > >>>>>>> HI Dirk, hi Romain, > >>>>>>> > >>>>>>> allright, this is now clear to me, if I want to reuse memory, the > allocated memory from R (so implicitly in C) must of course have the same > type - otherwise the memory has a different size. > >>>>>> > >>>>>> so far, this is obvious. > >>>>>> > >>>>>>> On the other side I then assume, that the Rcpp:as<class M>() > function makes a cast and therefore creates a copy with new allocated > memory of the type included in M? Therefore a reuse of memory with this > function is not possible. > >>>>>> > >>>>>> Depends what is M, but most of the time yes, as<> copies data. > >>>>>> > >>>>>>> Best > >>>>>>> > >>>>>>> Simon > >>>>>>> > >>>>>>> > >>>>>>> On Jun 6, 2013, at 8:31 PM, Dirk Eddelbuettel <e...@debian.org> > wrote: > >>>>>>> > >>>>>>>> > >>>>>>>> On 6 June 2013 at 13:17, Dirk Eddelbuettel wrote: > >>>>>>>> | > >>>>>>>> | On 6 June 2013 at 19:05, Simon Zehnder wrote: > >>>>>>>> | | sorry I had overseen this message from you. Okay, so the > explicit cast to SEXP together with the assignment operator makes the deal. > But it still includes the reuse of memory right, i.e. the '=' does not call > the copy constructor? > >>>>>>>> | > >>>>>>>> | But how could an _unsigned int_ from Armadillo possibly have > the same value > >>>>>>>> | as a _signed int_ in R? > >>>>>>>> | > >>>>>>>> | Either you are efficient (no copy), or you are correct (with a > copy). I do > >>>>>>>> | not see how you could have both. > >>>>>>>> > >>>>>>>> Sorry -- please ignore this message. > >>>>>>>> > >>>>>>>> I had mistakenly assumed that you were still thinking about > arma::umat to > >>>>>>>> integer. For direct int-to-int this is indeed efficient just > like the > >>>>>>>> double-to-double is for arma::mat to NumericMatrix (and dito for > vectors). I > >>>>>>>> though that was a given -- maybe need to make this (even) more > explicit in > >>>>>>>> the documentation. > >>>>>>>> > >>>>>>>> So in sum: you get correct and efficient behaviour if and only if > you stick > >>>>>>>> with the types natively supported in Armadillo and R. > >>>>>>>> > >>>>>>>> Dirk > >>>>>>>> > > > > > > -- > > Romain Francois > > Professional R Enthusiast > > +33(0) 6 28 91 30 30 > > > > R Graph Gallery: http://gallery.r-enthusiasts.com > > > > blog: http://blog.r-enthusiasts.com > > |- http://bit.ly/Zs97qg : highlight 0.4.1 > > `- http://bit.ly/10X94UM : Mobile version of the graph gallery > > > > _______________________________________________ > Rcpp-devel mailing list > Rcpp-devel@lists.r-forge.r-project.org > https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel > -- -Kevin
_______________________________________________ Rcpp-devel mailing list Rcpp-devel@lists.r-forge.r-project.org https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel