使用太多内存(我认为)

时间:2011-06-13 16:59:18

标签: c++ memory memory-management slowdown

我正在尝试运行一个程序来分析包含数字的一堆文本文件。文本文件的总大小约为12 MB,我从360个文本文件中获取1,000个双打并将它们放入向量中。我的问题是我大约在文本文件列表的一半,然后我的计算机变慢,直到它不再处理任何文件。该程序不是无限循环,但我认为我有使用太多内存的问题。有没有更好的方法来存储这些不会占用太多内存的数据?

其他可能相关的系统信息:

运行Linux

8 GB内存

安装了Cern ROOT框架(虽然我不知道如何减少我的内存占用量)

Intel Xeon四核处理器

如果您需要其他信息,我会更新此列表

编辑:我跑了顶,我的程序使用了更多的内存,一旦超过80%我杀了它。有很多代码,所以我会选择分配内存的位等分享。 编辑2:我的代码:

void FileAnalysis::doWork(std::string opath, std::string oName)
{
//sets the ouput filepath and the name of the file to contain the results
outpath = opath;
outname = oName;
//Reads the data source and writes it to a text file before pushing the filenames into a vector
setInput();
//Goes through the files queue and analyzes each file
while(!files.empty())
{
    //Puts all of the data points from the next file onto the points vector then deletes the file from the files queue
    readNext();
    //Places all of the min or max points into their respective vectors
    analyze();
    //Calculates the averages and the offset and pushes those into their respective vectors
    calcAvg();
}
makeGraph();
}

//Creates the vector of files to be read
void FileAnalysis::setInput()
{
string sysCall = "", filepath="", temp;
filepath = outpath+"filenames.txt";
sysCall = "ls "+dataFolder+" > "+filepath;
system(sysCall.c_str());
ifstream allfiles(filepath.c_str());
while (!allfiles.eof())
{
    getline(allfiles, temp);
    files.push(temp);
}
}
//Places the data from the next filename into the files vector, then deletes the filename from the vector
void FileAnalysis::readNext()
{
cout<<"Reading from "<<dataFolder<<files.front()<<endl;
ifstream curfile((dataFolder+files.front()).c_str());
string temp, temptodouble;
double tempval;
getline(curfile, temp);
while (!curfile.eof())
{

    if (temp.size()>0)
    {
        unsigned long pos = temp.find_first_of("\t");
        temptodouble = temp.substr(pos, pos);
        tempval = atof(temptodouble.c_str());
        points.push_back(tempval);
    }
    getline(curfile, temp);
}
setTime();
files.pop();
}
//Sets the maxpoints and minpoints vectors from the points vector and adds the vectors to the allmax and allmin vectors
void FileAnalysis::analyze()
{
for (unsigned int i = 1; i<points.size()-1; i++)
{
    if (points[i]>points[i-1]&&points[i]>points[i+1])
    {
        maxpoints.push_back(points[i]);
    }
    if (points[i]<points[i-1]&&points[i]<points[i+1])
    {
        minpoints.push_back(points[i]);
    }
}
allmax.push_back(maxpoints);
allmin.push_back(minpoints);
}
//Calculates the average max and min points from the maxpoints and minpoints vector and adds those averages to the avgmax and avgmin vectors, and adds the offset to the offset vector
void FileAnalysis::calcAvg()
{
double maxtotal = 0, mintotal = 0;
for (unsigned int i = 0; i<maxpoints.size(); i++)
{
    maxtotal+=maxpoints[i];
}
for (unsigned int i = 0; i<minpoints.size(); i++)
{
    mintotal+=minpoints[i];
}
avgmax.push_back(maxtotal/maxpoints.size());
avgmin.push_back(mintotal/minpoints.size());
offset.push_back((maxtotal+mintotal)/2);

}

编辑3:我在代码中添加了保留向量空间,我添加了代码来关闭文件,但是在程序停止之前我的内存仍然被填充到96%...

5 个答案:

答案 0 :(得分:4)

这可以无休止地优化,但我的直接反应是使用除矢量之外的容器。请记住,向量的存储是在内存中串行分配的,这意味着如果没有足够的当前空间来容纳新元素,添加其他元素会导致整个向量的重新分配

尝试为常量插入优化的容器,例如队列或列表。

或者,如果需要vector,您可以尝试预先分配预期的内存占用量以避免连续重新分配。请参阅vector.reserve()Vector。请注意,保留容量是元素,而不是字节。

int numberOfItems = 1000;
int numberOfFiles = 360;

size_type totalExpectedSize = (numberOfItems) * (numberOfFiles);
myVector.reserve( totalExpectedSize );

----------编辑后续代码----------

我直接关注的是analyze()中的以下逻辑:

for (unsigned int i = 1; i<points.size()-1; i++) 
{     
    if (points[i]>points[i-1]&&points[i]>points[i+1])     
    {         
        maxpoints.push_back(points[i]);     
    }     
    if (points[i]<points[i-1]&&points[i]<points[i+1])     
    {         
        minpoints.push_back(points[i]);     
    } 
} 
allmax.push_back(maxpoints); 
allmin.push_back(minpoints); 

具体来说,我关心的是allmax和allmin容器,你要在其上推送maxpoints和minpoints容器的副本。根据数据集,maxpoints和minpoints容器本身可以通过此逻辑变得非常大。

您要承担几次次的容器副本的费用。是否真的有必要将minpoints / maxpoints容器复制到allmax / allmin中?如果不了解更多,就很难优化存储设计。

我没有看到任何地方实际上已经清空了minpoints和maxpoints,这意味着随着时间的推移它们会变得非常大,并且它们对allmin / allmax容器的相应副本将变得非常大。 minpoints / maxpoints应该代表只有一个文件的最小/最大点吗?

作为一个例子,让我们看一下简化的minpoints和allmin场景(但请记住,这同样适用于max,并且两者都比此处所示的规模更大)。显然,这是一个数据集,旨在表明我的观点:

File 1: 2 1 2 1 2 1 2 1 2 1 2
minpoints: [1 1 1 1 1]
allmin:    [1 1 1 1 1]

File 2: 3 2 3 2 3 2 3 2 3 2 3
minpoints: [1 1 1 1 1 2 2 2 2 2]
allmin:    [1 1 1 1 1 1 1 1 1 1 2 2 2 2 2]

File 3: 4 3 4 3 4 3 4 3 4 3 4
minpoints: [1 1 1 1 1 2 2 2 2 2 3 3 3 3 3]
allmin:    [1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3]

还有其他一些优化和批评,但是现在我将其限制为试图解决你的直接问题。您可以发布makeGraph()函数,以及所涉及的所有容器的定义(点,最小点,最大点,allmin,allmax)吗?

答案 1 :(得分:3)

要尝试的一些事项:

  1. 运行top以查看您的程序使用了多少内存。
  2. valgrind下运行一个较小的问题示例(例如,从1个文件中读取10个浮点数)并检查是否存在内存泄漏。
  3. 使用reserve()
  4. 预先分配所需的向量大小(高估)

答案 2 :(得分:0)

查看您的代码和迭代次数。如果你有很多迭代没有Sleep或基于事件的编程,那么你的进程可能会消耗很多CPU。

OR

预先分配向量的元素数量,以便向量不需要重新分配..但这将是矫枉过正

由于您的程序主要使用CPU,因此将您的进程作为后台运行,并使用top命令查看程序的CPU和内存使用情况。

答案 3 :(得分:0)

  1. 检查内存使用情况是否符合预期,即。您没有泄漏资源(您是否未能释放任何内存,无法关闭任何文件?)
  2. 尝试预先将矢量保留为您需要的完整大小,并查看它是否正确分配。
  3. 您是否一次需要内存中的所有结果?你能把它们写到文件中吗?
  4. 如有必要,您可以尝试:

    • 使用小于double的数据类型
    • 使用数组(如果您担心开销)而不是向量
    • 使用链接的向量列表,如果您担心内存碎片

    但是,我认为这不应该是必要的(或者是生产性的),你所做的事情听起来应该有效。

答案 4 :(得分:0)

您可能在eof()方法中使用readNext()时遇到问题。例如,请参阅C ++常见问题解答中的this SO questionsection 15.4/15.5。如果这确实是这个问题,那么修复读取循环以检查getline()的返回状态应该可以解决问题。

如果没有,我会先调试一下,看看程序在哪里/如何“崩溃”。在这种情况下,我可能会首先通过printf()简单地记录到控制台或日志文件,然后每1000行输出当前文件和状态。让它运行几次并检查日志输出是否有任何明显的麻烦迹象(即,它永远不会超过读取文件#3)。

如果这还不足以揭露问题,那么在必要的位置添加更详细的日志记录和/或打入调试器并开始跟踪(当您的代码概念与计算机不同时很有用,我们经常阅读我们的内容认为代码应该做而不是实际上说的。)