欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

opencv中CPU指令集优化、GPU

程序员文章站 2022-04-19 10:28:32
...

CPU指令集优化功能可以根据需要开启或关闭:
首先可以使用此函数 
           bool cv::useOptimized()
        来查询当前是否开启了CPU指令集优化功能,
        可以使用函数
                       void cv::setUseOptimized(bool onoff)
来设置是否开启CPU指令集优化功能;
        可以使用此函数
 bool checkHardwareSupport(int feature);
                     来查询你的CPU是否支持某种指令集优化特性。
 feature的取值有以下几种:
          opencv中CPU指令集优化、GPU
请看一下代码:
[cpp] view plain copy
  1. #include   
  2. #include    
  3.   
  4. using namespace std;  
  5. using namespace cv;   
  6.   
  7. int main(int argc ,char** args)  
  8. {  
  9.     //设置是否启用指令集优化特性  
  10.     cv::setUseOptimized(true);  
  11.     //获取当前机器的CPU指令集支持特性  
  12.     bool opt_status = cv::useOptimized();  
  13.     cout<<"当前的指令集优化状态:"<  

在上述代码中,如果setUseOptimized()函数的参数为true的话,则CPU的硬件指令优化功能被开启,状态函数opt_status = cv::useOptimized()返回为真,
bool simd = checkHardwareSupport(CV_CPU_SSE);
	cout << "当前的指令集优化状态:" << simd << endl;
	bool simd1 = checkHardwareSupport(CV_CPU_SSE2);
	cout << "当前的指令集优化状态:" << simd1 << endl;
	bool simd2 = checkHardwareSupport(CV_CPU_SSE3);
	cout << "当前的指令集优化状态:" << simd2 << endl;
	bool simd3 = checkHardwareSupport(CV_CPU_SSSE3);
	cout << "当前的指令集优化状态:" << simd3 << endl;
	bool simd4 = checkHardwareSupport(CV_CPU_MMX);
	cout << "当前的指令集优化状态:" << simd4 << endl;
	bool simd5 = checkHardwareSupport(CV_CPU_SSE4_1);
	cout << "当前的指令集优化状态:" << simd5 << endl;
	bool simd6 = checkHardwareSupport(CV_CPU_SSE4_2);
	cout << "当前的指令集优化状态:" << simd6 << endl;
	bool simd7 = checkHardwareSupport(CV_CPU_AVX);
	cout << "当前的指令集优化状态:" << simd7 << endl;
	bool simd8 = checkHardwareSupport(CV_CPU_POPCNT);
	cout << "当前的指令集优化状态:" << simd8 << endl;

opencv中CPU指令集优化、GPU

二、

OpenCV的GPU模块只支持NVIDIA的显卡,原因是该部分是基于NVIDIA的CUDA和NVIDIA的NPP模块实现的。而该模块的好处在于使用GPU模块无需安装CUDA工具,也无需学习GPU编程,因为不需要编写GPU相关的代码。但如果你想重新编译OpenCV的GPU模块的话,还是需要CUDA的toolkit。

由于GPU模块的发展,使大部分函数使用起来和之前在CPU下开发非常类似。首先,就是把GPU模块链接到你的工程中,并包含必要的头文件gpu.hpp。其次,就是GPU模块下的数据结构,原本在cv名字空间中的现在都在gpu名字空间中,使用时可以gpu::和cv::来防止混淆

需要再说明的是,在GPU模块中,矩阵的名字为GpuMat,而不是之前的Mat,其他的函数名字和CPU模块中相同,不同的是,现在的参数输入不再是Mat,而是GpuMat。

还有一个问题就是,对于2.0的GPU模块,多通道的函数支持的并不好,推荐使用GPU模块处理灰度的图像。有些情况下,使用GPU模块的运行速度还不及CPU模块下的性能,所以可以认为,GPU模块相对而言还不够成熟,需要进一步优化。很重要的一个原因就是内存管理部分和数据转换部分对于GPU模块而言消耗了大量的时间。

需要注意的是,在所有使用GPU模块的函数之前,最好需要调用函数gpu::getCudaEnabledDeviceCount,如果你在使用的OpenCV模块编译时不支持GPU,这个函数返回值为0;否则返回值为已安装的CUDA设备的数量。

还有一点就是使用GPU模块,需要在用CMake编译OpenCV时使其中的WITH_CUDA和WITH_TBB的宏生效,为ON。

由于我对GPU部分的熟悉程度还不行,先拿来一段sample自带的一段求矩阵转置的程序来做例子,代码如下:

[cpp] view plain copy
  1. #include <iostream>  
  2. #include "cvconfig.h"  
  3. #include "opencv2/core/core.hpp"  
  4. #include "opencv2/gpu/gpu.hpp"  
  5. #include "opencv2/core/internal.hpp" // For TBB wrappers  
  6.   
  7. using namespace std;  
  8. using namespace cv;  
  9. using namespace cv::gpu;  
  10.   
  11. struct Worker { void operator()(int device_id) const; };  
  12.   
  13. int main()  
  14. {  
  15.     int num_devices = getCudaEnabledDeviceCount();  
  16.     if (num_devices < 2)  
  17.     {  
  18.         std::cout << "Two or more GPUs are required\n";  
  19.         return -1;  
  20.     }  
  21.     for (int i = 0; i < num_devices; ++i)  
  22.     {  
  23.         DeviceInfo dev_info(i);  
  24.         if (!dev_info.isCompatible())  
  25.         {  
  26.             std::cout << "GPU module isn't built for GPU #" << i << " ("  
  27.                  << dev_info.name() << ", CC " << dev_info.majorVersion()  
  28.                  << dev_info.minorVersion() << "\n";  
  29.             return -1;  
  30.         }  
  31.     }  
  32.   
  33.     // Execute calculation in two threads using two GPUs  
  34.     int devices[] = {0, 1};  
  35.     parallel_do(devices, devices + 2, Worker());  
  36.   
  37.     return 0;  
  38. }  
  39.   
  40.   
  41. void Worker::operator()(int device_id) const  
  42. {  
  43.     setDevice(device_id);  
  44.   
  45.     Mat src(1000, 1000, CV_32F);  
  46.     Mat dst;  
  47.   
  48.     RNG rng(0);  
  49.     rng.fill(src, RNG::UNIFORM, 0, 1);  
  50.   
  51.     // CPU works  
  52.     transpose(src, dst);  
  53.   
  54.     // GPU works  
  55.     GpuMat d_src(src);  
  56.     GpuMat d_dst;  
  57.     transpose(d_src, d_dst);  
  58.   
  59.     // Check results  
  60.     bool passed = norm(dst - Mat(d_dst), NORM_INF) < 1e-3;  
  61.     std::cout << "GPU #" << device_id << " (" << DeviceInfo().name() << "): "  
  62.         << (passed ? "passed" : "FAILED") << endl;  
  63.   
  64.     // Deallocate data here, otherwise deallocation will be performed  
  65.     // after context is extracted from the stack  
  66.     d_src.release();  
  67.     d_dst.release();  
  68. }  

1、OpenCV提供的开发包中提供的库没有开启gpu和ocl模块功能,虽然有***gpu.lib/***gpu.dll文件,但不能用。如果调用gpu::getCudaEnableDeviceCount()将会return 0;要开启该功能需要重新编译opencv的库。

2、 参考http://docs.opencv.org/modules/gpu/doc/introduction.htmlhttp://blog.csdn.net/quanquanyu/article/details/8917765文章,需要在编译之前安装:CMake用于生成vs工程,Tbb, Qt(gui), cuda tool kit, python 等程序。

3、用CMake生成vs工程时,要打开cuda功能,其他功能可以任选,要让cmake找到你的tbb、qt、cuda和python的位置。

4、有时候要编译静态库,这时需要更改vs工程。对于不同目录下的更改设置不同。对于输出是.EXE的工程,要修改Use of MFC为 use MFC in a Static Library, 在C/C++中的Runtime Library中修改为/Mt(d debug or release),而对于输出是.dll的工程则需要把输出的改为.lib并修改configuration Type为 Static Library(.lib)


配置CUDA

相关标签: GPU CPU