简体   繁体   English

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

[英]How to reliably pair a thread to an object instance in a concurrency::parallel_for?

I have a vector of M images that has to be processed in parallel by up to N threads, where N is a parameter set by the user. 我有一个由M个图像组成的向量,必须由N个线程并行处理,其中N是用户设置的参数。

I also have a vector of N Detector instances that take care of the processing, but each instance must run in its own thread (ie, if two threads call detect() on the same instance before the previous call ended, bad things will happen). 我还有一个由N个Detector实例组成的向量,它们负责处理,但是每个实例必须在自己的线程中运行(即,如果两个线程在上一个调用结束之前在同一实例上调用detect() ,那么将会发生不好的情况) 。

Detector is a self-contained class (that I can modify if necessary) with one void Detector::detect(cv::Mat image) method I call that alters the internal state of the detector for the duration of the (lengthy) detection process (hence the need to prevent parallel calls of detect() from different threads). Detector是一个自包含的类(我可以根据需要进行修改),具有一个void Detector::detect(cv::Mat image)方法,该方法在(冗长的)检测过程中更改检测器的内部状态(因此需要防止从不同线程并行调用detect() )。

I originally implemented this with OpenMP as: 我最初使用OpenMP实现此目的:

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

However, since the detection can throw exceptions, I thought of using PPL's parallel_for instead, which comes with thread-originated-exception catching in the main thread. 但是,由于检测会引发异常,因此我想到了改用PPL的parallel_for ,它在主线程中捕获了线程起源的异常。

The problem is, I can't find an equivalent of omp_get_thread_num that I can use to map a Detector to a specific thread: 问题是,我找不到可用于将Detector映射到特定线程的omp_get_thread_num等效项:

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

How can I ensure that one thread always uses the same instance from the detectors pool? 如何确保一个线程始终使用检测器池中的同一实例? Or, if this is the wrong approach, how can I map the execution of detect() over the pool of detectors I already have? 或者,如果这是错误的方法,我如何在已经拥有的检测器池上映射detect()的执行?

Upon suggestion from @NathanOliver, I ended up using a concurrent_queue to solve the issue: 根据@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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM