0

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)?

Omega1x
  • 39
  • 4
  • 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 Answers1

0

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`?

akraf
  • 2,965
  • 20
  • 44