opencv最近版本对GPU加速提供了很好的支持, 使用起来也非常方便,DNN模块默认使用第一个GPU卡进行加速,当我们建立多个检测任务,并且电脑包含多个GPU的时候,我们更希望把每个模型分配到不同的GPU卡上,发挥多个GPU卡的加速效果。

opencv提供了设置GPU卡的接口,也很简单,本文例子测试使用opencv4.4版本,并且编译为支持GPU版本。

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个卡上, 运行正常。

其它情况有需要请读者自行测试。 

欢迎留言讨论!

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐