Я работаю над визуальным обнаружением объектов, и я использую каскадный классификатор из Opencv. Он работает хорошо, но для меня это слишком медленно. Я использовал Vtune, чтобы получить все горячие точки, и я нахожу, что на 140-м этапе исполнения (время процессора, реальное было около 60 секунд), есть 123s накладных расходов. cvCascadeClassifier использует TBB быстрее, но кажется, что все потоки 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 очень маленький) для каждого потока и слияние всех этих векторов в конце. Это решение сокращает накладные расходы (менее 10 с на 140 с процессорного времени), но я хотел бы больше.
Это мой вопрос: Есть ли способ эффективно слить результаты из различных потоков TBB (ака сократить время накладных расходов)?
EDIT: В моем случае я обнаружил ошибку во время ссылки. Создание локальных векторов и слияние в конце с мьютекс хорошо работает. Теперь у меня есть 0.1s накладных расходов на 140s процессорного времени. Это частный случай с небольшим количеством элементов. Антон ответ, кажется, более общий