Reputation: 13
I'm trying to speed up my R code - I'm wondering if this is something that can be done in Rcpp. This is my code that I started to write.
library(Rcpp)
cppFunction('int cont.run_C(int reps=10000,int n=10000,int d=0.005,int l=10 ,int s=0.1) {
r = rep(0, reps)
theta = rep(0, n)
for(int t = 0; t < reps; t++) {
epsilon = rnorm(1, 0, d)
Zt = sum(epsilon > theta ? 1 : epsilon < -theta ? -1: 0)
r[t] = Zt / (l * n)
theta = runif(n) < s ? abs(r[t]) : theta
}
return mean(r)
}')
system.time(cont.run_C())
Upvotes: 1
Views: 101
Reputation: 26823
Before trying to translate your code to C++ it makes sense to look at the R code first, especially if you do not know C++. If you use a profiler on your code, you will see that much of the time is spent in the two lines with ifelse
. However, both lines can be improved. The first line is equivalent to:
Zt <- sum(epsilon > theta) - sum(epsilon < -theta)
The second line can be written as
theta[runif(n) < s] <- abs(r[t])
These two changes reduce the runtime on my system from over 10s to under 5s. Looking at the profiler results again, we see that now most of the time is spent in runif
. Here we can use a faster RNG from my dqrng package, reducing the runtime to under 2s. Final code:
library(dqrng)
cont.run <- function(reps=10000, n=10000, d=0.005, l=10 ,s=0.1) {
r <- rep(0, reps)
theta <- rep(0, n)
for (t in 1:reps) {
epsilon <- dqrnorm(1, 0, d)
#Zt = sum(ifelse(epsilon > theta, 1, ifelse(epsilon < -theta, -1, 0)))
Zt <- sum(epsilon > theta) - sum(epsilon < -theta)
r[t] <- Zt / (l * n)
theta[dqrunif(n) < s] <- abs(r[t])
}
return(mean(r))
}
system.time(cont.run())
#> User System verstrichen
#> 1.804 0.244 2.049
Created on 2019-05-21 by the reprex package (v0.2.1)
Upvotes: 3