[Rcpp-devel] calling R function triggers tryCatch() ???
Romain Francois
romain at r-enthusiasts.com
Fri Oct 11 17:04:03 CEST 2013
I will give some concretes next week. For now, i just wanted to hint:
- mean is a mammoth. Try applying mean_ :
mean_ <- function(.) .Internal(mean(.))
- by using x(r,_) you are allocating memory at each loop iteration, when we can use just one vector, since all rows are by definition of the same size.
I will contribute code versions of these hints later.
Romain
Le 11 oct. 2013 à 16:27, Hadley Wickham <h.wickham at gmail.com> a écrit :
> Interestingly, that shows that rowApply2 is actually slightly _slower_
> than rowApply1.
>
> Hadley
>
> On Fri, Oct 11, 2013 at 9:24 AM, Hadley Wickham <h.wickham at gmail.com> wrote:
>> FYI, I recommend using microbenchmark which uses a much higher
>> precision timer so you can see the variability as well as the mean
>> times. Also note that you can use /*** R */ to include R code that's
>> automatically run when benchmarking:
>> https://gist.github.com/hadley/6935459
>>
>> That gives:
>>
>>> microbenchmark(rowMeans(M),
>> + apply(M, 1L, mean),
>> + rowApply0(M, mean),
>> + rowApply1(M, mean),
>> + rowApply2(M, mean))
>> Unit: microseconds
>> expr min lq median uq max neval
>> rowMeans(M) 5.31 7.11 7.54 7.84 13.9 100
>> apply(M, 1L, mean) 46.23 49.46 50.78 53.06 136.9 100
>> rowApply0(M, mean) 50.87 53.81 55.36 57.54 85.3 100
>> rowApply1(M, mean) 18.92 20.14 21.20 22.44 36.9 100
>> rowApply2(M, mean) 18.73 20.18 21.27 22.40 34.0 100
>>
>>> M <- matrix(rnorm(1500L), nrow=30L);
>>
>>> microbenchmark(rowMeans(M),
>> + apply(M, 1L, mean),
>> + rowApply0(M, mean),
>> + rowApply1(M, mean),
>> + rowApply2(M, mean))
>> Unit: microseconds
>> expr min lq median uq max neval
>> rowMeans(M) 9.86 12 13 14.1 21.9 100
>> apply(M, 1L, mean) 265.28 288 308 349.8 475.2 100
>> rowApply0(M, mean) 506.54 541 575 604.9 5469.3 100
>> rowApply1(M, mean) 174.37 185 206 232.4 334.0 100
>> rowApply2(M, mean) 171.55 183 223 245.8 4244.7 100
>>
>> On Fri, Oct 4, 2013 at 11:36 AM, Thomas Tse <tommy_228_228 at yahoo.com.hk> wrote:
>>> The next test compares the speeds:
>>>
>>> // [[Rcpp::export]]
>>> NumericVector rowApply0(NumericMatrix& x, const Function& FUN)
>>> {
>>> int n = x.nrow();
>>> NumericVector result = no_init(n);
>>>
>>> for (int r = 0; r < n; r++) {
>>> result[r] = as<double>(FUN(x(r, _) ) );
>>> }
>>> return result;
>>> }
>>>
>>> // [[Rcpp::export]]
>>> NumericVector rowApply1(NumericMatrix& x, const Function& FUN)
>>> {
>>> int n = x.nrow();
>>> NumericVector result = no_init(n);
>>>
>>> for (int r = 0; r < n; r++) {
>>> Language call(FUN, x(r, _)) ;
>>> result[r] = as<double>(call.fast_eval() );
>>> }
>>> return result;
>>> }
>>>
>>> // [[Rcpp::export]]
>>> NumericVector rowApply2(NumericMatrix& x, const Function& FUN)
>>> {
>>> int n = x.nrow();
>>> NumericVector result = no_init(n);
>>>
>>> Language call(FUN, R_NilValue);
>>> Language::Proxy proxy(call, 1);
>>> for (int r = 0; r < n; r++) {
>>> proxy = x(r, _) ;
>>> result[r] = as<double>(call.fast_eval() );
>>> }
>>> return result;
>>> }
>>>
>>>> M <- matrix(rnorm(15L), nrow=3L);
>>>> identical(rowMeans(M), apply(M, 1L, mean));
>>> [1] TRUE
>>>> identical(rowMeans(M), rowApply0(M, mean));
>>> [1] TRUE
>>>> identical(rowMeans(M), rowApply1(M, mean));
>>> [1] TRUE
>>>> identical(rowMeans(M), rowApply2(M, mean));
>>> [1] TRUE
>>>> benchmark(rowMeans(M),
>>> + apply(M, 1L, mean),
>>> + rowApply0(M, mean),
>>> + rowApply1(M, mean),
>>> + rowApply2(M, mean),
>>> + replications=300000L);
>>> test replications elapsed relative user.self sys.self
>>> user.child sys.child
>>> 3 rowApply0(M, mean) 300000 23.26 8.551 23.14 0
>>> NA NA
>>> 2 apply(M, 1, mean) 300000 21.30 7.831 21.13 0
>>> NA NA
>>> 4 rowApply1(M, mean) 300000 10.23 3.761 10.22 0
>>> NA NA
>>> 5 rowApply2(M, mean) 300000 9.87 3.629 9.82 0
>>> NA NA
>>> 1 rowMeans(M) 300000 2.72 1.000 2.72 0
>>> NA NA
>>>
>>>> M <- matrix(rnorm(1500L), nrow=30L);
>>>> benchmark(rowMeans(M),
>>> + apply(M, 1L, mean),
>>> + rowApply0(M, mean),
>>> + rowApply1(M, mean),
>>> + rowApply2(M, mean),
>>> + replications=30000L);
>>> test replications elapsed relative user.self sys.self
>>> user.child sys.child
>>> 3 rowApply0(M, mean) 30000 21.32 48.455 21.30 0
>>> NA NA
>>> 2 apply(M, 1, mean) 30000 11.17 25.386 11.17 0
>>> NA NA
>>> 4 rowApply1(M, mean) 30000 8.24 18.727 8.19 0
>>> NA NA
>>> 5 rowApply2(M, mean) 30000 8.10 18.409 8.08 0
>>> NA NA
>>> 1 rowMeans(M) 30000 0.44 1.000 0.43 0
>>> NA NA
>>>
>>>> M <- matrix(rnorm(150000L), nrow=300L);
>>>> benchmark(rowMeans(M),
>>> + apply(M, 1L, mean),
>>> + rowApply0(M, mean),
>>> + rowApply1(M, mean),
>>> + rowApply2(M, mean),
>>> + replications=3000L);
>>> test replications elapsed relative user.self sys.self
>>> user.child sys.child
>>> 3 rowApply0(M, mean) 3000 26.65 18.379 26.41 0.01
>>> NA NA
>>> 2 apply(M, 1, mean) 3000 19.76 13.628 19.71 0.00
>>> NA NA
>>> 4 rowApply1(M, mean) 3000 12.79 8.821 12.78 0.00
>>> NA NA
>>> 5 rowApply2(M, mean) 3000 12.69 8.752 12.68 0.00
>>> NA NA
>>> 1 rowMeans(M) 3000 1.45 1.000 1.45 0.00
>>> NA NA
>>>
>>> again, as Romain suggested, implementation rowApply2 is faster than
>>> rowApply1, and rowApply0 (which triggers tryCatch) is even slower than R's
>>> apply.
>>>
>>> Thanks Romain !
>>>
>>>
>>> _______________________________________________
>>> Rcpp-devel mailing list
>>> Rcpp-devel at lists.r-forge.r-project.org
>>> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
>>
>>
>>
>> --
>> Chief Scientist, RStudio
>> http://had.co.nz/
>
>
>
> --
> Chief Scientist, RStudio
> http://had.co.nz/
> _______________________________________________
> Rcpp-devel mailing list
> Rcpp-devel at lists.r-forge.r-project.org
> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
More information about the Rcpp-devel
mailing list