Gibbs sampler in Groovy
I recently read a couple of nice articles by Darren Wilkinson about implementing MCMC in various languages. The posts are here and here. Wilkinson apparently uses, or is considering using, Python for a lot of prototyping and C for a lot of his actual MCMC runs. However, since he feels that Java is in some ways nicer than C, and almost as fast, he has been using Java some also for the final MCMC runs. I thought I'd see how Groovy performed on this task.
A Groovy version of Wilkinson's Gibbs sampler is given here:
#!/usr/bin/env groovy
java.lang.Math.*
N=20000
thin=500
rngEngine= new DoubleMersenneTwister(new Date())
rngN= new Normal(0.0,1.0,rngEngine)
rngG= new Gamma(1.0,1.0,rngEngine)
x=y=0.0
println("Iter x y")
for(i in 1..N){
for(j in 1..thin){
x=rngG.nextDouble(3.0,y*y+4)
y=rngN.nextDouble(1.0/(x+1),1.0/sqrt(x+1))
}
println("$i $x $y")
}
You'd run it like:
./Gibbs.gv > data.tab
On a Macbook Pro 2.2 GHz Intel Core 2 Duo, comparing Wilkinson's Java (1.6.1) and Python (2.7.2) versions with my Groovy (1.8.0) version, I get the following times:
- java: 5.23 sec
- python: 1m49s
- groovy: 16.5s
Labels: Gibbs sampling, groovy, MCMC
Did you try compiling the Groovy to see what difference there was between the compile Java and compiled Groovy execution times?
There's also supposed to be some Java 7-related work which will speed up dynamic languages. I think there's some work that the dynamic languages will have to do to take advantage of it though. (July 25, 2011 at 5:43 PM) top
I have never seen compiling Groovy help much. I gave it a whirl here and, as usual, it didn't make any noticeable difference. I think for processes that run more than a few seconds, JIT compiling pretty much smooths out any differences there would be. I do compile lots of Groovy code, to call it from Java, but I gave up on that as a way to improve performance.
Groovy++ really does have a big performance gain, but you lose a lot of Groovy goodness in the process. It might be useful in this case, though... maybe I'll give it a try and update the post. (July 25, 2011 at 9:23 PM) top
Actually, I tried Groovy++ on this example and it only had a small impact, maybe 10%. I've seen examples where the improvement was large. (July 27, 2011 at 2:00 PM) top
Hold on... I'm going to try something:
The probability of getting \(k\) heads when flipping \(n\) coins is
\[P(E) = {n \choose k} p^k (1-p)^{ n-k}\] (July 29, 2011 at 11:23 PM) top