Огромное увеличение использования памяти - PullRequest
1 голос
/ 18 июня 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;
}

реализация vectorDist ()

double vectorDist(vector<double> vec1, vector<double> vec2)
{

    double sqrsum=0;
    double tempd=0;

    int vs = vec1.size();

    for ( int i=0;i<vs;i++)
    {
        tempd = vec1[i] - vec2[i];
        sqrsum += tempd*tempd;
    }

    return sqrsum;
}

Edit:

Кстати, я пробовал эту альтернативную реализацию, которая по-прежнему не может контролировать использование памяти

double Cluster::rss()
{
    list<double> fvals;
    rss(cnode->mean , fvals);

    double sum=0;
    list<double>::iterator tpit;
    for(tpit=fvals.begin() ; tpit != fvals.end() ; ++tpit)
    {
        sum += *tpit;
    }
    return sum;
}

void Cluster::rss(vector<double> &cmean , list<double> &fvals)
{
    if(cnode->numOfVecs==1)
    {
        fvals.push_back( vectorDist(cmean,cnode->mean) );
    }
    else
    {
        ec1->rss(cmean , fvals);
        ec2->rss(cmean , fvals);        
    }
}

1 Ответ

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

Если вам не хватает памяти, у вас очень глубокое дерево, или ваши объекты кластера большие или оба. Попробуйте создать другую древовидную структуру данных с той же топологией, что и у вашего дерева кластеров, и назовите ее деревом RSS для хранения значений RSS. Вычислите значения rss нижних узлов, а затем рекурсивно заполните остальные значения в дереве RSS . Таким образом, вы не удерживаете кластерные объекты в памяти, пока выполняете вычисления rss.

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