分享

Armadillo,Eigen,OpenCV 矩阵操作比较(Compare Armadillo, Eigen and OpenCV)

 好景宜人 2015-03-25

转自:http://blog.csdn.net/houston11235/article/details/8501135

有的时候写出来的程序慢也许并不是算法有问题,而是用的库比较慢;也可能并不是库本身慢,而只是你的写法不够高效。在经历了无数次令人蛋疼的等待后,我决定比较一下这几个所谓的高效的线性代数库(OpenCV虽然目标是计算机视觉,但也提供了比较丰富的代数计算能力),看看它们的性能到底怎么样。

有人已经做过类似的事情了,比如  OpenCV vs. Armadillo vs. Eigen on Linux revisited,这哥们比较了这几个库在各种矩阵运算方面的效率,总结的比较齐全。但是,在计算机视觉领域这些还不够,比如经常使用的相似性度量(Similarity Measure)的计算。当然后很多种方法,这里就考虑最基本的SAD(Sum of Absolute Difference)方法吧,简单来说就是把两个矩阵(或者向量)相减,求个绝对值,再加起来。这个计算看起来挺简单的,不过比较的结果令我比较意外。

 先把代码贴出来吧。

  1. //  PerformanceTest.h  
  2.   
  3. #pragma warning(disable:4344)  
  4. #define DEIGEN_NO_DEBUG  
  5. #define DNDEBUG  
  6.   
  7. #include <emmintrin.h>  
  8. #include <opencv.hpp>  
  9. #include <vector>  
  10. #include <iostream>  
  11. #include <armadillo>  
  12. #include <Eigen/Dense>  
  13. #include "Timer.h"  
  14.   
  15. using namespace std;  


  1. //  PerformanceTest.cpp  
  2.   
  3. #include "PerformanceTest.h"  
  4.   
  5. int main(void)  
  6. {  
  7.     Timer timer;        //  timer  
  8.     double elapsedTime; //  time in millisecond  
  9.     double res;         //  SAD value  
  10.     int i;              //  loop variable  
  11.     float bnd = 1e5;    //  loop times  
  12.   
  13.     //  Armadillo  
  14.     arma::mat armaA(4, 1);  
  15.     arma::mat armaB(4, 1);  
  16.     timer.start();  
  17.     for (i = 0; i < bnd; ++i)  
  18.     {  
  19.         res = arma::accu(arma::abs(armaA - armaB));  
  20.   
  21.         //res = 0;  
  22.         //for (int idx = 0; idx < 4; ++idx)  
  23.         //{  
  24.         //  res += abs(armaA(idx, 0) - armaB(idx, 0));  
  25.         //}  
  26.     }  
  27.     elapsedTime = timer.getElapsedTimeInMilliSec();  
  28.     cout<<"arma time : "<<elapsedTime<<" ms"<<endl;  
  29.   
  30.     //  Eigen  
  31.     Eigen::Vector4d eiA;  
  32.     Eigen::Vector4d eiB;  
  33.     Eigen::Vector4d eiC;  
  34.     timer.start();  
  35.     for (i = 0; i < bnd; ++i)  
  36.     {  
  37.         res = (eiA - eiB).cwiseAbs().sum();  
  38.         //res = 0;  
  39.         //for (int idx = 0; idx < 4; ++idx)  
  40.         //{  
  41.         //  res += abs(eiA(idx,0) - eiB(idx, 0));  
  42.         //}  
  43.     }  
  44.     elapsedTime = timer.getElapsedTimeInMilliSec();  
  45.     cout<<"eigen time : "<<elapsedTime<<" ms"<<endl;  
  46.   
  47.     //  OpenCV  
  48.     cv::Mat ocvA(4, 1, CV_64F);  
  49.     cv::Mat ocvB(4, 1, CV_64F);  
  50.     timer.start();  
  51.     for (i = 0; i < bnd; ++i)  
  52.     {  
  53.         res = cv::sum(cv::abs(ocvA - ocvB))[0];  
  54.         //res = 0;  
  55.         //for (int idx = 0; idx < 4; ++idx)  
  56.         //{  
  57.         //  res += abs(ocvA.at<double>(idx, 0) - ocvB.at<double>(idx, 0));  
  58.         //}  
  59.     }  
  60.     elapsedTime = timer.getElapsedTimeInMilliSec();  
  61.     cout<<"opencv time : "<<elapsedTime<<" ms"<<endl;  
  62.   
  63.     //  pointer operation  
  64.     double *a = (double*)_mm_malloc(4 * sizeof(double), 16);  
  65.     double *b = (double*)_mm_malloc(4 * sizeof(double), 16);  
  66.     int len = ocvA.rows;  
  67.     timer.start();  
  68.     for (i = 0; i < bnd; ++i)  
  69.     {  
  70.         res = 0;  
  71.         for (int idx = 0; idx < len; ++idx)  
  72.         {  
  73.             res += abs(a[idx] - b[idx]);  
  74.         }  
  75.         //cout<<"i = "<<i<<endl;  
  76.     }  
  77.     elapsedTime = timer.getElapsedTimeInMilliSec();  
  78.     cout<<"array operation : "<<elapsedTime<<" ms"<<endl;  
  79.   
  80.     //  release resource  
  81.     _mm_free(a);  
  82.     _mm_free(b);  
  83.     return 0;  
  84. }  



其中的计时函数用到的是 Franz Kafka 提供的跨平台高精度计时类,可以从以下地址下载 High Resolution Timer

用以上代码在 release 下得到的结果如下:

  1. arma time : 0.87827 ms  
  2. eigen time : 0.13641 ms  
  3. opencv time : 179.599 ms  
  4. array operation : 0.135591 ms  


可以看出 Eigen 的时间和直接用数组运算的时间是相当的,Armadillo 的时间慢了 6~7 倍左右,而 OpenCV 已经目不忍视了,不知道 OpenCV 是怎么想的,差距有点悬殊。

下面又做了另外一组对比,把循环中的求 SAD 部分用类似于数组的方式自己计算,结果如下

  1. arma time : 0.145423 ms  
  2. eigen time : 0.134772 ms  
  3. opencv time : 0.134362 ms  
  4. array operation : 0.139278 ms  


这下计算时间基本上是相当的了。

通过这些对比得到两个结论:

1、虽然这些库在矩阵相乘等操作上可能比较高效,但是对于某些低级操作可能效率并不高

2、通过模板访问数据并不比数组效率低,性能基本相当

 

实验环境:

Windows 7 Ultimate SP1

Visual C++ 2008

Armadillo 3.4.4

Eigen 3.1.2

OpenCV 2.3.1

Compiled to 32-bit binary

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多