использование памяти в алгоритме рекурсивного дерева - PullRequest
0 голосов
/ 19 июня 2011

У меня есть код, в котором мне нужно создать карту с двойными значениями ключей (значение f-критерия между двумя кластерами. Мне нужно рассчитать для этого остаточную сумму квадратов) и сопоставленное значение clusterpair. которая является парой класса Cluster, который я создал. Карта предназначена для хранения значений F-теста между всеми кластерами, чтобы мне не нужно было делать вычисления снова и снова на каждом шаге. Кстати, кластер - это древовидная структура, в которой каждый кластер содержит два подкластера, а сохраненные значения представляют собой 70-мерные векторы.

Проблема в том, что для вычисления RSS мне нужно реализовать рекурсивный код, в котором мне нужно найти расстояние каждого элемента кластера от среднего значения кластера, и это, кажется, потребляет огромный объем памяти. , Когда я создаю ту же карту со значениями ключей, представляющими собой простое расстояние между средними значениями двух кластеров, программа использует минимальное количество памяти, поэтому я думаю, что увеличение использования памяти вызвано вызовом рекурсивной функции RSS. Что я должен сделать, чтобы управлять использованием памяти в коде ниже? В своей текущей реализации системе не хватает памяти, и Windows закрывает приложение, сообщая, что системе не хватило виртуальной памяти.

Основной код:

    map<double,cluspair> createRSSMap( list<Cluster*> cluslist )
    {
            list<Cluster*>::iterator it1;
            list<Cluster*>::iterator it2;

            map<double,cluspair> rtrnmap;


            for(it1=cluslist.begin(); it1!= --cluslist.end() ;it1++)
            {
                it2=it1;
                ++it2;
                cout << ".";

                list<Cluster*>::iterator itc;
                double cFvalue=10000000000000000000;
                double rIt1 = (*it1)->rss();

                for(int kk=0 ; it2!=cluslist.end(); it2++)
                {

                    Cluster tclustr ((*it1) , (*it2));
                    double r1 = tclustr.rss();
                    double r2= rIt1 + (*it2)->rss();
                    int df2 = tclustr.getNumOfVecs() - 2;

                    double fvalue = (r1 - r2) / (r2 / df2);

                    if(fvalue<cFvalue)
                    {
                        cFvalue=fvalue;
                        itc=it2;
                    }
                }


                cluspair clp;
                clp.c1 = *it1;
                clp.c2 = *itc;


                bool doesexists = (rtrnmap.find(cFvalue) != rtrnmap.end());

                while(rtrnmap)
                {
                    cFvalue+= 0.000000001;
                    rtrnmap= (rtrnmap.find(cFvalue) != rtrnmap.end());
                }

                rtrnmap[cFvalue] = clp;


            }

            return rtrnmap;
    }

и реализация функции RSS:

double Cluster::rss()
{
    return rss(cnode->mean);
}

double Cluster::rss(vector<double> &cmean)
{
    if(cnode->numOfVecs==1)
    {
        return vectorDist(cmean,cnode->mean);
    }
    else
    {
        return ( ec1->rss(cmean) + ec2->rss(cmean) );       
    }
}

Большое спасибо заранее. Я действительно не знаю, что делать в этот момент.


ниже приведен код, который я использую для создания карты с ключами, представляющими собой простое евклидово расстояние между двумя средними значениями кластера. Как я уже говорил выше, он очень похож и использует минимальное количество памяти. Он отличается только в расчете fvalue. Вместо рекурсивного вычисления есть вычисление простого расстояния средних двух кластеров. Надеюсь, это поможет определить проблему

    map<double,cluspair> createDistMap( list<Cluster*> cluslist )
    {
            list<Cluster*>::iterator it1;
            list<Cluster*>::iterator it2;

            map<double,cluspair> rtrnmap;


            for(it1=cluslist.begin(); it1!= --cluslist.end() ;it1++)
            {
                it2=it1;
                ++it2;
                cout << ".";

                list<Cluster*>::iterator itc;
                double cDist=1000000000000000;

                for(int kk=0 ; it2!=cluslist.end(); it2++)
                {
                    double nDist = vectorDist( (*it1)->getMean(),(*it2)->getMean());
                    if (nDist<cDist)
                    {
                        cDist = nDist;
                        itc=it2;
                    }
                }   

                cluspair clp;
                clp.c1 = *it1;
              clp.c2 = *itc;



                bool doesexists = (rtrnmap.find(cDist) != rtrnmap.end());

                while(doesexists)
                {
                    cDist+= 0.000000001;
                    doesexists  = (rtrnmap.find(cDist) != rtrnmap.end());
                }

                rtrnmap[cDist] = clp;

            }

            return rtrnmap;
    }

Конструктор кластеров

Cluster::Cluster (Cluster *C1, Cluster *C2)
{
    ec1=C1;
    ec2=C2;
    node* cn = new node;
    cn->numOfVecs = C1->cnode->numOfVecs + C2->cnode->numOfVecs;

    double nov = cn->numOfVecs;
    double div = (1 / nov);

    cn->mean = scalarMultVect(div,vectAdd(scalarMultVect(C1->cnode->numOfVecs,C1->cnode->mean),scalarMultVect(C2->cnode->numOfVecs,C2->cnode->mean)));

    mvect tmv;
    tmv.stock="";
    cn->v1 = tmv;

    cnode = cn;
}

1 Ответ

1 голос
/ 19 июня 2011

Вы задали точно такой же вопрос раньше: Огромное увеличение использования памяти

  1. rtrnmap = (rtrnmap.find (cFvalue)! = Rtrnmap.end ()); не имеет смысла.
  2. Вам сказали передавать данные по ссылкам
  3. Вам сказали добавить информацию для регистрации и посмотреть, сколько выполнено итераций.

Несколько комментариев:

  • Это плохая идея иметь map с ключом double, так как вы можете оказаться не в состоянии извлечь элемент из-за незначительной разницы в double.
  • Добавьте только несколько элементов в коллекцию и вручную выполните все функции в отладчике. Вы увидите, что будет выполнено, и сразу увидите, соответствует ли фактический поток выполнения вашим ожиданиям

И, пожалуйста, не публикуйте свои вопросы дважды (даже если вы используете разных пользователей).

EDIT:

Мы все приняли на себя должного деструктора. Убедитесь, что вы освобождаете любую память, которую вы явно выделяете с помощью new или new[] с delete или delete[], в зависимости от ситуации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...