Perfilando código Rcpp en OS X

Estoy interesado en perfilar algunos códigos Rcpp en OS X (Mountain Lion 10.8.2), pero el generador de perfiles se bloquea cuando se ejecuta.

Ejemplo de juguete, usandoinline, solo diseñado para tomarse el tiempo suficiente para que un perfilador lo note.

library(Rcpp)
library(inline)

src.cpp <- "
  RNGScope scope;
  int n = as<int>(n_);
  double x = 0.0;
  for ( int i = 0; i < n; i++ )
    x += (unif_rand()-.5);
  return wrap(x);"

src.c <- "
  int i, n = INTEGER(n_)[0];
  double x = 0.0;
  GetRNGstate();
  for ( i = 0; i < n; i++ )
    x += (unif_rand()-.5);
  PutRNGstate();
  return ScalarReal(x);"

f.cpp <- cxxfunction(signature(n_="integer"), src.cpp, plugin="Rcpp")
f.c <- cfunction(signature(n_="integer"), src.c)

Si utilizo los Instrumentos GUI (en Xcode, versión 4.5 (4523)) o la línea de comandossample, ambos fallan: los instrumentos fallan de inmediato, mientras que la muestra completa el procesamiento de las muestras antes de fallar:

# (in R)
set.seed(1)
f.cpp(200000000L)

# (in a separate terminal window)
~ » sample R  # this invokes the profiler
Sampling process 81337 for 10 seconds with 1 millisecond of run time between samples
Sampling completed, processing symbols...
[1]    81654 segmentation fault  sample 81337

Si hago el mismo proceso pero con la versión C (es decir,f.c(200000000L)) ambos instrumentos ysample trabajar bien y producir resultados como

Call graph:
1832 Thread_6890779   DispatchQueue_1: com.apple.main-thread  (serial)
  1832 start  (in R) + 52  [0x100000e74]
    1832 main  (in R) + 27  [0x100000eeb]
      1832 run_Rmainloop  (in libR.dylib) + 80  [0x1000e4020]
        1832 R_ReplConsole  (in libR.dylib) + 161  [0x1000e3b11]
          1832 Rf_ReplIteration  (in libR.dylib) + 514  [0x1000e3822]
            1832 Rf_eval  (in libR.dylib) + 1010  [0x1000aa402]
              1832 Rf_applyClosure  (in libR.dylib) + 849  [0x1000af5d1]
                1832 Rf_eval  (in libR.dylib) + 1672  [0x1000aa698]
                  1832 do_dotcall  (in libR.dylib) + 16315  [0x10007af3b]
                    1382 file1412f6e212474  (in file1412f6e212474.so) + 53  [0x1007fded5]  file1412f6e212474.cpp:16
                    + 862 unif_rand  (in libR.dylib) + 1127,1099,...  [0x10000b057,0x10000b03b,...]
                    + 520 fixup  (in libR.dylib) + 39,67,...  [0x10000aab7,0x10000aad3,...]
                    356 file1412f6e212474  (in file1412f6e212474.so) + 70,61,...  [0x1007fdee6,0x1007fdedd,...]  file1412f6e212474.cpp:16
                    56 unif_rand  (in libR.dylib) + 1133  [0x10000b05d]
                    38 DYLD-STUB$unif_rand  (in file1412f6e212474.so) + 0  [0x1007fdf1c]

Realmente apreciaría algún consejo sobre si hay algo que esté haciendo mal, si hay alguna otra forma preferida, o si esto no es posible. Dado que uno de los usos principales de Rcpp parece ser acelerar el código R, me sorprende no encontrar más información sobre esto, pero quizás estoy buscando en el lugar equivocado.

Esto está en OS X 10.8.2 con R 2.15.1 (x86_64-apple-darwin9.8.0), Rcpp 0.9.15, y g ++ --version informa "i686-apple-darwin11-llvm-g ++ - 4.2 (GCC) 4.2 .1 (basado en Apple Inc. compilación 5658) (LLVM compilación 2336.11.00) ".

Una solución

Gracias a la respuesta de Dirk a continuación, y su charla aquíhttp://dirk.eddelbuettel.com/papers/ismNov2009introHPCwithR.pdf, Tengo al menos una solución parcial usando Google perftools. Primero, instale desde aquíhttp://code.google.com/p/gperftools/y agregue -lprofiler a PKG_LIBS al compilar el código C ++. Entonces tambien

(a) Ejecutar R comoCPUPROFILE=samples.log R, ejecute todo el código y salga (o use Rscript)

(b) Use dos pequeñas funciones de utilidad para activar / desactivar la creación de perfiles:

RcppExport SEXP start_profiler(SEXP str) {
  ProfilerStart(as<const char*>(str));
  return R_NilValue;
}

RcppExport SEXP stop_profiler() {
  ProfilerStop();
  return R_NilValue;
}

Entonces, dentro de R puedes hacer

.Call("start_profiler", "samples.log")
# code that calls C++ code to be profiled
.Call("stop_profiler")

de cualquier manera, el archivosamples.log contendrá información de perfil. Esto se puede ver con

pprof --text /Library/Frameworks/R.framework/Resources/bin/exec/x86_64/R samples.log

que produce salida como

Using local file /Library/Frameworks/R.framework/Resources/bin/exec/x86_64/R.
Using local file samples.log.
Removing __sigtramp from all stack traces.
Total: 112 samples
  64  57.1%  57.1%       64  57.1% _unif_rand
  30  26.8%  83.9%       30  26.8% _process_system_Renviron
  14  12.5%  96.4%      101  90.2% _for_profile
   3   2.7%  99.1%        3   2.7% Rcpp::internal::expr_eval_methods
   1   0.9% 100.0%        1   0.9% _Rf_PrintValueRec
   0   0.0% 100.0%        1   0.9% 0x0000000102bbc1ff
   0   0.0% 100.0%       15  13.4% 0x00007fff5fbfe06f
   0   0.0% 100.0%        1   0.9% _Rf_InitFunctionHashing
   0   0.0% 100.0%        1   0.9% _Rf_PrintValueEnv
   0   0.0% 100.0%      112 100.0% _Rf_ReplIteration

lo que probablemente sería más informativo en un ejemplo real.

Respuestas a la pregunta(1)

Su respuesta a la pregunta