In this document we look at some variations of the same piece of R code to see some of the strengths and weaknesses of the JIT compiler. The code is the "Distribution of a determinant" on page 154 in Venables and Ripley

"Consider the problem of finding the distribution of the determinant of a 2

The tests were made on a 3GHz Pentium G on a Windows XP system using R 2.6.2 and Ra 1.0.6. The times are in milliseconds. Smaller time ratios mean that Ra is faster. The standard deviation of each number in the table is less than 5%. The code to reproduce these timing results is here.Function RTime RaTime Ratio Notesms ms Ra/Rdd.for.c 240 230 0.96 original dd.for.c1 240 err err c() prevents compile dd.for.c2 240 201 0.84 nojit(val) dd.for.prealloc 132 10 0.08 preallocate val dd.for.tabulate 128 6 0.05 tabulate replaces table dd.fast.tabulate 1.47 1.43 0.97 no loops

dd.for.c <- function() { val <- NULL for (a in 0:9) for (b in 0:9) for (d in 0:9) for (e in 0:9) val <- c(val, a*b - d*e) table(val) }We enable just-in-time compilation by adding a

dd.for.c1 <- function() {but run into a problem. Under Ra, we get the error message:jit(1) # enable just-in-time compilationval <- NULL for (a in 0:9) for (b in 0:9) for (d in 0:9) for (e in 0:9) val <- c(val, a*b - d*e) table(val) }

Error: cannot change the length of a jitted variable Tried to change "val" from length 1 to length 2The problem is that the

dd.for.c2 <- function() { jit(1) val <- NULLThis function is about 20% faster under Ra. That's not much of an improvement. Thenojit(val) # inhibit compilation of valfor (a in 0:9) for (b in 0:9) for (d in 0:9) for (e in 0:9) val <- c(val, a*b - d*e) table(val) }

dd.for.prealloc <- function() { jit(1)The function is now faster under both R and Ra, but with Ra about 13 times faster than R because of JIT compilation.val <- double(10000) # preallocate valnval <- 0for (a in 0:9) for (b in 0:9) for (d in 0:9) for (e in 0:9)val[nval <- nval + 1] <- a*b - d*etable(val) }

dd.for.tabulate <- function() { jit(1) val <- double(10000) nval <- 0 for (a in 0:9) for (b in 0:9) for (d in 0:9) for (e in 0:9) val[nval <- nval + 1] <- a*b - d*eWith this, Ra runs about 21 times faster than R.tabulate(val) # was table()}

dd.fast.tabulate.jit <- function() { jit(1) val <- outer(0:9, 0:9, "*") val <- outer(val, val, "-") tabulate(val) }This solution is the fastest of all. The Ra time is about the same as the R time because there are no loops to optimize. The

"Vectorization" (i.e. getting rid of loops) usually gives you the fastest code.

The JIT compiler can give substantial performance improvements for looped arithmetic. It is useful when using loops is a natural or convenient expression of the problem, or when code cannot be vectorized.

See the Ra homepage for more information.