Ra Timing Tests
Here is a table of timing tests. (These are for older versions of Ra. For more recent results look here.)
TestName --TimeInSecs--- -------Time/R---------
R ra04-nojit ra04-nojit ra03 ra04
convolve 4.1 4.7 1.1 0.7 0.1
.TAOCP1997init from base/TAOCP.R 4.1 4.4 1.1 1.0 0.2
looped.dnorm 6.7 7.3 1.1 0.6 0.2
simple.count x <- x + 1 4.7 5.2 1.1 0.7 0.4
vadim1 x[i] = x[i-1] 3.4 3.9 1.1 1.2 0.1
vadim2 x[i-1] 5.0 5.6 1.1 0.7 0.3
vadim3 1 4.2 4.5 1.1 1.1 1.1
vadim4 x[i] = 1.0 4.7 5.1 1.1 1.2 0.1
vadim5 i-1 5.2 5.7 1.1 0.4 0.4
vadim6 i 4.4 5.3 1.2 1.2 1.2
For the specifics of each test see the code below.
The TimeInSecs column shows time in seconds for R 2.6.1 and ra04 without jitting.
The Time/R columns are the most interesting. They show the time taken by the Ra code divided by the R2.6.1 time. Successive runs give the same results give or take +-1 in the last digit.
- The ra04-nojit column shows the time taken by ra04 without jitting divided by the R2.6.1 time. The ra code without jitting is roughly 10 sometimes 20 percent slower than R. The slowdown is mainly caused by the numerous assertions in the ra code. The assertions will be removed in due course.
- The ra03 and ra04 columns show the time taken with jitting divided by the R2.6.1 time. The improvements of ra04 over ra03 are mainly due to jitting subscripted assignments.
The measurements were made with on a 3 Ghz Pentium D running Windows XP. In jit.c, DEBUG_JIT=1 and DEBUG_SYM=1.
The tests tend to show the jitter in a good light. This is because they make heavy use of arithmetic with vectors in loops, do not call C or Fortran routines, and use a high number of loop iterations. Drop me a line if there are other tests you would like to see.
Here is the code to generate the results above. This code was run for the various configurations in the table. The relative times were then calculated manually using the R2.6.1 time as a reference.
# time-jit.R
# # dummy function for testing with standard R
#
# jit <- function(jit=NA, trace=0)
# {
# if (length(grep(" ra\\-", R.version.string)) > 0)
# stop("Cannot redefine \"jit()\" when running ra")
# c(jit, trace, jit)
# }
jit.flag <- 0
trace.flag <- 0
quick = 0 # 0 for full test, 1 for quick test
gctorture(0)
test <- function(f, N)
{
strip.white.space <- function(s) gsub("[ \t\n]", "", s)
jit.flag <<- 1; trace.flag <<- 0; time.jit = system.time(a <- f(N))[1];
jit.flag <<- 0; trace.flag <<- 0; time.no.jit = system.time(b <- f(N))[1];
cat(sprintf("%-34.34s %5.2f %5.2f %8.0f %4.2f\n",
paste(substitute(f)), time.no.jit, time.jit, N, time.jit / time.no.jit))
stopifnot(identical(a, b))
}
convolve <- function(N) # from the extending R manual
{
jit(jit.flag, trace.flag)
a <- double(N)
b <- double(N)
na <- length(a)
nb <- length(b)
ab <- double(na + nb)
for(i in 1:na)
for(j in 1:nb)
ab[i + j] <- ab[i + j] + a[i] * b[j]
ab
}
# from base/TAOCP.R, a good test of integer arithmetic
.TAOCP1997init <- function(seed)
{
jit(jit.flag, trace.flag)
seed <- as.integer(seed) # added for jit to prevent type change error
KK <- 100L; LL <- 37L; MM <- as.integer(2^30)
KKK <- KK + KK - 1L; KKL <- KK - LL
ss <- seed - (seed %% 2L) + 2L
X <- integer(KKK)
for(j in 1L:KK) {
X[j] <- ss
ss <- ss+ss
if(ss >= MM) ss <- ss - MM + 2L
}
X[2L] <- X[2L] + 1L
ss <- seed
T <- 69L
while(T > 0) {
for(j in KK:2L) X[j + j - 1L] <- X[j]
for(j in seq(KKK, KKL + 1L, -2L))
X[KKK - j + 2L] <- X[j] - (X[j] %% 2L)
for(j in KKK:(KK+1L))
if(X[j] %% 2L == 1L) {
X[j - KKL] <- (X[j - KKL] - X[j]) %% MM
X[j - KK] <- (X[j - KK] - X[j]) %% MM
}
if(ss %% 2L == 1L) {
for(j in KK:1L) X[j + 1L] <- X[j]
X[1L] <- X[KK + 1L]
if(X[KK + 1L] %% 2L == 1L)
X[LL + 1L] <- (X[LL + 1L] - X[KK + 1L]) %% MM
}
if(ss) ss <- ss %/% 2L else T <- T - 1L
}
rs <- c(X[(LL+1L):KK], X[1L:LL])
invisible(rs)
}
`.TAOCP1997init from base/TAOCP.R` <- function(N)
{
for (i in 1:N)
.TAOCP1997init(N)
}
looped.dnorm <- function(N) # from one of Luke's compiler documents
{
jit(jit.flag, trace.flag)
mu <- 0
sigma <- 1
x <- 0
for (i in 1:N)
x <- x + (1/sqrt(2 * pi)) * exp(-0.5 * ((x - mu)/sigma)^2) / sigma
x
}
`simple.count x <- x + 1` <- function(N)
{
jit(jit.flag, trace.flag)
x <- 0
for(i in 1:N)
x <- x+1
}
# Tests from Vadim Ogranovich post.
# See http://tolstoy.newcastle.edu.au/R/devel/05/04/0678.html
# Expressions are the same as the Luke's email reply except
# that x and iA are local.
`vadim1 x[i] = x[i-1]` <- function(N)
{
jit(jit.flag, trace.flag)
iA = seq(2,N); x = double(N); x[1] = 1; x[2] = 2
for (i in iA)
x[i] = x[i-1]
x
}
`vadim2 x[i-1]` <- function(N)
{
jit(jit.flag, trace.flag)
iA = seq(2,N); x = double(N); x[1] = 1; x[2] = 2
for (i in iA)
x[i-1]
x
}
`vadim3 1` <- function(N)
{
jit(jit.flag, trace.flag)
iA = seq(2,N); x = double(N);
for (i in iA)
1
x
}
`vadim4 x[i] = 1.0` <- function(N)
{
jit(jit.flag, trace.flag)
iA = seq(2,N); x = double(N); x[1] = 1; x[2] = 2
for (i in iA)
x[i] = 1.0
x
}
`vadim5 i-1` <- function(N)
{
jit(jit.flag, trace.flag)
iA = seq(2,N);
for (i in iA)
i-1
i
}
`vadim6 i` <- function(N)
{
jit(jit.flag, trace.flag)
iA = seq(2,N);
for (i in iA)
i
i
}
cat("testname time jit-time N reltime\n\n")
test(convolve, if (quick) 300 else 600)
test(`.TAOCP1997init from base/TAOCP.R`, if (quick) 5 else 20)
test(looped.dnorm, if (quick) 1e5 else 5e5)
N = as.integer(if (quick) 2e6 else 1e7)
# we adjust N below so each test takes about the same time
test(`simple.count x <- x + 1`, as.integer(N/3))
test(`vadim1 x[i] = x[i-1]`, N/20)
test(`vadim2 x[i-1]`, N/4)
test(`vadim3 1`, N*1.5)
test(`vadim4 x[i] = 1.0`, N/10)
test(`vadim5 i-1`, N/2)
test(`vadim6 i`, N*1.5)
To Ra homepage