【问题标题】:How to efficiently merge results from TBB threads如何有效地合并来自 TBB 线程的结果
【发布时间】:2016-10-17 09:28:15
【问题描述】:

我正在研究对象的视觉检测,我使用 Opencv 的级联分类器。它运作良好,但对我来说太慢了。我使用 Vtune 获取所有热点,我发现在 140 秒的执行时间(CPU 时间,实际约为 60 秒),有 123 秒的开销时间。 cvCascadeClassifier 使用 TBB 更快,但似乎所有 TBB 线程等待的时间都超过了它们应有的时间。 有代码:

void operator()(const Range& range) const
{
    Ptr<FeatureEvaluator> evaluator = classifier->featureEvaluator->clone();

    Size winSize(cvRound(classifier->data.origWinSize.width * scalingFactor), cvRound(classifier->data.origWinSize.height * scalingFactor));

    int y1 = range.start * stripSize;
    int y2 = min(range.end * stripSize, processingRectSize.height);
    for( int y = y1; y < y2; y += yStep )
    {
        for( int x = 0; x < processingRectSize.width; x += yStep )
        {
            if ( (!mask.empty()) && (mask.at<uchar>(Point(x,y))==0)) {
                continue;
            }

            double gypWeight;
            int result = classifier->runAt(evaluator, Point(x, y), gypWeight);

            #if defined (LOG_CASCADE_STATISTIC)
            logger.setPoint(Point(x, y), result);
            #endif
            if( rejectLevels )
            {
                if( result == 1 )
                    result =  -(int)classifier->data.stages.size();
                if( classifier->data.stages.size() + result < 4 )
                {
                    mtx->lock();
                    rectangles->push_back(Rect(cvRound(x*scalingFactor), cvRound(y*scalingFactor), winSize.width, winSize.height));
                    rejectLevels->push_back(-result);
                    levelWeights->push_back(gypWeight);
                    mtx->unlock();
                }
            }
            else if( result > 0 )
            {
                mtx->lock();
                rectangles->push_back(Rect(cvRound(x*scalingFactor), cvRound(y*scalingFactor),
                                           winSize.width, winSize.height));
                mtx->unlock();
            }
            if( result == 0 )
                x += yStep;
        }
    }
}

我认为问题来自结果的合并。互斥锁过多,线程需要经常等待。这部分代码被调用了很多时间,并且线程很少(在我的例子中是 3 个)。我尝试为每个线程创建局部向量(我没有尝试使用列表,因为 Rect 类型非常小),并在最后合并所有这些向量。此解决方案减少了开销时间(在 140 秒的 CPU 时间上少于 10 秒),但我想要更多。

这是我的问题: 有没有办法有效地合并来自不同 TBB 线程的结果(也就是减少开销时间)?

编辑: 就我而言,我在链接过程中发现了一个错误。创建局部向量并在最后与互斥体合并效果很好。现在,我在 140 秒的 CPU 时间上有 0.1 秒的开销。这是一个非常小的元素很少的特殊情况。安东的回答似乎更笼统

【问题讨论】:

    标签: c++ multithreading opencv tbb


    【解决方案1】:

    还有另一种可能更有效的方法来组合结果。使用combinable"ets" 类来收集每个线程/任务的.local() 结果(不要直接使用线程),然后使用.combine() 组合结果

    【讨论】:

      【解决方案2】:

      您可以尝试使用 TBB concurrent_vectorgrow_by 接口可以帮助您减少插入开销:您可以在堆栈上创建小型(例如 16 个元素)数组并将其中的所有元素合并到 concurrent_vector 中。

      您还可以将push_back 替换为emplace_back 与C++11 驱动的concurrent_vector。

      【讨论】:

        猜你喜欢
        • 2019-09-23
        • 1970-01-01
        • 2018-02-26
        • 2011-11-12
        • 2022-01-14
        • 2010-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多