para - r studio for mac
Perfil de código Rcpp en OS X (1)
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, uso en inline
, solo diseñado para tomar 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 sample
línea de comandos, ambos fallan: los instrumentos fallan de inmediato, mientras que la muestra completa el procesamiento de 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, fc(200000000L)
), tanto los instrumentos como la sample
funcionan bien y producen 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 agradecerí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 utilizando Google perftools. Primero, instale desde aquí http://code.google.com/p/gperftools/ , y agregue -lprofiler a PKG_LIBS cuando compile el código C ++. Entonces tambien
(a) Ejecute R como CPUPROFILE=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 archivo samples.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.
Estoy confundido, tu ejemplo es incompleto:
no muestra la invocación (trivial) de
cfunction()
ycxxfunction()
No muestras cómo invocas el perfilador.
no estás perfilando el código C o C ++ (!!)
¿Puede tal vez editar la pregunta y aclararla?
Además, cuando ejecuto esto, los dos ejemplos dan resultados de velocidad idénticos, ya que son esencialmente idénticos. [Rcpp le permitiría hacer esto en llamadas con funciones de números aleatorios de Sugars. ]
R> library(Rcpp)
R> library(inline)
R>
R> 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);"
R>
R> 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 Rf_ScalarReal(x);"
R>
R> fc <- cfunction(signature(n_="int"), body=src.c)
R> fcpp <- cxxfunction(signature(n_="int"), body=src.c, plugin="Rcpp")
R>
R> library(rbenchmark)
R>
R> print(benchmark(fc(10000L), fcpp(10000L)))
test replications elapsed relative user.self sys.self user.child sys.child
1 fc(10000) 100 0.013 1 0.012 0 0 0
2 fcpp(10000) 100 0.013 1 0.012 0 0 0
R>