2016-03-08 4 views
1

У меня есть реализация случайного леса в C++, который я запускаю в matlab через mex. Он работает плавно, пока не достигнет функции ниже, где она застревает и начинает потреблять память, пока компьютер не замерзнет.утечка памяти, вероятно, из-за рекурсивной функции

void MyFunction(
    const IDataPointCollection& data, 
    std::vector<std::vector<int> >& leafNodeIndices, 
    ProgressStream* progress=0) const 
{ 
    ProgressStream defaultProgressStream(std::cout, Interest); 
    progress = (progress==0)?&defaultProgressStream:progress; 

    leafNodeIndices.resize(TreeCount()); 

    tbb::parallel_for<int>(0,TreeCount(),[&](int t) 
    { 
    leafNodeIndices[t].resize(data.Count()); 

    (*progress)[Interest] << "\rApplying tree " << t << "..."; 
    trees_[t]->Apply(data, leafNodeIndices[t]); 
    }); 
    (*progress)[Interest] << "STUCK HERE" << std::endl; 
    return; 
} 

Переход через код для trees_[t]->Apply() выше, я был в состоянии сузить ее до рекурсивной функции ниже:

void ApplyNode(
    int nodeIndex, 
    const IDataPointCollection& data, 
    std::vector<unsigned int>& dataIndices, 
    int i0, 
    int i1, 
    std::vector<int>& leafNodeIndices, 
    std::vector<float>& responses_) 
{ 
std::cout<<"applying node"<<std::endl; 
    assert(nodes_[nodeIndex].IsNull()==false); 

    Node<F,S>& node = nodes_[nodeIndex]; 

    if (node.IsLeaf()) 
    { 
    for (int i = i0; i < i1; i++) 
     leafNodeIndices[dataIndices[i]] = nodeIndex; 
    return; 
    } 

    else if (i0 == i1) // No samples left 
    return; 

    else 
    { 
     for (int i = i0; i < i1; i++) 
      responses_[i] = node.Feature.GetResponse(data, dataIndices[i]); 

     int ii = Partition(responses_, dataIndices, i0, i1, node.Threshold); 

     // Recurse for child nodes. 
     ApplyNode(nodeIndex * 2 + 1, data, dataIndices, i0, ii, leafNodeIndices, responses_); 
     ApplyNode(nodeIndex * 2 + 2, data, dataIndices, ii, i1, leafNodeIndices, responses_); 
     return; 
    } 
    } 

Каждый вызов рекурсивной функции имеет разное время вычисления в зависимости от node.Feature.GetResponse() функции. Если я сделаю так же время вычисления для всех рекурсивных вызовов (изменив GetResponse()), код будет работать плавно.

float AxisAlignedFeatureResponse::GetResponse(const IDataPointCollection& data, int index) const { 

    double retArg; 
    // retrieve DataManager object 
    const DataManager& concreteData = (const DataManager&)(data); 

//  // retrieve data point at index 
    DataPoint currDataPoint   = concreteData.getDataPoint(index); 
//  
//  // get coordinates of data point 
    Coordinate currCoordinates  = currDataPoint.getOrigPos(); 
//  
//  // get intensity image of the respective data point 
    int imgIndex = currDataPoint.getImageIndex(); 
    Image currImg = concreteData.getImage(imgIndex);  
    Image currFeatureImg = concreteData.getFeatureImage(imgIndex); 
    // return respective feature 
    int featureNumber = (int)(this->axis*(double)concreteData.getNumberOfFeatures());  
    if(featureNumber>=concreteData.getNumberOfFeatures()){ 
     cout<<"warning! trying to reach a feature that is not there!"<<endl; 
     featureNumber=concreteData.getNumberOfFeatures()-1; 
    } 

    std::vector<Coordinate> feature = concreteData.getFeature(featureNumber); 
    Coordinate tmp=currCoordinates+feature[0]; 
    if(feature[1].x == 0) { 
     retArg = currCoordinates.x*feature[0].x+currCoordinates.y*feature[0].y+currCoordinates.z*feature[0].z; 
    //retArg = 0;  //DOING THIS runs the code smoothly 
    } 

    else if(feature[1].x == 2) { 
     retArg = currFeatureImg.getValue(feature[0]); 
    } else { 
     retArg = currImg.mean(tmp,feature[1]); 
    } 
    return (float)(retArg); 
     //return (float) 0; 
} 
+0

Так что, похоже, проблема не в GetResponse? Где код для этого? – xaxxon

+0

@xaxxon добавлен сейчас, хотя я не вижу, как может быть проблема в этом, за исключением разницы во времени вычисления – Azhar

ответ

0

Это выглядит как работа для valgrind. Я не вижу никакой причины для утечки памяти, если ваша программа не прекратится внезапно. Утечки памяти обычно вызваны тем, что переменные кучи не освобождаются («новый» не сопровождается последующим «удалением»).

Valgrind предоставит вам преступника и номер строки, и вы можете установить контрольные точки и пройти через gdb, чтобы узнать, что именно происходит. Возможно, опубликуйте подробный вывод работы «valgrind -v your_program». Не забудьте скомпилировать с опцией -g предоставить полные данные отладки valgrind и gdb.

+1

, к сожалению, нет документального способа запуска valgrind с mex-файлами matlab – Azhar

Смежные вопросы