OpenCV学习之五: 如何用指令启动或关闭OpenCV的CPU指令集CV_SSE2,CV_SSSE4等优化

在这篇博客中,我将会给大家分享关于OpenCV源码中的CPU指令集CV_SSE2等的相关知识

一、
   CV_SSE系列指令集的预编译符号定义在opencv2/core/internal.hpp这个头文件中,如果你不包含这个头文件的话,把源码拷贝到自己的函数中,CV_SSE是不被定义的
下面是harrisCorner中的一部分代码

/*该函数的主要作用是利用给定的梯度协矩阵计算每一个点上的harris角点响应强度矩阵*/
static void calcHarris( const Mat& _cov, Mat& _dst, double k )
{
    int i, j;
    Size size = _cov.size();
#if CV_SSE
    volatile bool simd = checkHardwareSupport(CV_CPU_SSE);  //获取CPU指令集优化状态 
#endif

    if( _cov.isContinuous() && _dst.isContinuous() )
    {
        size.width *= size.height;
        size.height = 1;
    }

    for( i = 0; i < size.height; i++ )
    {
        const float* cov = (const float*)(_cov.data + _cov.step*i);
        float* dst = (float*)(_dst.data + _dst.step*i);
        j = 0;

    #if CV_SSE
		//如果CPU支持SSE指令集优化的话(CV_SSE有定义),而且当前允许使用指令集优化,
		//(simd 状态为真)则下面这段代码将被执行
        if( simd )
        {
            __m128 k4 = _mm_set1_ps((float)k);
            for( ; j <= size.width - 5; j += 4 )
            {
                __m128 t0 = _mm_loadu_ps(cov + j*3); // a0 b0 c0 x
                __m128 t1 = _mm_loadu_ps(cov + j*3 + 3); // a1 b1 c1 x
                __m128 t2 = _mm_loadu_ps(cov + j*3 + 6); // a2 b2 c2 x
                __m128 t3 = _mm_loadu_ps(cov + j*3 + 9); // a3 b3 c3 x
                __m128 a, b, c, t;
                t = _mm_unpacklo_ps(t0, t1); // a0 a1 b0 b1
                c = _mm_unpackhi_ps(t0, t1); // c0 c1 x x
                b = _mm_unpacklo_ps(t2, t3); // a2 a3 b2 b3
                c = _mm_movelh_ps(c, _mm_unpackhi_ps(t2, t3)); // c0 c1 c2 c3
                a = _mm_movelh_ps(t, b);
                b = _mm_movehl_ps(b, t);
                t = _mm_add_ps(a, c);
                a = _mm_sub_ps(_mm_mul_ps(a, c), _mm_mul_ps(b, b));
                t = _mm_mul_ps(_mm_mul_ps(k4, t), t);
                a = _mm_sub_ps(a, t);
                _mm_storeu_ps(dst + j, a);
            }
			return;
        }
    #endif
        //不启用指令集优化时这段普通代码将被执行
        for( ; j < size.width; j++ )
        {
            float a = cov[j*3];
            float b = cov[j*3+1];
            float c = cov[j*3+2];
            dst[j] = (float)(a*c - b*b - k*(a + c)*(a + c));
        }
    }
}

在上述代码中,如果条件编译符号CV_SSE被定义过,则调用checkHardwareSupport(CV_CPU_SSE); 获取你的电脑上的CPU是否支持CPU_SSE指令集优化特性。如果查询结果为真,就说明你的CPU在当前状态下支持CPU_SSE指令集优化特性。如果查询结果为假,就说明你的CPU不支持CPU_SSE指令集优化。但是这并不说明你的CPU硬件本身不支持SSE指令集优化特性。  


二、
CPU指令集优化功能可以根据需要开启或关闭:
首先可以使用此函数  
          bool cv::useOptimized()
        来查询当前是否开启了CPU指令集优化功能,
        可以使用函数
                       void cv::setUseOptimized(bool onoff)
来设置是否开启CPU指令集优化功能;
        可以使用此函数
 bool checkHardwareSupport(int feature);
                      来查询你的CPU是否支持某种指令集优化特性。
 feature的取值有以下几种:
          
请看一下代码:
#include 
    
    
     
     
#include 
     
     
      
       

using namespace std;
using namespace cv; 

int main(int argc ,char** args)
{
	//设置是否启用指令集优化特性
	cv::setUseOptimized(true);
	//获取当前机器的CPU指令集支持特性
	bool opt_status = cv::useOptimized();
	cout<<"当前的指令集优化状态:"<
      
      
       
       <
       
       
      
      
     
     
    
    

在上述代码中,如果setUseOptimized()函数的参数为true的话,则CPU的硬件指令优化功能被开启,状态函数opt_status = cv::useOptimized()返回为真,
 而且在上述代码中我们查询了我的机器的CPU指令优化支持特性,我的CPU型号为Inter Core(TM) i5 650 的,查询结果显示如下:

可以看到,我的CPU支持绝大多数的指令集优化特性,只有最后一个CPU_AVX是0,尽管我们用程序指令开启了指令集优化特性,但是CPU_AVX依然是0,这就说明我的CPU在硬件层面上不提供CPU_AVX的优化功能,即使setUseOptimized()函数的参数为true,也无法使用此功能。
如果setUseOptimized()函数的参数为false的话,则CPU的硬件指令优化功能被关闭,状态函数opt_status = cv::useOptimized()返回为假,上述代码的运行结果为


可以看到,此时所有的CPU指令集优化功能都被禁止了,即使CPU硬件本身支持的特性,也被禁止使用了。

所以在你的程序中,你可以在main()主函数中通过setUseOptimized()函数来设置是否启用OpenCV的指令集优化功能
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值