Получение gperftools для работы с Rcpp

Я прочитал связанные сообщения здесь и здесь и посмотрел выступление Дирка Эддельбюттеля здесь, но мне даже не удается получить файл .log от gperftools. Вот мой файл R под названием Rcpp_practice.R:

library(Rcpp)

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

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

Вот содержимое 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);
}

Затем в Терминале (я использую OSX):

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

Я надеялся увидеть eigenprof.log в моем рабочем каталоге, но этого не произошло. Кроме того, я не получаю сообщение, которое я видел в других сообщениях формы PROFILE: interrupts/evictions/bytes = 012/34/567891

Я убедился, что у меня установлена ​​последняя версия gperftools. ($ brew upgrade google-perftools дает Error: gperftools 2.5 already installed).

Что мне не хватает?

Обновить

После того, как я изменил свой код, чтобы он соответствовал коду @nrussell, я получаю это сообщение об ошибке:

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

Это появляется в строке с sourceCpp, если я запускаю скрипт в интерактивном режиме.


person Jason    schedule 18.10.2016    source источник
comment
Вы показываете только частичные команды. Это наверняка работало много лун назад и должно работать до сих пор. Что бы я сделал, так это проследить от минимального main() в файле С++, убедиться, что у меня есть все флаги и параметры компиляции и компоновки, а затем перенести это в сборку на основе Rcpp.   -  person Dirk Eddelbuettel    schedule 19.10.2016


Ответы (2)


У меня нет доступа к машине OS X, но в Debian 8 работало следующее, где я только что добавил вызовы ProfilerStart/ProfilerStop в ваш код C++ (и вообще не изменил код R¹):

// [[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();
}

¹См. обновление ниже.


Затем с терминала

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 

Что касается ваших обновлений, попробуйте изменить вызов sourceCpp на

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

где я использую cacheDir = "/tmp/profdir" для переопределения случайного каталога по умолчанию (tempdir()), который sourceCpp использует для создания общей библиотеки; и rebuild = TRUE, чтобы обеспечить создание нового .so при каждом запуске.

Вернувшись в свою оболочку, запустите эти команды, заменив соответствующие имена файлов и каталогов по мере необходимости:

  • 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

Это дает мне

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

Второй шаг я сделал на лету, так что не судите меня за это; но это просто поиск в каталоге, который вы передали cacheDir (в моем случае /tmp/profdir), для самого последнего созданного (измененного) файла .so. Вы также можете просто взять имя файла вручную с помощью Finder и т. д., если на вашем компьютере отсутствуют какие-либо из этих программ.

person nrussell    schedule 18.10.2016
comment
Эта штука подключена? - person nrussell; 19.10.2016
comment
comment
Это, по крайней мере, приводит меня к новой ошибке. Он огромный, но начинается с Error in dyn.load и включает в себя unable to load shared object '/a/long/path/sourceCpp_2.so, а также Expected in: flat namespace. - person Jason; 19.10.2016

В OS X я вижу ту же ошибку при наивной попытке скомпилировать код:

> Rcpp::sourceCpp('scratch/prof.cpp')
Error in dyn.load("/private/var/folders/tm/5dt8p5s50x58br1k6wpqnwx00000gn/T/RtmpgOwFk7/sourceCpp-x86_64-apple-darwin13.4.0-0.12.7.1/sourcecpp_9f424793a11/sourceCpp_2.so") : 
  unable to load shared object '/private/var/folders/tm/5dt8p5s50x58br1k6wpqnwx00000gn/T/RtmpgOwFk7/sourceCpp-x86_64-apple-darwin13.4.0-0.12.7.1/sourcecpp_9f424793a11/sourceCpp_2.so':
  dlopen(/private/var/folders/tm/5dt8p5s50x58br1k6wpqnwx00000gn/T/RtmpgOwFk7/sourceCpp-x86_64-apple-darwin13.4.0-0.12.7.1/sourcecpp_9f424793a11/sourceCpp_2.so, 6): Symbol not found: _ProfilerStart
  Referenced from: /private/var/folders/tm/5dt8p5s50x58br1k6wpqnwx00000gn/T/RtmpgOwFk7/sourceCpp-x86_64-apple-darwin13.4.0-0.12.7.1/sourcecpp_9f424793a11/sourceCpp_2.so
  Expected in: flat namespace
 in /private/var/folders/tm/5dt8p5s50x58br1k6wpqnwx00000gn/T/RtmpgOwFk7/sourceCpp-x86_64-apple-darwin13.4.0-0.12.7.1/sourcecpp_9f424793a11/sourceCpp_2.so

Соответствующий бит Symbol not found: _ProfilerStart означает, что мы не предоставляем компилятору информацию, необходимую для связи с библиотекой Google perftools. Чтобы исправить это, достаточно добавить бит -lprofiler к вызову компоновщика — самый простой способ — добавить что-то к вашему ~/.R/Makevars с помощью чего-то вроде:

LDFLAGS = -L/usr/local/lib -lprofiler

предполагая, что у вас установлены инструменты Google perftools + символическая ссылка на /usr/local стандартным способом.

Более тщательное решение будет включать реализацию кода атрибутов Rcpp, необходимого для генерации этих флагов, так что добавления // [[Rcpp::plugin(gperftools)]] будет достаточно, чтобы гарантировать, что Rcpp автоматически добавил необходимые флаги. См. ?Rcpp::Rcpp.plugin.maker для получения информации о том, как это можно сделать.

person Kevin Ushey    schedule 19.10.2016