r - %dopar% or alternative method to speed up sequential stochastic calculation -
i have written stochastic process simulator speed since it's pretty slow.
the main part of simulator made of for
loop re-write foreach
`%dopar%.
i have tried doing simplified loop i'm running problems. suppose for
loop looks
library(foreach) r=0 t<-rep(0,500) for(n in 1:500){ s<-1/2+r u<-runif(1, min = 0, max = 1) if(u<s){ t[n]<-u r<-r+0.001 }else{r<-r-0.001} }
which means @ each iteration update value of r
, s
and, in 1 of 2 outcomes, populate vector t
. have tried several different ways of re-writing foreach
loop seems each iteration values don't updated , pretty strange results. have tried using return
doesn't seem work!
this example of have come with.
rr=0 tt<-foreach(i=1:500, .combine=c) %dopar% { ss<-1/2+rr uu<-runif(1, min = 0, max = 1) if(uu<=ss){ return(uu) rr<-rr+0.001 }else{ return(0) rr<-rr-0.001} }
if impossible use foreach
other way there me re-write loop able use cores , speed things?
since comments, turning c, encouraging , -mostly- prove isn't hard task (especially such operations) , it's worth looking into, here comparison of 2 sample functions accept number of iterations , perform steps of loop:
ffr = function(n) { r = 0 t = rep(0, n) for(i in 1:n) { s = 1/2 + r u = runif(1) if(u < s) { t[i] = u r = r + 0.001 } else r = r - 0.001 } return(t) } ffc = inline::cfunction(sig = c(r_n = "integer"), body = ' int n = integer(as_integer(r_n))[0]; sexp ans; protect(ans = allocvector(realsxp, n)); double r = 0.0, s, u, *pans = real(ans); getrngstate(); for(int = 0; < n; i++) { s = 0.5 + r; u = runif(0.0, 1.0); if(u < s) { pans[i] = u; r += 0.001; } else { pans[i] = 0.0; r -= 0.001; } } putrngstate(); unprotect(1); return(ans); ', includes = "#include <rmath.h>")
a comparison of results:
set.seed(007); ffr(5) #[1] 0.00000000 0.39774545 0.11569778 0.06974868 0.24374939 set.seed(007); ffc(5) #[1] 0.00000000 0.39774545 0.11569778 0.06974868 0.24374939
a comparison of speed:
microbenchmark::microbenchmark(ffr(1e5), ffc(1e5), times = 20) #unit: milliseconds # expr min lq median uq max neval # ffr(1e+05) 497.524808 519.692781 537.427332 668.875402 692.598785 20 # ffc(1e+05) 2.916289 3.019473 3.133967 3.445257 4.076541 20
and sake of completeness:
set.seed(101); ans1 = ffr(1e5) set.seed(101); ans2 = ffc(1e5) all.equal(ans1, ans2) #[1] true
hope of helpful in way.
Comments
Post a Comment