【问题标题】:Matrix multiplication in c++ armadillo is very slowc ++犰狳中的矩阵乘法非常慢
【发布时间】:2022-01-01 12:16:30
【问题描述】:

我正在使用犰狳做一些基本的乘法运算,但由于某种原因,它需要很长时间才能完成。我对 c++ 很陌生,所以我可能做错了什么,但即使在这个非常基本的例子中我也看不到它:

#include <armadillo>
#include <iostream>

using namespace arma;

int main(){
    arma::vec coefficients = {1.0, 1.09, 1.08};
    arma::mat X = arma::mat(100000, 3, fill::randu) * coefficients;

    cout << X.n_cols;
}

当我的意思是非常慢时,我已经运行了这个示例几分钟但没有完成

编辑

我使用perf stat ./main 运行脚本,但在一段时间后停止了它,因为它不应该花那么长时间。这是输出。

^C./main: Interrupt

 Performance counter stats for './main':

        257,169.20 msec task-clock                #    1.003 CPUs utilized          
             3,342      context-switches          #   12.995 /sec                   
               215      cpu-migrations            #    0.836 /sec                   
             1,312      page-faults               #    5.102 /sec                   
   963,025,520,077      cycles                    #    3.745 GHz                    
   542,959,361,927      instructions              #    0.56  insn per cycle         
   113,002,342,332      branches                  #  439.409 M/sec                  
     1,095,168,312      branch-misses             #    0.97% of all branches        

     256.349026907 seconds time elapsed

     147.860947000 seconds user
     109.317743000 seconds sys

【问题讨论】:

  • 这对我来说似乎很快。你是怎么编译的?
  • g++ 默认优化级别为-O0 或“编译时间优化”。试试g++ -O3 main.cpp -o main -larmadillo
  • @JérômeRichard 花了我一段时间来安装 perf。但我更新了问题
  • 查看文档我的怀疑是:矩阵存储方式错误。转置它并做一个转置产品。更适合缓存、TLB 等。
  • 将编译代码改为g++ main.cpp -o main -DARMA_DONT_USE_WRAPPER -larmadillo -llapack即可解决问题。我很乐意接受任何解释原因的人的回答。

标签: c++ armadillo


【解决方案1】:

Armadillo 是一个基于模板的库,可用作仅头文件库。只需包含其标题并确保您链接到一些 BLAS 和 LAPACK 实现。像这样使用时,armadillo 假定您有可用的 BLAS 和 LAPACK 实现。如果您尝试在犰狳中使用任何需要它们而不与它们链接的功能,您将收到链接错误。如果您没有 BLAS 和/或 LAPACK,您可以更改 armadillo_bits/config.hpp 文件并注释掉其中的一些定义,以便犰狳使用它自己(较慢)的功能实现。

或者,犰狳可以编译为包装库,在这种情况下,您只需链接“犰狳”包装库。它的 CMake 代码将尝试在配置期间确定您可用的内容,并“注释掉适当的定义”以防您没有可用的要求,这反过来又会使其使用较慢的实现。该“配置”代码错误地确定您没有可用的 BLAS,因为 BLAS 是提供快速矩阵乘法的代码。

我的建议是确保您已安装 BLAS 和 LAPACK,并将犰狳用作仅标头库,确保将您的程序与 BLAS 和 LAPACK 链接。

另一种选择是使用conan 包管理器来安装犰狳。柯南最近添加了一个安装犰狳的配方。它的优点是可以安装犰狳所需的一切(它安装了 openblas,它提供了 BLAS 和 LAPACK 实现)并且它与系统无关(类似于 Python 中的虚拟环境)。


注意

在您提到的 cmets 中,它与 g++ main.cpp -o main -DARMA_DONT_USE_WRAPPER -larmadillo -llapack 一起使用。原因是即使您安装了包装库,如果您定义ARMA_DONT_USE_WRAPPER,您实际上是在将犰狳用作仅头文件库。您可以将-larmadillo -llapack 替换为-lblas -llapack

【讨论】:

  • 所以只是通过传递参数-larmadillo -llapack 来明确我正在将犰狳与正确的 LAPACK 联系起来?
  • 此时您正在构建自己的程序,并将其与犰狳包装库和系统中安装的 lapack 库链接。即使您将犰狳用作仅标头库,由于ARMA_DONT_USE_WRAPPER 的定义,您仍然可以根据需要链接到包装库。这只是带来了与之相关的内容。你可以把事情说清楚,直接用 blas 和 lapack 链接。
  • 无耻插件:如果您使用 gdb 调试器,您可能会对犰狳库中的类型感兴趣的 pretty printers
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 2017-12-09
  • 2015-08-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多