Jason Jason - 1 month ago 12
C++ Question

Getting gperftools to work with Rcpp

I've read related posts here and here, and looked at Dirk Eddelbuettel's talk here and yet I'm failing to even get a .log file from

gperftools
. Here is my
R
file, called
Rcpp_practice.R
:

library(Rcpp)

Sys.setenv("PKG_LIBS"="-lprofiler")
sourceCpp('eigen.cpp')

a <- matrix(rnorm(300^2), 300, 300)
getEigenValues(a)


Here are the contents of
eigen.cpp
:

#include <RcppArmadillo.h>
#include <gperftools/profiler.h>
// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
arma::vec getEigenValues(arma::mat M) {
return arma::eig_sym(M);
}


Then, on Terminal (I'm using OSX):

CPUPROFILE="eigenprof.log" R -f "Rcpp_practice.R"


I was hoping to see
eigenprof.log
sitting in my working directory but I don't. Also, I don't get the message that I've seen in other posts of the form
PROFILE: interrupts/evictions/bytes = 012/34/567891


I verified that I have the latest version of
gperftools
installed. (
$ brew upgrade google-perftools
gives
Error: gperftools 2.5 already installed
).

What am I missing?

Update

After I modified my code to match @nrussell's I get this error message:

Error in dyn.load("/private/var/folders/6k/ffcchdq52kbb7d631b5vsqcw0000gn/T/RtmpCIdHkG/sourceCpp-x86_64-apple-darwin13.4.0-0.12.7/sourcecpp_6c3253d60384/sourceCpp_2.so") :
unable to load shared object '/private/var/folders/6k/ffcchdq52kbb7d631b5vsqcw0000gn/T/RtmpCIdHkG/sourceCpp-x86_64-apple-darwin13.4.0-0.12.7/sourcecpp_6c3253d60384/sourceCpp_2.so':
dlopen(/private/var/folders/6k/ffcchdq52kbb7d631b5vsqcw0000gn/T/RtmpCIdHkG/sourceCpp-x86_64-apple-darwin13.4.0-0.12.7/sourcecpp_6c3253d60384/sourceCpp_2.so, 6): Symbol not found: _ProfilerStart
Referenced from: /private/var/folders/6k/ffcchdq52kbb7d631b5vsqcw0000gn/T/RtmpCIdHkG/sourceCpp-x86_64-apple-darwin13.4.0-0.12.7/sourcecpp_6c3253d60384/sourceCpp_2.so
Expected in: flat namespace
in /private/var/folders/6k/ffcchdq52kbb7d631b5vsqcw0000gn/T/RtmpCIdHkG/sourceCpp-x86_64-apple-darwin13.4.0-0.12.7/sourcecpp_6c3253d60384/sourceCpp_2.so
Calls: sourceCpp -> source -> withVisible -> eval -> eval -> dyn.load
Execution halted


This appears on the line with
sourceCpp
if I run the script interactively.

Answer

I don't have access to an OS X machine, but the following worked on Debian 8, where I've just added in the ProfilerStart / ProfilerStop calls to your C++ code (and not changed your R code at all):

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <gperftools/profiler.h>

// [[Rcpp::export]]
arma::vec getEigenValues(arma::mat M) {
    ProfilerStart("./eigen-prof.log");
    return arma::eig_sym(M);
    ProfilerStop();
}

Then from a terminal,

R -f eigen-prof.R > /dev/null && google-pprof --text $(which R) eigen-prof.log 

# PROFILE: interrupts/evictions/bytes = 2/0/264
# Using local file /usr/local/bin/R.
# Using local file eigen-prof.log.
# /usr/bin/addr2line: /usr/local/bin/R: File format not recognized
# Total: 2 samples
#        1  50.0%  50.0%        1  50.0% dlamch_
#        1  50.0% 100.0%        1  50.0% dsymv_
#        0   0.0% 100.0%        1  50.0% 00000000004007ca
#        0   0.0% 100.0%        1  50.0% 00000000004007fa
#        0   0.0% 100.0%        1  50.0% 00007f84002bf0bd
#        0   0.0% 100.0%        1  50.0% 00007f84002bf2a8
#        0   0.0% 100.0%        1  50.0% 00007f84002c14c8
#        0   0.0% 100.0%        1  50.0% R_ReplConsole
#        0   0.0% 100.0%        1  50.0% Rf_ReplIteration
#        0   0.0% 100.0%        1  50.0% Rf_applyClosure
#        0   0.0% 100.0%        1  50.0% Rf_eval
#        0   0.0% 100.0%        1  50.0% __libc_start_main
#        0   0.0% 100.0%        1  50.0% dlatrd_
#        0   0.0% 100.0%        1  50.0% do_dotcall
#        0   0.0% 100.0%        1  50.0% dsyev_
#        0   0.0% 100.0%        1  50.0% dsytrd_
#        0   0.0% 100.0%        1  50.0% frame_dummy
#        0   0.0% 100.0%        1  50.0% run_Rmainloop 

Regarding your updates, try changing the sourceCpp call to

sourceCpp(
    'eigen-prof.cpp',
    verbose = TRUE,
    rebuild = TRUE,
    cacheDir = "/tmp/profdir"
)

where I'm using cacheDir = "/tmp/profdir" to override the default random directory (tempdir()) that sourceCpp uses to build the shared library; and rebuild = TRUE to ensure that a new .so is generated each run.

Back in your shell, run these commands, substituting the appropriate file & directory names as needed:

  • R -f eigen-prof.R
  • so_file=$(find /tmp/profdir/ -iname '*.so' -printf "%T+\t%p\n" | sort -r | head -n1 | awk '{print $2}')
  • google-pprof --text $so_file eigen-prof.log

This gives me

# Using local file /tmp/profdir/sourceCpp-x86_64-pc-linux-gnu-0.12.7/sourcecpp_5dc5531d6f20/sourceCpp_4.so.
# Using local file eigen-prof.log.
# Total: 2 samples
#        1  50.0%  50.0%        1  50.0% dsterf_
#        1  50.0% 100.0%        1  50.0% dsymv_
#        0   0.0% 100.0%        2 100.0% 0x00000000004007ca
#        0   0.0% 100.0%        2 100.0% 0x00000000004007fa
#        0   0.0% 100.0%        2 100.0% R_ReplConsole
#        0   0.0% 100.0%        2 100.0% Rf_ReplIteration
#        0   0.0% 100.0%        2 100.0% Rf_applyClosure
#        0   0.0% 100.0%        2 100.0% Rf_eval
#        0   0.0% 100.0%        2 100.0% __libc_start_main
#        0   0.0% 100.0%        2 100.0% arma::auxlib::eig_sym
#        0   0.0% 100.0%        1  50.0% dlatrd_
#        0   0.0% 100.0%        2 100.0% do_dotcall
#        0   0.0% 100.0%        2 100.0% dsyev_
#        0   0.0% 100.0%        1  50.0% dsytrd_
#        0   0.0% 100.0%        2 100.0% eig_sym (inline)
#        0   0.0% 100.0%        2 100.0% getEigenValues
#        0   0.0% 100.0%        2 100.0% run_Rmainloop
#        0   0.0% 100.0%        2 100.0% sourceCpp_1_getEigenValues
#        0   0.0% 100.0%        2 100.0% syev (inline)

I threw the second step together on the fly so don't judge me on that; but it's just searching the directory you passed to cacheDir (/tmp/profdir in my case) for the most recently created (modified) .so file. You could also just grab the file name manually using Finder, etc. if your machine is lacking any of those programs.