opencv最近版本对GPU加速提供了很好的支持, 使用起来也非常方便,DNN模块默认使用第一个GPU卡进行加速,当我们建立多个检测任务,并且电脑包含多个GPU的时候,我们更希望把每个模型分配到不同的GPU卡上,发挥多个GPU卡的加速效果。
opencv提供了设置GPU卡的接口,也很简单,本文例子测试使用opencv4.4版本,并且编译为支持GPU版本。
一、 函数接口说明
接口在opencv2\core\cuda.hpp 中,函数声明如下。
/** @brief Sets a device and initializes it for the current thread.
@param device System index of a CUDA device starting with 0.
If the call of this function is omitted, a default device is initialized at the fist CUDA usage.
*/
CV_EXPORTS_W void setDevice(int device);
看函数说明, 函数可以为当前线程设置一个设备并且初始化它。 可以理解为 函数对当前线程有效,每个线程需要单独设置,否则就使用默认的第一个GPU卡。
cuda_info.cpp中函数实现如下:
void cv::cuda::setDevice(int device)
{
#ifndef HAVE_CUDA
CV_UNUSED(device);
throw_no_cuda();
#else
cudaSafeCall( cudaSetDevice(device) );
cudaSafeCall( cudaFree(0) );
#endif
}
二、调用方法
有了这个函数,指定GPU序号就很简单了
首先 头文件中包含 cuda.hpp
#include <opencv2/core/cuda.hpp>
然后,在调用setPreferableBackend之前调用setDevice就可以了。
cv::dnn::Net netDetect = cv::dnn::readNet( (const char *)model_file.c_str(), (const char *)config_file.c_str());
cv::cuda::setDevice(nGpuId);
netDetect.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
netDetect.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
三、测试
测试及遗留问题:
因为这个函数是线程相关的,也就存在了三种不同的情况
1、单线程一个模型,设置一个GPU序号。
2、单线程多个模型,设置一个GPU序号,线程内模型使用同一个GPU卡。
3、单线程多个模型,并且把模型分配到不同的GPU卡上。
本文测试电脑4个GPU卡,分4个线程将模型跑在4个卡上, 运行正常。
其它情况有需要请读者自行测试。
欢迎留言讨论!