如何在并发::: parallel_for中可靠地将线程与对象实例配对?

时间:2018-12-05 14:49:00

标签: c++ ppl

我有M个图像的向量,必须并行处理多达N个线程,其中N是用户设置的参数。

我还有一个由N个Detector实例组成的向量,它们负责处理,但是每个实例必须在自己的线程中运行(即,如果两个线程在实例之前在同一实例上调用detect()之前的通话结束了,不好的事情会发生)

Detector是一个自包含的类(我可以根据需要进行修改),该方法我调用一种void Detector::detect(cv::Mat image)方法,该方法会在(冗长的)检测过程中更改检测器的内部状态(因此需要防止从不同的线程并行调用detect()

我最初是用OpenMP实现的:

#pragma omp parallel for num_threads(N)
for(int i=0; i<M; i++)
{
    detectors[omp_get_thread_num()].detect(images[i]);
}

但是,由于检测会引发异常,因此我想到了使用PPL的parallel_for来代替,它带有在主线程中捕获线程起源的异常。

问题是,找不到与omp_get_thread_num对应的Detector映射到特定线程:

concurrency::CurrentScheduler::Create( concurrency::SchedulerPolicy( 2, 
concurrency::MinConcurrency, 1, concurrency::MaxConcurrency, N ) );
concurrency::parallel_for(0, M, [&](int i)
{
    detectors[?????].detect(images[i]);
});
concurrency::CurrentScheduler::Detach(); // clear scheduler

如何确保一个线程始终使用检测器池中的同一实例? 或者,如果这是错误的方法,我如何在已经拥有的检测器池上映射detect()的执行情况?

1 个答案:

答案 0 :(得分:0)

根据@NathanOliver的建议,我最终使用concurrent_queue解决了这个问题:

using namespace concurrency;
CurrentScheduler::Create( SchedulerPolicy( 2, 
MinConcurrency, 1, MaxConcurrency, N ) );
concurrent_queue<std::shared_ptr<Detector>> detectors_queue;
for(auto& det : obj->instances)
{
    detectors_queue.push(det);
}
parallel_for(0, M, [&](int i)
{
    std::shared_ptr<Detector> thread_det = nullptr;
    while(!detectors_queue.try_pop(thread_det))
    {
        wait(100);
    }
    thread_det->detect(images[i]);
    detectors_queue.push(thread_det);
});
CurrentScheduler::Detach(); // clear scheduler