2012-11-05 34 views
19

Tôi quan tâm đến việc lập hồ sơ một số mã Rcpp trong OS X (Mountain Lion 10.8.2), nhưng profiler bị treo khi đang chạy.Tạo mã Rcpp trên OS X

Ví dụ về đồ chơi, sử dụng inline, chỉ được thiết kế để có đủ thời gian cho trình thông báo nhận dạng.

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) 

Nếu tôi sử dụng một trong hai cụ GUI (trong Xcode, phiên bản 4.5 (4523)) hoặc dòng lệnh sample, cả hai vụ tai nạn: Dụng cụ treo ngay lập tức, trong khi mẫu hoàn thành mẫu xử lý trước khi đâm:

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

Nếu tôi làm quá trình tương tự nhưng với phiên bản C (ví dụ, f.c(200000000L)) cả Instruments và sample làm việc tốt, và sản xuất sản lượng như

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] 

Tôi thực sự đánh giá cao một số lời khuyên nếu có bất cứ điều gì tôi làm sai, nếu có một số cách ưa thích khác, hoặc nếu điều này là không thể. Cho rằng một trong những cách sử dụng chính của Rcpp dường như đang tăng tốc mã R, tôi ngạc nhiên khi không tìm thêm thông tin về điều này, nhưng có lẽ tôi đang tìm kiếm sai chỗ.

Đây là trên OS X 10.8.2 với R 2.15.1 (x86_64-apple-darwin9.8.0), Rcpp 0.9.15 và báo cáo chuyển đổi g ++ - "i686-apple-darwin11-llvm-g ++ - 4.2 (GCC) 4.2.1 (Dựa trên Apple Inc. xây dựng 5658) (LLVM build 2336.11.00) ".

Một giải pháp

Nhờ câu trả lời Dirk của dưới đây, và nói chuyện của mình ở đây http://dirk.eddelbuettel.com/papers/ismNov2009introHPCwithR.pdf, tôi có ít nhất một giải pháp phần sử dụng perftools Google. Trước tiên, hãy cài đặt từ đây http://code.google.com/p/gperftools/ và thêm -lprofiler vào PKG_LIBS khi biên dịch mã C++. Sau đó, một trong hai

(a) Chạy R như CPUPROFILE=samples.log R, chạy tất cả các mã và bỏ (hoặc sử dụng Rscript)

(b) Sử dụng hai chức năng tiện ích nhỏ để bật/tắt hồ sơ:

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

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

sau đó, trong R bạn có thể làm

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

một trong hai cách, các tập tin samples.log sẽ chứa profiling thông tin. Điều này có thể được xem xét với

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

trong đó sản xuất ra như

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 

mà có lẽ sẽ được nhiều thông tin thêm về một ví dụ thực tế.

+1

+1 - perftools, profiler gcc hoặc valgrind đều có thể hữu ích. Thực tế R là tương tác không ném cờ lê ở đây vì nó thêm nhiều lớp mã hơn. –

+0

Tôi chạy vào bản thân mình khi tôi nâng cấp XCode của tôi, nhưng tôi nghĩ rằng nó có thể chỉ là tôi. Vấn đề là Shark đã làm việc hoàn hảo để lược tả Rcpp trước đây, nhưng bây giờ nó đã không còn tồn tại. Tôi đoán chúng ta có thể gọi đây là lỗi của Apple. –

Trả lời

4

Tôi bối rối, ví dụ của bạn là không đầy đủ:

  • bạn không hiển thị (tầm thường) gọi của cfunction()cxxfunction()

  • bạn không thấy cách bạn gọi profiler

  • bạn không profiling C hoặc C++ (!!)

Bạn có thể chỉnh sửa câu hỏi và làm cho câu hỏi rõ ràng hơn không?

Ngoài ra, khi tôi chạy điều này, hai ví dụ cho kết quả tốc độ giống hệt nhau vì chúng cơ bản giống nhau. [Rcpp sẽ cho phép bạn thực hiện cuộc gọi này với các hàm số đường ngẫu nhiên. ]

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> 
+0

Xin chào Dirk, và cảm ơn bạn đã giúp đỡ! Tôi đã chỉnh sửa ví dụ trên để rõ ràng, tôi hy vọng. Trình lược tả được gọi với lệnh 'mẫu', và tôi đã bao gồm đầu ra từ phiên bản C để cho thấy rằng đó là C đang được lược tả. Tôi đã sử dụng cách tiếp cận chung này thành công với mã R + C trước đây, nhưng không phải với C++. Các ví dụ sẽ cho kết quả giống nhau và không đại diện cho vấn đề tôi thực sự đang cố gắng để hồ sơ. Cảm ơn một lần nữa, Rich – Rich

+1

Tôi thấy bây giờ - Tôi không biết gì về khía cạnh OS X của điều này. Đối với thẳng lên 'gcc' et al, tôi đặt một số ghi chú về lược tả vào 'Giới thiệu với HPC với R' trượt trên trang web của tôi/từ các cuộc đàm phán trước đó. Bạn sẽ cần phải xem với r-sig-mac liệu 'sample' có hoạt động trên chuỗi công cụ R hay không. –