c++ - 如果同时运行 GPU 密集光流算法,为什么会得到损坏的结果?

标签 c++ multithreading opencv

在并行使用 OpenCV CUDA 密集光流时,我注意到有时我得到损坏的光流结果,尽管我在不同的 cuda::GpuMat 上运行它s 和单独的 cuda::Stream s 与单独的 Algorithm实例。

在对代码进行一些实验后,我发现如果我保护 DenseOpticalFlow::calc()mutex 打电话或者只运行一个线程,我总是得到正确(未损坏)的结果。

我将我的代码减少到最小的可重现示例,我在多个线程中多次对相同的输入图像运行光流算法:

#include <thread>
#include <vector>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main() {
    Mat frames[2] = { imread("im0.jpg"), imread("im1.jpg") };
    for (int i = 0; i < 2; i++) cvtColor(frames[i], frames[i], COLOR_BGR2GRAY);
    Size frameSize = frames[0].size();

    vector<thread> workers;
    mutex m;

    for (int id = 0; id < 2; ++id) // 2 threads
        workers.emplace_back([&, id]()
    { // lambda
        // Separate Stream, Algorithm and GpuMats for each thread
        auto algoGpu = cuda::OpticalFlowDual_TVL1::create();
        cuda::Stream stream; 
        cuda::GpuMat optFlow(frameSize, CV_32FC2);
        cuda::GpuMat gpuFrame[2] = {
            cuda::GpuMat(frameSize, CV_8UC1),
            cuda::GpuMat(frameSize, CV_8UC1) 
        };
        Mat downloaded, converted;
        Mat channels[2] = { Mat(), Mat() };

        for (int i = 0; i < 2; ++i) gpuFrame[i].upload(frames[i], stream);

        for (int i = 0; i < 1000; i++) { // run 1000 times with SAME input
            {
                //unique_lock<mutex> l(m); // WORKS OK IF UNCOMMENTED !!!!!
                algoGpu->calc(gpuFrame[0], gpuFrame[1], optFlow, stream);
            }

            if (id == 0) { // show results from same single thread
                optFlow.download(downloaded, stream);
                stream.waitForCompletion();

                split(downloaded, channels);
                channels[0].convertTo(converted, CV_8UC1, 100, 128);
                imshow("flow", converted);
                waitKey(1);
            }
        }

        stream.waitForCompletion();
    });

    for (auto& worker : workers) worker.join();
    return 0;
}

如果我取消注释 //unique_lock<mutex> l(m);每次通话我都会得到相同的有效结果图像。但是,如果我保留它的评论,大约一半的结果已损坏。

输入图片:

im0 im1

正确结果:

correct

损坏结果示例:

corrupt1 corrupt2

我将 OpenCV 4.0 与 CUDA 10.1 结合使用。

最佳答案

此问题现已由 this PR 解决, 并将反射(reflect)在下一版本的 OpenCV 中。

关于c++ - 如果同时运行 GPU 密集光流算法,为什么会得到损坏的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59075944/

相关文章:

c# - 线程中的 TopMost 表单?

c++ - OpenCV Videocapture 抓取和检索

c++ - 为什么有时可以将临时对象上的函数调用运算符解释为不隐藏参数的声明?

c++ - 哪个草案最接近 C++14 标准?

c++ - 使用 vector<>::iterator 时查找索引

Java 从多次调用中收集 CompletableFuture 的结果

c# - 在新的Thread()中等待是否毫无意义?

python - 过滤图像以提高文本识别

android - 静态链接OpenCV 2.4.3.2

c++ - AOT编译语言是如何实现匿名函数的?