New patches to speed up R 2.13.0
I have now released a new collection of 30 patches to speed up R version 2.13.0. You can get them here
Assessing how much these patches speed up R is difficult. First of all, the speedup varies tremendously with the type of program. It also varies quite a bit with the machine and compiler used to run R. Finally, it varies in apparently random ways — changing code in one part of the R interpreter can change the speed of operations that never use the modified code by plus or minus 5% or more. This is presumably due to the change altering the exact addresses of other code segments, with consequent effects on alignment of memory fetches or on cache behaviour.
Nevertheless, here is a comparison of R 2.13.0 without modification and with all my patches applied, with and without compilation of R functions. The tests were done with an Intel X5680 processor running at 3.33GHz in 64-bit mode using gcc 4.4.4 under Red Hat Linux with default R configuration parameters. The tests use my suite of speed tests for R.
Here are some highlights:
- For programs dominated by general interpretive overhead, such as the first test listed (“em”), there is a speedup by a factor of up to about 1.5. If these programs are compiled with the R bytecode compiler, the speedup is less, but not negligible (up to a factor of about 1.1).
- Vector and matrix subscripting is substantially faster, for both interpreted and compiled programs. The speedup is mostly when extracting subsets (for instance, r <- v[100:200]), with only a small improvement when replacing a subset (for instance, v[100:200]<-r). Here are some examples:
- Operations such as A[100:200,300:400] are sped up by a factor of about 3.4.
- Operations such as A[100:200,10] are sped up by a factor of about 1.8.
- Operations such as A[,10:11], with A having 300 rows, are sped up by a factor of about 4.3.
- Accessing a single element of a logical or complex vector is sped up by a factor of about 1.7.
- Accessing a fairly big range of elements in a vector (eg, a[1:100]) is sped up by a factor of about 1.6.
- Forming a vector with one element deleted (for example, a[-100], with a being of length 1000) is sped up by a factor of about 5.5.
- The interpreter now sometimes avoids creating a sequence of integers when it is just used as a subscript or in a for statement. This is partly responsible for the speedups detailed above for subscripting operations such as a[1:100]. A for statement such as for (i in 1:1000000) will now not actually create a vector of length 1000000, but just behave as if it had.
- Vector dot products (done with %*%) are sped up by a factor of 10 for long vectors. Matrix times vector and vector times matrix products with the vector being of length 1000 are sped up factors ranging from 3.2 to 5.5. General matrix-matrix products are sped up substantially as long as at least one dimension of the result matrix is not large. For discussion of the issues involved here, see my previous post.
- Accessing an element of a list by name with the $ operator is sped up by a factor of about 1.5.
- Argument matching when a function is called has been sped up. The speedup for this operation alone isn’t too clear from the tests, but is probably a factor of 1.3 or more. Somewhat as a by-product of this patch, some primitive operations such as rep have also been sped up (they had used an inefficient kludge for their argument matching). For instance, rep(1,length=100) is sped up by a factor of 1.5.
I’ll now switch to working on other projects for a while, but I plan to get back to R work in August. In the meantime, I will be posting a bit more on what some of these patches are doing. I’m also interested, of course, in hearing of any problems that people may have installing the patches, in any bugs that they find, and in reports of how much effect the patches have on the speed of real programs.
Note to commenters: Remember that “<” must be entered as “<”, and “&” must be entered as “&”. Unfortunately, there’s nothing I can do to fix things if you post a comment with a “<” that gets interpreted as indicating the start of an HTML tag!