It is known that base R uses BLAS for calculation speedup. In my code I want to use those functions from base R and may be its packages that do use BLAS. How can I get the list of R functions which exactly use BLAS? Or how can I check whether the function I want to use in my code do use BLAS (ATLAS, LAPACK and so on)?
-
If you conduct your calculations by vectorized operations, I think you stand a pretty good chance of using BLAS routines. See [The R inferno, Chapter 3 "Failing To Vectorize"](http://www.burns-stat.com/pages/Tutor/R_inferno.pdf) and [the pile of SO questions regarding vectorization](https://stackoverflow.com/questions/tagged/vectorization+r) to find your specific problem. – akraf Nov 22 '17 at 19:25
1 Answers
This is not a complete answer, as I am no expert in this. But maybe you or someone else can take some of these starting ideas and create a solution from it (would be great if you could post that then!)
Inspect R's functions if they are defined in C
Only functions which call C code are suspects for using BLAS. So finding out these functions could be a first step.
capture.output(print( FUN ))
gives you the definition of a function as a string vector (one element per line) So to list all functions which are defined in terms of .Internal
, .Primitive
etc. do the following:
# Set this to the package you want to screen
envName <- 'base'
# Get the environment for the given name
env <- pos.to.env(which(search() == paste0('package:',envName)))
# Return TRUE if `string` contains `what`
contains <- function(string, what){
length(grep(what, string, fixed = TRUE)) != 0
}
# Build up a matrix which contains true if an element is defined in terms
# of the following functions which indicate calls to C code
signalWords <- c( '.Primitive', '.Internal', '.External'
, '.Call' , '.C' , '.Fortran' )
envElements <- ls(envir = env)
funTraits <- matrix(FALSE, nrow = length(envElements), ncol = length(signalWords),
dimnames = list(envElements, signalWords))
# Fill up the values of the matrix by reading each elements' definition
for (elementName in envElements){
element <- get(elementName, envir = env)
if(!is.function(element)){
next
}
fun.definition <- capture.output(print(element))
for(s in signalWords){
if(contains(fun.definition, s)){
funTraits[elementName, s] <- TRUE
}
}
}
When a function calls an external C function (as opposed to .Primitive
functions) , it looks like this:
dnorm
## function (x, mean = 0, sd = 1, log = FALSE)
## .External(C_dnorm, x, mean, sd, log)
## <bytecode: 0x1b1eebfc>
## <environment: namespace:stats>
Then hunt down the object which is called by .External
. It has the name of the corresponding C function. Use PACKAGE:::OBJECT$name
to find it:
stats:::C_dnorm$name
## [1] "dnorm"
See further: How can I view the source code for a function?, it also information about where to find source code for compiled functions, and How to see the source code of R .Internal or .Primitive function?
Finally, you'll have to somehow screen the C code and all the functions it calls for BLAS routines...
LD_PRELOAD something which logs if a BLAS function is called
You could develop a DLL which has BLAS's names but just logs its usage and from where it has been called before forwarding the call to the real BLAS routines... The LD_PRELOAD
UNIX environment variable can be used to load this library instead of BLAS. This only works if R was compiled to load BLAS as a dynamically linked library.
https://blog.netspi.com/function-hooking-part-i-hooking-shared-library-function-calls-in-linux/
See also: Why can R be linked to a shared BLAS later even if it was built with `--with-blas = lblas`?

- 2,965
- 20
- 44