27

OS X (Mountain Lion 10.8.2) でいくつかの Rcpp コードをプロファイリングすることに興味がありますが、プロファイラーを実行するとクラッシュします。

inlineプロファイラが気付くのに十分な時間がかかるように設計された を使用したおもちゃの例。

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)

GUI インストゥルメント (Xcode、バージョン 4.5 (4523)) またはコマンド ラインのいずれかを使用するとsample、両方ともクラッシュします。インストゥルメントはすぐにクラッシュしますが、サンプルはクラッシュする前にサンプルの処理を完了します。

# (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

同じプロセスを C バージョン (つまりf.c(200000000L)) で実行すると、Instruments と両方とも正常に動作し、次sampleのような出力が生成されます。

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]

私が間違っていることがある場合、他の好ましい方法がある場合、またはこれが不可能な場合は、アドバイスをいただければ幸いです。Rcpp の主な用途の 1 つが R コードの高速化にあるように思われることを考えると、これに関する詳しい情報が見つからないことに驚いていますが、おそらく私は間違った場所を探しているのでしょう。

これは、OS X 10.8.2 で R 2.15.1 (x86_64-apple-darwin9.8.0)、Rcpp 0.9.15、および g++ --version レポート "i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2 .1 (Apple Inc. ビルド 5658 に基づく) (LLVM ビルド 2336.11.00)".

解決策

以下の Dirk の回答と、ここでの彼の講演http://dirk.eddelbuettel.com/papers/ismNov2009introHPCwithR.pdfのおかげで、Google perftools を使用して少なくとも部分的な解決策を得ることができました。まず、ここhttp://code.google.com/p/gperftools/からインストールし、C++ コードをコンパイルするときに PKG_LIBS に -lprofiler を追加します。その後、どちらか

(a) R を as としてCPUPROFILE=samples.log R実行し、すべてのコードを実行して終了する (または Rscript を使用する)

(b) 2 つの小さなユーティリティ関数を使用して、プロファイルのオン/オフを切り替えます。

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

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

次に、R内で次のことができます

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

どちらの方法でも、ファイルsamples.logにはプロファイリング情報が含まれます。これはで見ることができます

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

次のような出力を生成します

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

これはおそらく実際の例でより有益です。

4

1 に答える 1

4

私は混乱しています、あなたの例は不完全です:

  • cfunction()andの(些細な)呼び出しを表示しませんcxxfunction()

  • プロファイラーを呼び出す方法を示していません

  • C または C++ コードをプロファイリングしていない (!!)

質問を編集して、より明確にすることはできますか?

また、これを実行すると、2 つの例は本質的に同じであるため、同じ速度の結果が得られます。[ Rcpp では、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> 
于 2012-11-05T00:15:55.647 に答える