我试图利用NVBLAS库(http://docs.nvidia.com/cuda/nvblas/)通过将一些计算转移到GPU来加快项目中的线性代数部分(主要是计算统计,MCMC,粒子过滤器和所有这些功能)。

我主要使用C++代码,尤其是Armadillo库进行矩阵计算,并且通过它们的常见问题解答,我知道仅通过以正确的方式链接armadillo(http://arma.sourceforge.net/faq.html)就可以使用NVBLAS。

因此,我设置了库的安装并编写了以下虚拟prog:

#include <armadillo>
int main(){

arma::mat A = arma::randn<arma::mat>(3000,2000);
arma::mat B = cov(A);
arma::vec V = arma::randn(2000);
arma::mat C; arma::mat D;

for(int i = 0; i<20; ++i){ C = solve(V,B); D = inv(B);  }

return 0;
}

用它编译
g++ arma_try.cpp -o arma_try.so -larmadillo

并用
nvprof ./arma_try.so

探查器输出显示:
==11798== Profiling application: ./arma_try.so
==11798== Profiling result:
Time(%)      Time     Calls       Avg       Min       Max  Name
 72.15%  4.41253s       580  7.6078ms  1.0360ms  14.673ms  void magma_lds128_dgemm_kernel<bool=0, bool=0, int=5, int=5, int=3, int=3, int=3>(int, int, int, double const *, int, double const *, int, double*, int, int, int, double const *, double const *, double, double, int)
 20.75%  1.26902s      1983  639.95us  1.3440us  2.9929ms  [CUDA memcpy HtoD]
  4.06%  248.17ms         1  248.17ms  248.17ms  248.17ms  void fermiDsyrk_v2_kernel_core<bool=1, bool=1, bool=0, bool=1>(double*, int, int, int, int, int, int, double const *, double const *, double, double, int)
  1.81%  110.54ms         1  110.54ms  110.54ms  110.54ms  void fermiDsyrk_v2_kernel_core<bool=0, bool=1, bool=0, bool=1>(double*, int, int, int, int, int, int, double const *, double const *, double, double, int)
  1.05%  64.023ms       581  110.19us  82.913us  12.211ms  [CUDA memcpy DtoH]
  0.11%  6.9438ms         1  6.9438ms  6.9438ms  6.9438ms  void gemm_kernel2x2_tile_multiple_core<double, bool=1, bool=0, bool=0, bool=1, bool=0>(double*, double const *, double const *, int, int, int, int, int, int, double*, double*, double, double, int)
  0.06%  3.3712ms         1  3.3712ms  3.3712ms  3.3712ms  void gemm_kernel2x2_core<double, bool=0, bool=0, bool=0, bool=1, bool=0>(double*, double const *, double const *, int, int, int, int, int, int, double*, double*, double, double, int)
  0.02%  1.3192ms         1  1.3192ms  1.3192ms  1.3192ms  void syherk_kernel_core<double, double, int=256, int=4, bool=1, bool=0, bool=0, bool=1, bool=0, bool=1>(cublasSyherkParams<double, double>)
  0.00%  236.03us         1  236.03us  236.03us  236.03us  void syherk_kernel_core<double, double, int=256, int=4, bool=0, bool=0, bool=0, bool=1, bool=0, bool=1>(cublasSyherkParams<double, double>)

我认识到dgemm和其他人的地方...所以它起作用了!精彩的。

现在,我想运行相同的代码,但与R接口(interface),因为有时我需要使用它进行输入/输出和绘图。 RcppArmadillo一直为我创造奇迹,与Rcpp一起提供了我需要的所有工具。因此,我编写了cpp:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
int arma_call(){

  arma::mat A = arma::randn<arma::mat>(3000,2000);
  arma::mat B = cov(A);
  arma::vec V = arma::randn(2000);
  arma::mat C; arma::mat D;

  for(int i = 0; i<20; ++i){ C = solve(V,B); D = inv(B);  }

  return 0;
}

和R脚本:
Rcpp::sourceCpp('arma_try_R.cpp')
arma_call()

并尝试通过在控制台上运行来执行它
nvprof R CMD BATCH arma_try_R.R

(编辑:请注意,使用Rscript而不是R CMD BATCH会产生相同的结果)
[NVBLAS] Cannot open default config file 'nvblas.conf'

很奇怪...也许R无论出于什么原因都无法访问该文件,所以我将其复制到工作目录中并重新运行代码:
==12662== NVPROF is profiling process 12662, command: /bin/sh /usr/bin/R CMD BATCH arma_try_R.R
==12662== Profiling application: /bin/sh /usr/bin/R CMD BATCH arma_try_R.R
==12662== Profiling result: No kernels were profiled.

我不知道是什么原因造成的。
我虽然在装有Bumblebee的Linux系统上,但是最后一次尝试是:
nvprof optirun R CMD BATCH arma_try_R.R

将力R与Nvidia卡一起运行,这一次的输出是
==10900== Profiling application: optirun R CMD BATCH arma_try_R.R
==10900== Profiling result:
Time(%)      Time     Calls       Avg       Min       Max  Name
100.00%  1.3760us         1  1.3760us  1.3760us  1.3760us  [CUDA memcpy HtoD]

因此,就我所了解的剖析器而言,根本没有对cuda库的调用,也没有对委派给GPU的任何计算。
现在实际上有很多问题,而不仅仅是一个。
  • 这仅是无法跟踪R内部调用的事件探查器吗? (我对此表示怀疑)
  • 这是因为在R中编译代码的方式吗?详细模式显示
    /usr/lib64/R/bin/R CMD SHLIB -o 'sourceCpp_27457.so' --preclean 'arma_try_R.cpp'g++ -I/usr/include/R/ -DNDEBUG -D_FORTIFY_SOURCE=2 -I"/home/marco/R/x86_64-unknown-linux-gnu-library/3.2/Rcpp/include" -I"/home/marco/R/x86_64-unknown-linux-gnu-library/3.2/RcppArmadillo/include" -I"/home/marco/prova_cuda" -fpic -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong --param=ssp-buffer-size=4 -c arma_try_R.cpp -o arma_try_R.og++ -shared -L/usr/lib64/R/lib -Wl,-O1,--sort-common,--as-needed,-z,relro -lblas -llapack -o sourceCpp_27457.so arma_try_R.o -llapack -lblas -lgfortran -lm -lquadmath -L/usr/lib64/R/lib -lR

  • 即使我强制使用-larmadillo而不是-lblas标志(通过PKG_LIBS env var),也不会发生任何变化。
  • 有什么方法可以使其工作?我想念什么吗?

  • 如果您需要更多输出,我可以提供所需的内容,无论如何,感谢您阅读本文!

    编辑:
    ldd /usr/lib/R/lib/libR.so
    [NVBLAS] Using devices :0
        linux-vdso.so.1 (0x00007ffdb5bd6000)
        /opt/cuda/lib64/libnvblas.so (0x00007f4afaccd000)
        libblas.so => /usr/lib/libblas.so (0x00007f4afa6ea000)
        libm.so.6 => /usr/lib/libm.so.6 (0x00007f4afa3ec000)
        libreadline.so.6 => /usr/lib/libreadline.so.6 (0x00007f4afa1a1000)
        libpcre.so.1 => /usr/lib/libpcre.so.1 (0x00007f4af9f31000)
        liblzma.so.5 => /usr/lib/liblzma.so.5 (0x00007f4af9d0b000)
        libbz2.so.1.0 => /usr/lib/libbz2.so.1.0 (0x00007f4af9afa000)
        libz.so.1 => /usr/lib/libz.so.1 (0x00007f4af98e4000)
        librt.so.1 => /usr/lib/librt.so.1 (0x00007f4af96dc000)
        libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f4af94d7000)
        libgomp.so.1 => /usr/lib/libgomp.so.1 (0x00007f4af92b5000)
        libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f4af9098000)
        libc.so.6 => /usr/lib/libc.so.6 (0x00007f4af8cf3000)
        /usr/lib64/ld-linux-x86-64.so.2 (0x0000556509792000)
        libcublas.so.7.5 => /opt/cuda/lib64/libcublas.so.7.5 (0x00007f4af7414000)
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f4af7092000)
        libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f4af6e7b000)
        libncursesw.so.6 => /usr/lib/libncursesw.so.6 (0x00007f4af6c0e000)
    

    因此,除了奇怪的[NVBLAS] Using devices :0之外,似乎R至少知道cuda nvblas库...

    最佳答案

    要回答我自己的问题:是的,有可能并且足以使R指向正确的(NV)BLAS库,并且RcppArmadillo将在正确的位置获取例程(您可能需要阅读Dirk Eddelbuettel对问题的评论以查看为什么 )

    现在,介绍我的问题的具体内容以及进行自我解答的原因:

    我认为问题不在我想的地方。

    例如,当我在另一个终端而不是运行nvidia-smi上运行Rscript arma_try_R.R

    +------------------------------------------------------+
    | NVIDIA-SMI 352.41     Driver Version: 352.41         |
    |-------------------------------+----------------------+----------------------+
    | GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
    | Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
    |===============================+======================+======================|
    |   0  GeForce GTX 860M    Off  | 0000:01:00.0     Off |                  N/A |
    | N/A   64C    P0    N/A /  N/A |    945MiB /  2047MiB |     21%      Default |
    +-------------------------------+----------------------+----------------------+
    
    +-----------------------------------------------------------------------------+
    | Processes:                                                       GPU Memory |
    |  GPU       PID  Type  Process name                               Usage      |
    |=============================================================================|
    |    0     20962    C   /usr/lib64/R/bin/exec/R                         46MiB |
    |    0     21598    C   nvidia-smi                                      45MiB |
    +-----------------------------------------------------------------------------+
    

    这意味着GPU确实可以正常工作!

    因此,问题出在nvprof例程中,该例程无法检测到该例程,有时会卡住我的Rscript。但这是另一个完全不相关的问题。

    (我将等待接受它作为答案,看看是否有人来并更巧妙地解决它...)

    09-07 03:41