利用Google Perftools和kcachegrind深入分解R措施机能瓶颈
当前位置:以往代写 > 其他教程 >利用Google Perftools和kcachegrind深入分解R措施机能瓶颈
2019-06-14

利用Google Perftools和kcachegrind深入分解R措施机能瓶颈

利用Google Perftools和kcachegrind深入分解R措施机能瓶颈

1 分解与Profiling


这里的”分解”对应的单词是”profiling”, 中文好像没有词语能精准地表达出原词的内在, 与”shell”的环境有点雷同, 所以就不去决心翻译了. 由于没有学过软件工程, 不惜先贴一段wiki上profiling的界说[1]:



In software engineering, program profiling, software profiling or simply profiling, a form of dynamic program analysis (as opposed to static code analysis), is the investigation of a program’s behavior using information gathered as the program executes. The usual purpose of this analysis is to determine which sections of a program to optimize – to increase its overall speed, decrease its memory requirement or sometimes both.


要提高R措施的运行速度, 不只仅需要剽悍的呆板(单核高频, 多核并行, GPU)和高效的代码(向量化, 殽杂编程), 寻找措施中的机能瓶颈并举办有针对的优化也是很重要的, “找到北这个偏向”, 就是profiling的意义地址.


R中其实自带了几个最简朴的profiling东西, 我们或多或少都打仗过:

  • base::system.time() —— 简略的计时秒表

  • utils::Rprof() —— 对CPU的浅易profile东西

  • utils::Rprofmem() —— 对内存的浅易profile东西

  • 关于这些函数的利用, 可以参看Ross Ihaka的说明[2]. 与此同时, CRAN上profr(Hadley Wickham)和proftools(Luke Tierney)两个微型包均提供了可视化Rprof()函数输出功效的本领. 可是, 这类简朴的profiling只将措施拆解了到了单个R运算的条理, 没有提供更深一层, 即profiling compiled code的成果. R原生支持这个特性, 但需要在编译时对默认选项举办简朴的修改[4].


    2 安装Google Perftools


    翻看Dirk Eddelbuettel牛在useR2010上的RhpcTutorial[3], 个中提到了Google员工开拓的Google Perftools可以profiling compiled code. 试了一下, 感受是个不错的东西, 共同kcachegrind, 还可以将功效可视化.


    测试情况: Arch Linux x86_64


    AUR上已有一位大人在维护google-perftools(源代码安装):

    sudo yaourt -S google-perftools

    Fedora:

    sudo yum install google-perftools

    Ubuntu:

    sudo apt-get install google-perftools

    不外Ubuntu/Fedora客栈中的二进制包大概较量陈旧了, 无妨直接自行编译版本:

    svn checkout http://google-perftools.googlecode.com/svn/trunk/

    在Arch x86_64下, google-perftools的默认安装路径为

    /usr/bin

    库文件libprofiler.so位于

    /usr/lib

    Google Perftools东西会合除了名为pprof的CPU profiler以外, 还提供了堆内存泄漏检测/利用环境统计等东西. 这里我们只存眷pprof就可以了: 它通过CPU间断采样的方法统计每个函数被采样的次数, 占总采样次数的百分比, 挪用的子函数的被采样次数等等(可以说”分解”在此处照旧较量得当的). 最后通过这些信息寻找措施的(CPU)机能瓶颈.


    3 利用Google Perftools


    要和R一起利用, pprof有两种可行的运行方法, 第一种较量硬朗: 在编译选项中直接插手对libprofiler.so的引用, R在运行时就会自动加载libprofiler库:

    wget http://cran.r-project.org/src/base/R-2/R-2.13.1.tar.gz
    tar -xf R-2.13.1.tar.gz
    cd R-2.13.1

    export MAIN_CFLAGS=”-pg”
    export MAIN_FFLAGS=”-pg”
    export MAIN_LDFLAGS=”-pg”
    export LDFLAGS=”-lprofiler”
    # 也可显式指定路径:
    # export LDFLAGS=”-L/usr/lib -lprofiler”
    ./configure –enable-R-shlib

    参数 -pg 打开R的profiling支持, 设定LDFLAGS用以毗连libprofiler库.

    configure完成:

    R is now configured for x86_64-unknown-linux-gnu
    

    Source directory: .
    Installation directory: /usr/local

    C compiler: gcc -std=gnu99 -g -O2
    Fortran 77 compiler: gfortran -g -O2

    C++ compiler: g++ -g -O2
    Fortran 90/95 compiler: gfortran -g -O2
    Obj-C compiler:

    Interfaces supported: X11
    External libraries: readline, ICU, lzma
    Additional capabilities: PNG, JPEG, TIFF, NLS, cairo
    Options enabled: shared R library, shared BLAS, R profiling, Java

    Recommended packages: yes

    功效无误, 开始编译安装:
    make && sudo make install

    这样, 毗连了libprofiler.so的R编译乐成.

    第二种利用pprof的方法则相对委婉: 利用时动态预加载库文件就可以了, Dirk大人的RhpcTutorial中已经给出说明, 此略.

    选取《Wringting R Extension》 3.2节中给出的一个例子举办测试:

     

    #!/usr/local/lib64/R/bin/Rscript
    suppressMessages(library(MASS))
    suppressMessages(library(boot))
    Storm.fm <- nls(Time ~ b*Viscosity/(Wt – c), stormer,
    start = c(b=29.401, c=2.2183))
    st <- cbind(stormer, fit=fitted(storm.fm))
    storm.bf <- function(rs, i) {
    st$Time <- st$fit + rs[i]
    tmp <- nls(Time ~ (b * Viscosity)/(Wt – c), st, start = coef(storm.fm))
    tmp$m$getAllPars()
    }
    rs <- scale(resid(storm.fm), scale = FALSE)
    storm.boot <- boot(rs, storm.bf, R = 500)

    将profiling功效记录到文件:

    chmod 755 profiling.R
    CPUPROFILE=rprof.out ./profiling.R

    这里在写R文件时用了一点点能力, 使得它可以或许支持类Unix系统的Shebang特性而直接执行, 参考[7], [8].

    执行完毕后, 我们即可利用pprof来阐明输出的功效文件(一个二进制文件!)了. pprof可以将此文件理会成你想要的各类可读的形式. 其参数如下:

    pprof –option [ –focus=< regexp > ] [ –ignore=< regexp > ]
    [–line or addresses or functions] 可执行文件路径 功效文件路径

    方括号为可选项目, < regexp >为正则表达式.

    详细的选项分为几组. 个中输格外式的根基可选项为:

    text, callgrind, gv, evince, web, symbols, dot, ps, pdf, svg, gif, raw, list=< regexp >, disasm

    text 暗示字符统计输出形式, 其它均对应各自的图形名目;
    list=< regexp > 暗示输出匹配正则表达式的函数的源代码;
    diasm=< regexp > 暗示输出匹配正则表达式的函数的反汇编代码.

    其他较量重要的参数:

    –focus=< regexp > 暗示只统计函数名匹配正则表达式的函数的采样;
    –ignore=< regexp > 暗示不统计函数名匹配正则表达式的函数的采样;
    [–line or addresses or functions] 暗示生成的统计是基于代码行, 指令地点照旧函数的, 默认是函数.

    这里仅输出文字型功效:

     

    pprof –cum –text /usr/local/lib64/R/bin/Rscript rprof.out | less

    功效中的前15位:

    Total: 254 samples
    2 0.8% 0.8% 213 83.9% Rf_applyClosure
    24 9.4% 10.2% 213 83.9% Rf_eval
    0 0.0% 10.2% 213 83.9% do_begin
    0 0.0% 10.2% 212 83.5% do_set
    0 0.0% 10.2% 206 81.1% do_internal
    0 0.0% 10.2% 148 58.3% do_lapply
    7 2.8% 13.0% 123 48.4% Rf_evalList
    0 0.0% 13.0% 107 42.1% Rf_ReplIteration
    0 0.0% 13.0% 104 40.9% R_ReplConsole
    0 0.0% 13.0% 102 40.2% Rf_usemethod
    0 0.0% 13.0% 100 39.4% run_Rmainloop
    0 0.0% 13.0% 96 37.8% main
    0 0.0% 13.0% 92 36.2% __libc_start_main
    0 0.0% 13.0% 85 33.5% do_usemethod
    1 0.4% 13.4% 85 33.5% forcePromise

    输出功效中, 每行对应着一个函数的统计:

  • 第1, 2列是该函数的当地采样(不包罗被该函数挪用的函数中的采样次数)次数和比例;
  • 第3列是该函数当地采样次数占当前所有已统计函数的采样次数之和的比例;
  • 第4, 5列是该函数的累计采样次数(包罗其挪用的函数中的采样次数)和比例.
  • 假如你的系统中安装了gnu-gv或evince, 即可直接立刻显示一幅无码清晰大图(ps/pdf):

     

    pprof –gv /usr/local/lib64/R/bin/Rscript rprof.out
    pprof –evince /usr/local/lib64/R/bin/Rscript rprof.out

    rprof

    其他几个较量常用的选项大概是

    生成PDF:

    pprof –pdf /usr/local/lib64/R/bin/Rscript rprof.out > rprof.pdf

    生成SVG:

    pprof –svg /usr/local/lib64/R/bin/Rscript rprof.out > rprof.svg

    生成GraphViz所支持的dot名目:

    pprof –dot /usr/local/lib64/R/bin/Rscript rprof.out > rprof.dot

    虽然, 要想读懂图中的内容, 从而针对某些部门举办优化, 还需要对R的底层较量熟悉才行: 最起码要相识涉及到的C函数的详细成果.

    4 共同kcachegrind可视化profile功效

    pprof可将输出转化为强大的Valgrind东西会合的组件Callgrind可回收的名目, 共同KCachegrind这个图形前端, 即可对功效举办简朴的可视化, 可以或许交互哦亲:

    # For Arch Linux
    # sudo pacman -S kdesdk-kcachegrind
    pprof –callgrind /usr/local/lib64/R/bin/Rscript rprof.out > rprof.callgrind
    kcachegrind rprof.callgrind

    kcachegrind

    其实看上去KCachegrid就是做了一个最普通的树可视化, 所以理论上我们其实可以用角度各异的无数种手段展示profiling功效: 就是画一棵树嘛. 不外KCachegrind中可以与图形交互, 进一步的阐明很利便, 各人可以本身进一步体验.

    5 其他东西(sprof和oprofile)

    Writing R Extensions[6]提到别的两个可供Linuxer选择的东西: sprof和oprofile, 我没有尝试, 感乐趣的同学不妨实践一下.

      关键字:

    在线提交作业