I'm doing a rejection sampling on R that needs to be as efficient as possible. Here is my raw code :
N <- 1e8
x <- rexp(N, 3) + rexp(N, 3)
todo <- runif(N, -1, 1) < cos(3.2*pi*x)
while(any(todo)){
x[todo] <- rexp(sum(todo), 3) + rexp(sum(todo), 3)
todo[todo] <- runif(sum(todo), -1, 1) < cos(3.2*pi*x[todo])
}
I was reading about copy-and-modify on https://adv-r.hadley.nz/names-values.html, and decided to use the lobstr package to find if there was any object concerned (with the tracemem()
function), and lo-and-behold, the logical vector todo
keeps getting copied in the while loop !
If I do the following test :
library(lobstr)
N <- 1e8
x <- rexp(N, 3) + rexp(N, 3)
todo <- runif(N, -1, 1) < cos(3.2*pi*x)
cat(tracemem(todo), "\n")
while(any(todo)){
x[todo] <- rexp(sum(todo), 3) + rexp(sum(todo), 3)
todo[todo] <- runif(sum(todo), -1, 1) < cos(3.2*pi*x[todo])
}
I get the following result (confirming my worries) :
[1] "0x38f4938"
[1] "0x1959ff30"
[1] "0x38f4938"
[1] "0x173bb6f0"
[1] "0x38f4938"
[1] "0x4caf788"
[1] "0x38f4938"
[1] "0x1a801628"
[1] "0x38f4938"
[1] "0x18f36768"
[1] "0x38f4938"
[1] "0x4e4d478"
[1] "0x38f4938"
[1] "0x195b93d8"
[1] "0x38f4938"
[1] "0x3f59fe0"
[1] "0x38f4938"
[1] "0x45ebf40"
[1] "0x38f4938"
[1] "0x1a42bdd8"
[1] "0x38f4938"
[1] "0x16c72ba0"
Can someone please help me get rid of this time-consuming behavior ? I tried, without success, the following declarations :
todo <- logical(N)
todo <- list(logical(N))
Edit : also, any help with improving the time efficiency of this bottleneck in my code will be very much appreciated...