<div dir="ltr">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.<div>
<br></div><div style>A simple example to illustrate (also shows how you can discover these things yourself):</div><div style><br></div><div style>---</div><div style><br></div><div style><div>#include <Rcpp.h></div>
<div><br></div><div>// [[Rcpp::export]]</div><div>Rcpp::NumericVector test_numeric(Rcpp::NumericVector x) {</div><div> </div><div> x = x + 1;</div><div> return x;</div><div> </div><div>}</div><div><br></div><div>// [[Rcpp::export]]</div>
<div>Rcpp::IntegerVector test_integer(Rcpp::IntegerVector x) {</div><div> x = x + 1;</div><div> return x;</div><div>}</div><div><br></div><div>/*** R</div><div>x <- c(1, 2, 3)</div><div><br></div><div>test_numeric(x) ## returns c(2, 3, 4)</div>
<div>print(x) ## x is now c(2, 3, 4)</div><div><br></div><div>test_integer(x) ## returns c(3, 4, 5)</div><div>print(x) ## x is still c(2, 3, 4)</div><div>*/</div><div><br></div><div>---</div><div><br></div><div style>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.</div>
<div><br></div><div style>-Kevin</div></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Sat, Jun 8, 2013 at 12:22 PM, Simon Zehnder <span dir="ltr"><<a href="mailto:szehnder@uni-bonn.de" target="_blank">szehnder@uni-bonn.de</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Romain,<br>
<br>
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.<br>
<br>
You answered to my question<br>
<br>
"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":<br>
<div class="im"><br>
Depends what is M, but most of the time yes, as<> copies data.<br>
<br>
</div>What I then tried, was this:<br>
<div class="im"><br>
setClass("myclass", representation(par = "list"))<br>
l <- list(lambda = array(0, dim = c(10,2)))<br>
mclass <- new("myclass", par = l)<br>
</div>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")<br>
<div class="im">cfunction(mclass)<br>
An object of class "myclass"<br>
Slot "par":<br>
$lambda<br>
[,1] [,2]<br>
[1,] 1.2 0<br>
[2,] 0.0 0<br>
[3,] 0.0 0<br>
[4,] 0.0 0<br>
[5,] 0.0 0<br>
[6,] 0.0 0<br>
[7,] 0.0 0<br>
[8,] 0.0 0<br>
[9,] 0.0 0<br>
[10,] 0.0 0<br>
<br>
</div>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.<br>
<br>
<br>
Best<br>
<span class="HOEnZb"><font color="#888888"><br>
Simon<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
<br>
On Jun 8, 2013, at 8:08 AM, Romain Francois <<a href="mailto:romain@r-enthusiasts.com">romain@r-enthusiasts.com</a>> wrote:<br>
<br>
> Le 07/06/13 16:07, Simon Zehnder a écrit :<br>
>> Hi Romain,<br>
>><br>
>> thanks for this precise answer. So the suggested methods below will work without making a copy of the object.<br>
><br>
> yes<br>
><br>
>> 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.<br>
><br>
> I don't know what you are talking about.<br>
><br>
>> Best<br>
>><br>
>> Simon<br>
>> On Jun 7, 2013, at 3:47 PM, Romain Francois <<a href="mailto:romain@r-enthusiasts.com">romain@r-enthusiasts.com</a>> wrote:<br>
>><br>
>>> Le 07/06/13 15:14, Simon Zehnder a écrit :<br>
>>>> Hi Romain, hi Dirk,<br>
>>>><br>
>>>> sorry for posting here again, but I found something in some way connected to this discussion - and pretty interesting concerning the Rcpp::as<>() function:<br>
>>>><br>
>>>> 1. I create a class containing a list:<br>
>>>><br>
>>>> setClass("myclass", representation(par = "list"))<br>
>>>><br>
>>>> l <- list(lambda = array(0, dim = c(10,2)))<br>
>>>><br>
>>>> mclass <- new("myclass", par = l)<br>
>>>><br>
>>>> 2. I compile a C++ function, that should reuse the memory of 'lambda' inside the list:<br>
>>>><br>
>>>> library(inline)<br>
>>>> 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")<br>
>>>><br>
>>>> I get an error:<br>
>>>><br>
>>>> Error in compileCode(f, code, language = language, verbose = verbose) :<br>
>>>> Compilation ERROR, function(s)/method(s) not created! file6fc2ab39965.cpp: In function ‘SEXPREC* file6fc2ab39965(SEXP)’:<br>
>>>> file6fc2ab39965.cpp:30:109: error: ‘Rcpp::Vector<19>::NameProxy’ has no member named ‘begin’<br>
>>>> 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);<br>
>>><br>
>>> 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.<br>
>>><br>
>>> Do this:<br>
>>><br>
>>> NumericVector tmp = parL["lambda"] ;<br>
>>> arma::mat armaPar(tmp.begin(), 10, 2, false, true);<br>
>>><br>
>>> This will not make copies of the data.<br>
>>><br>
>>> If thius feels like too much to type, just stuff this into a function:<br>
>>><br>
>>> inline arma::mat convert( SEXP x ){<br>
>>> NumericVector tmp = parL["lambda"] ;<br>
>>> return arma::mat(tmp.begin(), 10, 2, false, true);<br>
>>> }<br>
>>><br>
>>> and call :<br>
>>><br>
>>> arma::mat armaPar = convert( parL["lambda"] ) ;<br>
>>><br>
>>> There is a chance convert won't make a copy thanks to RVO.<br>
>>> ^<br>
>>>> make: *** [file6fc2ab39965.o] Error 1<br>
>>>> In addition: Warning message:<br>
>>>> running command '/Library/Frameworks/R.framework/Resources/bin/R CMD SHLIB file6fc2ab39965.cpp 2> file6fc2ab39965.cpp.err.txt' had status 1<br>
>>>><br>
>>>> -----------------------------------------------------------<br>
>>>><br>
>>>> It seems, that the SEXP inside the List is not yet an Rcpp::NumericMatrix, so I make it explicit to the arma::mat() constructor:<br>
>>>><br>
>>>> 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")<br>
>>>><br>
>>>> That compiles.<br>
>>>><br>
>>>> If we let it run it gives us:<br>
>>>><br>
>>>> cfunction(mclass)<br>
>>>> An object of class "myclass"<br>
>>>> Slot "par":<br>
>>>> $lambda<br>
>>>> [,1] [,2]<br>
>>>> [1,] 1.2 0<br>
>>>> [2,] 0.0 0<br>
>>>> [3,] 0.0 0<br>
>>>> [4,] 0.0 0<br>
>>>> [5,] 0.0 0<br>
>>>> [6,] 0.0 0<br>
>>>> [7,] 0.0 0<br>
>>>> [8,] 0.0 0<br>
>>>> [9,] 0.0 0<br>
>>>> [10,] 0.0 0<br>
>>>><br>
>>>> So, we can see, that implicitly calling Rcpp::as<>() inside the constructor arma::mat() avoids a copy by Rcpp::as<>() - which is just beautiful!<br>
>>>><br>
>>>><br>
>>>> Best<br>
>>>><br>
>>>> Simon<br>
>>>><br>
>>>><br>
>>>><br>
>>>><br>
>>>><br>
>>>> On Jun 7, 2013, at 1:19 PM, Simon Zehnder <<a href="mailto:szehnder@uni-bonn.de">szehnder@uni-bonn.de</a>> wrote:<br>
>>>><br>
>>>>> Thank you Romain!<br>
>>>>><br>
>>>>> All clear now!<br>
>>>>><br>
>>>>><br>
>>>>> Best<br>
>>>>><br>
>>>>> Simon<br>
>>>>><br>
>>>>> On Jun 7, 2013, at 1:13 PM, Romain Francois <<a href="mailto:romain@r-enthusiasts.com">romain@r-enthusiasts.com</a>> wrote:<br>
>>>>><br>
>>>>>> Le 07/06/13 13:09, Simon Zehnder a écrit :<br>
>>>>>>> HI Dirk, hi Romain,<br>
>>>>>>><br>
>>>>>>> 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.<br>
>>>>>><br>
>>>>>> so far, this is obvious.<br>
>>>>>><br>
>>>>>>> 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.<br>
>>>>>><br>
>>>>>> Depends what is M, but most of the time yes, as<> copies data.<br>
>>>>>><br>
>>>>>>> Best<br>
>>>>>>><br>
>>>>>>> Simon<br>
>>>>>>><br>
>>>>>>><br>
>>>>>>> On Jun 6, 2013, at 8:31 PM, Dirk Eddelbuettel <<a href="mailto:edd@debian.org">edd@debian.org</a>> wrote:<br>
>>>>>>><br>
>>>>>>>><br>
>>>>>>>> On 6 June 2013 at 13:17, Dirk Eddelbuettel wrote:<br>
>>>>>>>> |<br>
>>>>>>>> | On 6 June 2013 at 19:05, Simon Zehnder wrote:<br>
>>>>>>>> | | 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?<br>
>>>>>>>> |<br>
>>>>>>>> | But how could an _unsigned int_ from Armadillo possibly have the same value<br>
>>>>>>>> | as a _signed int_ in R?<br>
>>>>>>>> |<br>
>>>>>>>> | Either you are efficient (no copy), or you are correct (with a copy). I do<br>
>>>>>>>> | not see how you could have both.<br>
>>>>>>>><br>
>>>>>>>> Sorry -- please ignore this message.<br>
>>>>>>>><br>
>>>>>>>> I had mistakenly assumed that you were still thinking about arma::umat to<br>
>>>>>>>> integer. For direct int-to-int this is indeed efficient just like the<br>
>>>>>>>> double-to-double is for arma::mat to NumericMatrix (and dito for vectors). I<br>
>>>>>>>> though that was a given -- maybe need to make this (even) more explicit in<br>
>>>>>>>> the documentation.<br>
>>>>>>>><br>
>>>>>>>> So in sum: you get correct and efficient behaviour if and only if you stick<br>
>>>>>>>> with the types natively supported in Armadillo and R.<br>
>>>>>>>><br>
>>>>>>>> Dirk<br>
>>>>>>>><br>
><br>
><br>
> --<br>
> Romain Francois<br>
> Professional R Enthusiast<br>
> <a href="tel:%2B33%280%29%206%2028%2091%2030%2030" value="+33628913030">+33(0) 6 28 91 30 30</a><br>
><br>
> R Graph Gallery: <a href="http://gallery.r-enthusiasts.com" target="_blank">http://gallery.r-enthusiasts.com</a><br>
><br>
> blog: <a href="http://blog.r-enthusiasts.com" target="_blank">http://blog.r-enthusiasts.com</a><br>
> |- <a href="http://bit.ly/Zs97qg" target="_blank">http://bit.ly/Zs97qg</a> : highlight 0.4.1<br>
> `- <a href="http://bit.ly/10X94UM" target="_blank">http://bit.ly/10X94UM</a> : Mobile version of the graph gallery<br>
><br>
<br>
_______________________________________________<br>
Rcpp-devel mailing list<br>
<a href="mailto:Rcpp-devel@lists.r-forge.r-project.org">Rcpp-devel@lists.r-forge.r-project.org</a><br>
<a href="https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel" target="_blank">https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div dir="ltr">-Kevin</div>
</div>