记忆使用量的巨大增长

Enormous Increase In the Use Of Memory

本文关键字:巨大 使用量 记忆      更新时间:2023-10-16

我有一个代码,我需要创建一个键值为double的映射(两个集群之间的f-test值。我需要为此计算残差平方和)和clusterpair的映射值,clusterpair是我创建的类Cluster的对。Map旨在存储所有集群之间的F测试值,这样我就不需要在每一步中一遍又一遍地进行计算。BTW聚类是一种树结构,其中每个聚类包含两个子聚类,存储的值是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) );       
    }
}

非常感谢。我真的不知道此刻该怎么办。


下面是我用来创建一个映射的代码,其中键是两个聚类均值之间的简单欧氏距离。正如我在上面所说的,它非常相似,并且使用最少的内存。它只在f值的计算上有所不同。代替递归计算的是两个聚类的均值的简单距离的计算。希望这有助于识别问题

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;
}

编辑:

顺便说一句,我已经尝试过这种替代实现,但仍然无法控制内存使用

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);        
    }
}

如果内存不足,则有一个非常深的树,或者集群对象很大,或者两者都很大。尝试创建另一个具有与Cluster树相同拓扑结构的Double树数据结构,并将其称为RSS树以保存RSS值。计算底部节点的rss值,然后递归地填充rss树中的其余值。这样,在进行rss计算时就不会将集群对象保存在内存中。