犰狳库是不是会减慢矩阵运算的执行速度?

Posted

技术标签:

【中文标题】犰狳库是不是会减慢矩阵运算的执行速度?【英文标题】:Does armadillo library slow down the execution of a matrix operations?犰狳库是否会减慢矩阵运算的执行速度? 【发布时间】:2018-05-17 07:57:28 【问题描述】:

我已将 MATLAB 代码转换为 C++ 以加快速度,使用 Armadillo 库在 C++ 中处理矩阵运算,但令人惊讶的是它比 MATLAB 代码慢了 10 倍!

所以我测试了犰狳库,看看是否是原因。下面的代码是一个简单的测试代码,它初始化两个矩阵,将它们相加并将结果保存到一个新矩阵中。一段代码使用了 Armadillo 库,而另一段则没有。使用犰狳的部分太慢了(注意经过的时间)。

它真的会减慢执行速度(尽管它应该加快执行速度)还是我错过了什么?

#include<iostream>
#include<math.h>
#include<chrono>
#include<armadillo>
using namespace std;
using namespace arma;
int main()
 
   auto start = std::chrono::high_resolution_clock::now();
   double a[100][100];
   double b[100][100];
   double c[100][100];
   for (int i = 0; i < 100; i++)
     
       for (int j = 0; j < 100; j++)
         
           a[i][j] = 1;
           b[i][j] = 1;
           c[i][j] = a[i][j] + b[i][j];
         
     

     auto finish = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsed = finish - start;
    std::cout << "Elapsed time: " << elapsed.count() << " s\n";
    auto start1 = std::chrono::high_resolution_clock::now();
    mat a1=ones(100,100);
   mat b1=ones(100,100);
   mat c1(100,100);
   c1 = a1 + b1;
   auto finish1 = std::chrono::high_resolution_clock::now();
   std::chrono::duration<double> elapsed1 = finish1 - start1;
   std::cout << "Elapsed time: " << elapsed1.count() << " s\n";
   return 0;



这是我得到的答案:

Elapsed time: 5.1729e-05 s
Elapsed time: 0.00025536 s

如您所见,犰狳的速度要慢得多!不使用犰狳库会更好吗?

【问题讨论】:

Performance Tradeoff - When is MATLAB better/slower than C/C++的可能重复 @Wolfie 感谢您提供的链接,我已经检查过了,但我想知道犰狳库是否会减慢代码速度,就像我附加的代码一样。 为什么要使用库来帮助进行矩阵运算,然后手动完成矩阵运算?从 MATLAB 的角度来看,我不知道 C++/Armadillo syntax,但您肯定想在使用 Armadillo 时消除循环并执行 mat c1 = a1 + b1 你的代码没有任何MATLAB,手头的问题和MATLAB有什么关系? @MAh2014 不是用 C++ 开发 MATLAB 代码,而是用 C++ 做数学运算,与 MATLAB 无关。此外,MATLAB 是用于矩阵运算的最快代码,因为它在底层使用了高度优化的库。如果你认为你可以写出比 MATLAB 更快的线性代数代码,那么要么你错了,要么你会变得非常富有。我打赌它是第一个 ;) 【参考方案1】:

首先确保blaslapack库已启用,Armadillo doc有说明。 第二件事是它可能是犰狳中更广泛的内存分配。如果您重组代码以首先进行内存初始化为

#include<iostream>
#include<math.h>
#include<chrono>
#include<armadillo>
using namespace std;
using namespace arma;
int main()
 
   double a[100][100];
   double b[100][100];
   double c[100][100];
   mat a1=ones(100,100);
   mat b1=ones(100,100);
   mat c1(100,100);

   auto start = std::chrono::high_resolution_clock::now();
   for (int i = 0; i < 100; i++)
     
       for (int j = 0; j < 100; j++)
         
           a[i][j] = 1;
           b[i][j] = 1;
           c[i][j] = a[i][j] + b[i][j];
         
     
   auto finish = std::chrono::high_resolution_clock::now();
   std::chrono::duration<double> elapsed = finish - start;
   std::cout << "Elapsed time: " << elapsed.count() << " s\n";

   auto start1 = std::chrono::high_resolution_clock::now();
   c1 = a1 + b1;
   auto finish1 = std::chrono::high_resolution_clock::now();
   std::chrono::duration<double> elapsed1 = finish1 - start1;
   std::cout << "Elapsed time: " << elapsed1.count() << " s\n";

   return 0;

这样我得到了结果:

Elapsed time: 0.000647521 s
Elapsed time: 0.000353198 s

我用(在 Ubuntu 17.10 中)编译它: g++ prog.cpp -larmadillo

【讨论】:

您是否建议使用犰狳将加速矩阵运算?您是否认为如果我使用犰狳将 matlab 矩阵运算转换为完全相同的 C++ 代码(矩阵运算主要是乘法)会加速吗? 如果您使用矩阵/向量运算,犰狳可能不会比 Matlab 快,但是如果您在 Matlab 中循环迭代计算,您将使用犰狳/C++ 获得性能。一个有趣的比较是在 Matlab 中做两个变体(循环和矩阵),在 Matlab 中的差异很可能比犰狳代码更大 但是它是用低级语言(C++)实现的,即使matlab在矩阵运算方面做得更好,它是否会导致更快的执行?【参考方案2】:

我相信问题出在您根本没有使用犰狳。您独特地使用它来创建比 C++ 的普通 2D 数组更复杂的变量,但实际上仅此而已。 Armadillo 可以为您提供非常快速的矩阵运算,就像在c1=a1+b1; 中一样,没有循环。

但是,如果您只是将其编写为 elemetwise 操作,那么您就没有使用犰狳。它与使用 MATLAB 进行矩阵乘法相同,但要自己编写矩阵乘法。那你就不用MATLAB的库了!

【讨论】:

所以如果我删除循环并简单地添加矩阵,它必须比不使用犰狳更快,但事实并非如此。毕竟使用犰狳将matlab代码转换为C++会加快速度吗?我替换了没有循环的代码。 @MAh2014 不,将代码从 MATLAB 转换为犰狳一般不会加快速度,具体取决于您的问题。有时,取决于手头的任务,将 MATLAB 转换为低级语言可以加快速度。但是犰狳专门用于线性代数运算,MATrix LABoratory 软件在这方面做得非常好。但是,对于“它会更快”没有真正的答案,因为这在很大程度上取决于您的问题。

以上是关于犰狳库是不是会减慢矩阵运算的执行速度?的主要内容,如果未能解决你的问题,请参考以下文章

将二维数组转换为犰狳矩阵(垫)对象

1,Python常用库之一:Numpy

python 矩阵运算

python中的矩阵运算

C ++犰狳 - 为列赋值

犰狳 C++ 矩阵线程安全吗