2016-10-17 1 views
1

개체의 시각적 감지를 위해 노력하고 있으며 Opencv의 계단식 분류기를 사용합니다. 그것은 잘 작동하지만 너무 느립니다. 나는 Vtune을 사용하여 모든 핫스팟을 얻었으며 140 초에 걸친 실행 (CPU 시간, 실제는 약 60 초)에 123 초의 오버 헤드 시간이 있다는 것을 알았습니다. 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 형식이 매우 작기 때문에 목록으로 시도하지 않았 음) 결국 모든 벡터를 병합했습니다. 이 솔루션은 오버 헤드 시간 (CPU 시간의 140s에서 10 초 미만)을 줄이지 만 더 많은 것을 원합니다.

이것은 내 질문입니다. 다른 TBB 스레드의 결과를 효율적으로 병합 할 수 있습니까 (일명 오버 헤드 시간 감소)?

편집 : 내 경우, 나는 연결하는 동안 오류를 발견했습니다. 로컬 벡터를 만들고 뮤텍스와 함께 끝에서 병합하면 잘 작동합니다. 이제 140 초의 CPU 시간에 0.1 초의 오버 헤드가 발생했습니다. 아주 작은 요소가 거의없는 특별한 경우입니다. 안톤의 대답은 당신이 TBB concurrent_vector를 사용하려고 할 수 있습니다

답변

3

결과를 결합하는 또 다른 효율적인 방법이 있습니다. combinable 또는 "ets" 클래스를 사용하여 각 스레드/작업에 대해 .local() 개의 결과를 수집 한 다음 (스레드를 직접 사용하지 마십시오) .combine()

을 사용하여 결과를 결합하십시오
2

더 일반적인 것 같다. grow_by 인터페이스를 사용하면 삽입시 오버 헤드를 줄일 수 있습니다. 스택에 작은 (예 : 16 elem) 배열을 만들고 concurrent_vector에서 모든 요소를 ​​병합 할 수 있습니다.

또한 당신은 concurrent_vector로 전원이 공급 될 C++ 11 emplace_back에 의해 push_back을 대체 할 수 있습니다.

관련 문제