Opencv中gemm的使用

今天才发现opencv中集成了gemm啊!!之前花了很多时间在OpenBlas的上,今天在看Opencv的代码发现opencv中都已经集成了gemm函数,代码是C语言写的,2.4.9版本的文件在modules/core/src/matmul.cpp中。
函数定义如下:

void cv::gemm( InputArray matA, InputArray matB, double alpha,
           InputArray matC, double beta, OutputArray _matD, int flags )

函数体相当复杂,代码行数将近600行。计算的是:
这里写图片描述

OpenCV的gemm与OpenBlas的对比

代码:

#include "opencv2/core/core.hpp"
#include 
#include
#include
#include
using namespace std;
using namespace cv;

#define LEN 30
float timeOpenCV[LEN];
float timeOpenBlas[LEN];
int main(){
    _LARGE_INTEGER time_start, time_over;
    LARGE_INTEGER f;
    QueryPerformanceFrequency(&f);
    double dqFreq = (double)f.QuadPart;
    RNG &rng = theRNG();
    double alpha = 1.f, gamma = 0;
    int factor = 1;
    for (int i = 0; i < LEN; i++){
        factor += 10;
        int m = 5 * factor, p = 10 * factor, n = 5 * factor;
        Mat_<float> A(m, p, CV_32F), B(p, n, CV_32F), C = Mat::zeros(m, n, CV_32F);
        rng.fill(A, RNG::NORMAL, 1, 100);//mean=1,stddev=100
        rng.fill(B, RNG::NORMAL, 2, 50);
        QueryPerformanceCounter(&time_start);
        cv::gemm(A, B, alpha, C, gamma, C);
        QueryPerformanceCounter(&time_over);
        timeOpenCV[i] = (time_over.QuadPart - time_start.QuadPart) / dqFreq * 1000;//milliseconds
        float *src1, *src2, *src3;
        src1 = (float*)A.data;
        src2 = (float*)B.data;
        src3 = (float*)C.data;
        QueryPerformanceCounter(&time_start);
        cblas_sgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, m, n, p,
            (float)alpha, src1, m, src2, p, (float)gamma, src3, m);
        QueryPerformanceCounter(&time_over);
        timeOpenBlas[i] = (time_over.QuadPart - time_start.QuadPart) / dqFreq * 1000;//milliseconds
    }

    for (int i = 0; i < LEN; i++){
        cout << timeOpenCV[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < LEN; i++){
        cout << timeOpenBlas[i] << " ";
    }
    system("pause");
    return 0;
}

得到的结果在MATLAB中显示如下:
Opencv中gemm的使用_第1张图片
这个是前10个结果的比对,可以看出:
1.OpenBlas第一次运行的时候需要很多时间,其实Opencv也有这个这个现象,第一次启动时运行时间要比第二次运行时间长点点。
2.当矩阵的维数增大时,Opencv所花的矩阵相乘时间成指数增长,而OpenBlas却保持得很好,从下面的30个数据的结果可以看出,OpenBlas所花的时间成线性增长,factor因子是成线性增长的,所以,OpenBlas中的时间复杂度是O(n),这时OpenBlas完胜OpenCV。
Opencv中gemm的使用_第2张图片

结论

1.Opencv中的矩阵乘法函数gemm只适应于矩阵维数小的情况,大概加估计的话,当矩阵阶数是1000以内时,Opencv可以1000ms内完成两个矩阵相乘。
2.OpenBlas适合处理高维矩阵相乘,对于小矩阵有点像杀鸡用牛刀,当矩阵维数为1500*3000时,仍然可以在500ms以内完成两个矩阵相乘。

当然,具体时间可能跟机器有些差别,本结论是程序在Release 32bit配置下运行在AMD3.5GHz,6核64位win7系统上的结果。
另外,Opencv中不支持gemv矩阵向量相乘运算。

转载请注明作者和出处:http://blog.csdn.net/CHIERYU 未经允许请勿用于商业用途

你可能感兴趣的:(opencv图像处理,机器学习框架源码阅读)