【发布时间】: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