使用OpenCV进行并行GPU计算

时间:2012-06-21 15:25:10

标签: opencv parallel-processing cuda gpgpu

我的应用程序需要并行处理多个图像才能保持实时速度。

据我了解,我无法在单个CUDA设备上以多线程方式调用OpenCV的GPU功能。我尝试过一个OpenMP代码构造,如下所示:

#pragma omp parallel for
for(int i=0; i<numImages; i++){
    for(int j=0; j<numChannels; j++){
        for(int k=0; k<pyramidDepth; k++){
            cv::gpu::multiply(pyramid[i][j][k], weightmap[i][k], pyramid[i][j][k]);
        }
    }
}

这似乎正确编译和执行,但遗憾的是它似乎在同一个CUDA设备上串行执行numImages线程。

如果我有多个CUDA设备,我应该可以并行执行多个线程,对吗?为了获得多个CUDA设备,我需要多个视频卡吗?

有没有人知道nVidia GTX 690双芯片卡是否可以作为两个独立的CUDA设备使用OpenCV 2.4或更高版本?我发现确认它可以在OpenCL中使用,但没有关于OpenCV的确认。

4 个答案:

答案 0 :(得分:5)

只需将整个图像传递给cv::gpu::multiply()函数。

OpenCV和CUDA将处理拆分并以最佳方式划分任务。通常,GPU中的每个计算机单元(即核心)可以运行多个线程(在CUDA中通常> = 16)。除此之外,还有可以显示为多个GPU或将多个链接卡放在一台机器中的卡。

cv::gpu的重点是让您不必了解内部工作原理。

答案 1 :(得分:4)

马丁的答案为我工作。关键是如果您的CUDA设备被列为计算能力2或更高版本,则使用gpu :: Stream类。我将在此重申它,因为我无法在评论迷你编辑器中正确发布代码片段。

cv::gpu::Stream stream[3];

for(int i=0; i<numImages; i++){
    for(int j=0; j<numChannels; j++){
        for(int k=0; k<pyramidDepth; k++){
            cv::gpu::multiply(pyramid[i][j][k], weightmap[i][k], pyramid[i][j][k], stream[i]);
        }
    }
}

上面的代码似乎并行执行乘法(我的应用程序的numImages = 3)。还有Stream方法可以帮助上传/下载GPU内存中的图像,以及检查流状态以帮助与其他代码同步的方法。

所以...显然不需要多个CUDA设备(即GPU卡)来并行执行OpenCV GPU代码!

答案 2 :(得分:0)

我对OpenCV的GPU功能一无所知,但如果它们是完全独立的(即创建GPU上下文,将数据传输到GPU,计算结果,将结果传回CPU),那么这些并不奇怪使用单个GPU时,函数会显示为序列化。

如果您有多个GPU,那么应该有一些方法可以告诉OpenCV功能针对特定的GPU。如果你有多个GPU并且可以有效地定位它们,那么我认为没有理由不对GPU函数调用进行并行化。根据OpenCV wiki,GPU功能仅针对单个GPU,但您可以自己手动拆分工作:http://opencv.willowgarage.com/wiki/OpenCV%20GPU%20FAQ#Can_I_use_two_or_more_GPUs.3F

就GPU程序而言,像GTX 690这样的双GPU将作为两个不同的设备出现,并拥有自己的内存。见这里:http://forums.nvidia.com/index.php?showtopic=231726

此外,如果您要为计算应用程序采用双GPU路由,我建议不要使用GTX 690,因为与GTX 590相比,它的计算性能有些瘫痪。

答案 3 :(得分:0)

无论您使用哪种OpenCV版本,GTX 290都表现为2个独立的CUDA设备。你不需要多个GPU卡来获得多个GPU,你可以在一张卡上使用2个GPU,例如在GTX 290中。但是,从CUDA编程的角度来看,使用290上的两个GPU和使用它们没有太大区别单独连接的GPU卡上有2个GPU。许多OpenCV用户使用ArrayFire CUDA库来补充更多图像处理功能和简单的多GPU缩放。当然,我的免责声明是我在ArrayFire上工作,但我确实认为在这种情况下它会对你有帮助。