<div dir="ltr"><div>Thanks to all for all the great repliies. I have to go through them but it sounds like memcopy</div><div>is the best so I'll probably ending use that.  Amazing to be part of this list and receive all of</div><div>this wisdom. <br></div><div><br></div><div>Oh, as I said, the documentation on Rcpp is incredible but is there anything discussing memory because</div><div>I'm pretty lost on that. Thanks again.</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Dec 10, 2018 at 8:42 AM Serguei Sokol <<a href="mailto:serguei.sokol@gmail.com">serguei.sokol@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Le 10/12/2018 à 13:04, Jan van der Laan a écrit :<br>
> Small addendum: A large part of the performance gain in my example comes <br>
> from using NumericVector instead of std::vector<double>. Which avoids a <br>
> conversion. An example using std::copy with Numeric vector runs in the <br>
> same time as the version using memcpy.<br>
<br>
Yep.<br>
Few more percents of mean cpu time can be saved by using "const &" trick :<br>
<br>
// [[Rcpp::export]]<br>
NumericVector mybar5(const NumericVector &x, const NumericVector &y) {<br>
    NumericVector result(x.size() + y.size());<br>
    std::memcpy(result.begin(), x.begin(), x.size()*sizeof(double));<br>
    std::memcpy(result.begin()+x.size(), y.begin(), <br>
y.size()*sizeof(double));<br>
    return result;<br>
}<br>
<br>
# output<br>
Unit: microseconds<br>
                       expr     min       lq     mean   median       uq <br>
     max<br>
       c(testelem, testvec) 258.343 338.3110 418.0047 343.4450 378.7850 <br>
3077.347<br>
   mybar(testvec, testelem) 352.699 366.8770 498.3948 374.6635 450.4420 <br>
3046.408<br>
  mybar2(testvec, testelem) 334.820 348.3685 425.0098 354.7240 366.5270 <br>
3024.128<br>
  mybar3(testvec, testelem) 233.689 244.8640 315.7256 247.5180 255.0955 <br>
2945.068<br>
  mybar4(testvec, testelem) 232.083 241.9655 340.0751 245.0035 252.8260 <br>
2934.312<br>
  mybar5(testvec, testelem) 150.787 242.7685 285.4264 245.9465 254.1880 <br>
2049.493<br>
<br>
Serguei.<br>
<br>
> <br>
> Jan<br>
> <br>
> <br>
> <br>
> On 10-12-18 12:28, Jan van der Laan wrote:<br>
>><br>
>> For performance memcpy is probably fastest. This gives the same <br>
>> performance a c().<br>
>><br>
>> // [[Rcpp::export]]<br>
>> NumericVector mybar3(NumericVector x, double firstelem) {<br>
>>    NumericVector result(x.size() + 1);<br>
>>    result[0] = firstelem;<br>
>>    std::memcpy(result.begin()+1, x.begin(), x.size()*sizeof(double));<br>
>>    return result;<br>
>> }<br>
>><br>
>><br>
>> Or a more general version concatenating vector of arbitrary lengths:<br>
>><br>
>><br>
>> // [[Rcpp::export]]<br>
>> NumericVector mybar4(NumericVector x, NumericVector y) {<br>
>>    NumericVector result(x.size() + y.size());<br>
>>    std::memcpy(result.begin(), x.begin(), x.size()*sizeof(double));<br>
>>    std::memcpy(result.begin()+x.size(), y.begin(), <br>
>> y.size()*sizeof(double));<br>
>>    return result;<br>
>> }<br>
>><br>
>><br>
>><br>
>>  > n=1E7<br>
>>  > testvec = c(1,seq_len(n))<br>
>>  > testelem <- 7<br>
>>  > microbenchmark(c(testelem, testvec), mybar(testvec,testelem),<br>
>> +   mybar2(testvec,testelem),<br>
>> +   mybar3(testvec,testelem),<br>
>> +   mybar4(testvec,testelem)<br>
>> +   )<br>
>> Unit: milliseconds<br>
>>                        expr       min        lq      mean    median   <br>
>> uq        max neval<br>
>>        c(testelem, testvec)  36.48577  36.93754  41.10550  43.76742 <br>
>> 44.20709  46.09741   100<br>
>>    mybar(testvec, testelem) 102.54042 103.21756 106.88749 104.32033 <br>
>> 110.31527 119.55512   100<br>
>>   mybar2(testvec, testelem)  95.64696  96.19447 100.24691 102.61380 <br>
>> 103.58189 109.28290   100<br>
>>   mybar3(testvec, testelem)  36.45794  36.87915  40.43486  37.18063 <br>
>> 43.49643  95.49049   100<br>
>>   mybar4(testvec, testelem)  36.51334  37.05409  41.39680  43.20627 <br>
>> 43.57958  94.95482   100<br>
>><br>
>><br>
>> Best,<br>
>> Jan<br>
>><br>
>><br>
>><br>
>> On 10-12-18 12:10, Serguei Sokol wrote:<br>
>>> Le 09/12/2018 à 09:35, Mark Leeds a écrit :<br>
>>>> Hi All: I wrote below and it works but I have a strong feeling <br>
>>>> there's a better way to do it.<br>
>>> If performance is an issue, you can save few percents of cpu time by <br>
>>> using std::copy() instead of explicit for loop. Yet, for this <br>
>>> operation R's c() remains the best bet. It is more then twice faster <br>
>>> than both Rcpp versions below:<br>
>>><br>
>>> #include <Rcpp.h><br>
>>> using namespace Rcpp;<br>
>>><br>
>>> // [[Rcpp::export]]<br>
>>> std::vector<double> mybar(const std::vector<double>& x, double <br>
>>> firstelem) {<br>
>>>    std::vector<double> tmp(x.size() + 1);<br>
>>>    tmp[0] = firstelem;<br>
>>>    for (int i = 1; i < (x.size()+1); i++)<br>
>>>      tmp[i] = x[i-1];<br>
>>>    return tmp;<br>
>>> }<br>
>>> // [[Rcpp::export]]<br>
>>> std::vector<double> mybar2(const std::vector<double>& x, double <br>
>>> firstelem) {<br>
>>>    std::vector<double> tmp(x.size() + 1);<br>
>>>    tmp[0] = firstelem;<br>
>>>    std::copy(x.begin(), x.end(), tmp.begin()+1);<br>
>>>    return tmp;<br>
>>> }<br>
>>><br>
>>> /*** R<br>
>>> library(microbenchmark)<br>
>>> n=100000<br>
>>> testvec = c(1,seq_len(n))<br>
>>> testelem <- 7<br>
>>> microbenchmark(c(testelem, testvec), mybar(testvec,testelem), <br>
>>> mybar2(testvec,testelem))<br>
>>> */<br>
>>><br>
>>> # Ouput<br>
>>> Unit: microseconds<br>
>>>                        expr     min       lq      mean   <br>
>>> median        uq<br>
>>>        c(testelem, testvec) 247.098 248.5655  444.8657 257.3300  <br>
>>> 630.7725<br>
>>>    mybar(testvec, testelem) 594.978 622.3560 1226.5683 637.0230 <br>
>>> 1386.8385<br>
>>>   mybar2(testvec, testelem) 576.191 604.7565 1029.2124 616.1055 <br>
>>> 1351.6740<br>
>>>         max neval<br>
>>>    7587.977   100<br>
>>>   22149.605   100<br>
>>>   11651.831   100<br>
>>><br>
>>><br>
>>> Best,<br>
>>> Serguei.<br>
>>><br>
>>>> I looked on the net and found some material from back in ~2014 about <br>
>>>> concatenating<br>
>>>> vectors but I didn't see anything final about it. Thanks for any <br>
>>>> insights.<br>
>>>><br>
>>>> Also, the documentation for Rcpp is beyond incredible (thanks to <br>
>>>> dirk, romain, kevin and all the other people I'm leaving out )  but <br>
>>>> is there a general methodology for finding equivalents of R <br>
>>>> functions. For example, if I want a cumsum function in Rcpp, how do <br>
>>>> I know whether to use the stl with accumulate or if there's already <br>
>>>> one built in so<br>
>>>> that I just call cumsum.<br>
>>>><br>
>>>> Thanks.<br>
>>>><br>
>>>> #=======================================================<br>
>>>><br>
>>>> #include <Rcpp.h><br>
>>>> using namespace Rcpp;<br>
>>>><br>
>>>> // [[Rcpp::export]]<br>
>>>> std::vector<double> mybar(const std::vector<double>& x, double <br>
>>>> firstelem) {<br>
>>>>    std::vector<double> tmp(x.size() + 1);<br>
>>>>    tmp[0] = firstelem;<br>
>>>>    for (int i = 1; i < (x.size()+1); i++)<br>
>>>>      tmp[i] = x[i-1];<br>
>>>>    return tmp;<br>
>>>> }<br>
>>>><br>
>>>> /*** R<br>
>>>><br>
>>>> testvec = c(1,2,3)<br>
>>>> testelem <- 7<br>
>>>> mybar(testvec,testelem)<br>
>>>><br>
>>>> */<br>
>>>><br>
>>>> #===============================<br>
>>>> # OUTPUT FROM RUNNING ABOVE<br>
>>>> #=================================<br>
>>>>  > testvec <-  c(1,2,3)<br>
>>>>  > testelem <- 7<br>
>>>>  > mybar(testvec,testelem)<br>
>>>> [1] 7 1 2 3<br>
>>>>  ><br>
>>>><br>
>>>><br>
>>>><br>
>>>><br>
>>>><br>
>>>><br>
>>>><br>
>>>> _______________________________________________<br>
>>>> Rcpp-devel mailing list<br>
>>>> <a href="mailto:Rcpp-devel@lists.r-forge.r-project.org" target="_blank">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" rel="noreferrer" target="_blank">https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel</a><br>
>>>><br>
>>><br>
>>> _______________________________________________<br>
>>> Rcpp-devel mailing list<br>
>>> <a href="mailto:Rcpp-devel@lists.r-forge.r-project.org" target="_blank">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" rel="noreferrer" target="_blank">https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel</a><br>
>> _______________________________________________<br>
>> Rcpp-devel mailing list<br>
>> <a href="mailto:Rcpp-devel@lists.r-forge.r-project.org" target="_blank">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" rel="noreferrer" target="_blank">https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel</a><br>
> <br>
<br>
_______________________________________________<br>
Rcpp-devel mailing list<br>
<a href="mailto:Rcpp-devel@lists.r-forge.r-project.org" target="_blank">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" rel="noreferrer" target="_blank">https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel</a></blockquote></div>