C++ C++;映射性能-Linux(30秒)与Windows(30分钟)!
我需要处理一个文件列表。不应对同一文件重复处理操作。我使用的代码是-C++ C++;映射性能-Linux(30秒)与Windows(30分钟)!,c++,performance,stl,C++,Performance,Stl,我需要处理一个文件列表。不应对同一文件重复处理操作。我使用的代码是- using namespace std; vector<File*> gInputFileList; //Can contain duplicates, File has member sFilename map<string, File*> gProcessedFileList; //Using map to avoid linear search costs void processFile(F
using namespace std;
vector<File*> gInputFileList; //Can contain duplicates, File has member sFilename
map<string, File*> gProcessedFileList; //Using map to avoid linear search costs
void processFile(File* pFile)
{
File* pProcessedFile = gProcessedFileList[pFile->sFilename];
if(pProcessedFile != NULL)
return; //Already processed
foo(pFile); //foo() is the action to do for each file
gProcessedFileList[pFile->sFilename] = pFile;
}
void main()
{
size_t n= gInputFileList.size(); //Using array syntax (iterator syntax also gives identical performance)
for(size_t i=0; i<n; i++){
processFile(gInputFileList[i]);
}
}
使用名称空间std;
矢量文件列表//可以包含重复项,文件具有成员sFilename
映射gProcessedFileList//使用map避免线性搜索开销
作废处理文件(文件*pFile)
{
File*pProcessedFile=gpProcessedFileList[pFile->sFilename];
如果(pProcessedFile!=NULL)
return;//已处理
foo(pFile);//foo()是对每个文件执行的操作
gProcessedFileList[pFile->sFilename]=pFile;
}
void main()
{
size\u t n=gInputFileList.size();//使用数组语法(迭代器语法也提供相同的性能)
对于(size_t i=0;i我非常非常强烈地怀疑您的性能问题是否来自STL容器
尝试消除(注释掉)对foo(pFile)
的调用或任何其他涉及文件系统的方法。虽然运行foo(pFile)
一次可能看起来很快,但在1000个不同的文件上运行它(以我的经验,尤其是在Windows文件系统上)可能会慢得多(例如,由于文件系统缓存行为。)
编辑
您最初的帖子声称调试版本和发布版本都受到影响。现在您正在撤回该声明
请注意,在调试版本中:
STL实现执行以下操作:
额外检查和断言
堆
操作(内存分配等)
执行额外的检查和断言;
此外,在debug下构建
是
禁用(总容量高达10倍
内存分配速度减慢)
没有执行代码优化,
这可能会导致进一步的STL
性能下降(STL多次严重依赖内联、循环展开等)
对于1000次迭代,您可能不会受到上述影响(至少不会在外部循环级别),除非您在foo()中大量使用STL/堆.在任意时间使用调试器闯入程序,堆栈跟踪很有可能会告诉您它在哪里花费时间。我会像处理任何性能问题一样处理它。这意味着:评测。顺便说一句,MSVC有一个内置的评测器,所以这可能是一个熟悉它的好机会它。如果您看到的性能问题与map
类有任何关系,我会感到惊讶。执行1000次查找和1000次插入应该需要几微秒的时间。什么是foo()
正在做什么?在不知道其余代码如何配合的情况下,我认为缓存处理过的文件的总体想法有点古怪
首先尝试删除向量中的重复项,然后对它们进行处理。尝试对每个块或主要操作进行注释,以确定在Linux和Windows中哪个部分实际导致了执行时间的差异。我也不认为这是因为STL映射。问题可能出在foo()内部。这可能是在某些文件操作中,因为在这种情况下,这是我唯一能想到的代价高昂的事情
您可以插入时钟()在操作之间调用以了解执行时间。您说,当您中断时,您发现自己在vector::add中。您向我们展示的代码中没有vector::add,因此我怀疑它在foo
函数中。如果看不到该代码,就很难说出发生了什么
在微软Visual Studio中,您可能无意中创建了一个算法。
< P>,在访问标准的C++库时,存在一个全局锁,以防止调试生成中的多线程问题。这可能会导致大的性能命中。例如,我们的完整测试代码在50分钟内运行在Linux /GCC上,而Windows V上需要5小时。C++ 2008。注意,在发布模式编译时,不使用非调试VisualC++运行时,该性能不存在。 如果您放弃映射并分区向量,则可以改进一些事情。这意味着重新排序输入文件列表。这也意味着您必须找到一种快速确定文件是否已PR的方法。可能通过在文件
类中保留一个标志来处理。如果可以对文件列表重新排序,并且如果可以将脏标志存储在文件
对象中,则可以将性能从O(n log m)提高到O(n),对于n个总文件和m个已处理文件
#include <algorithm>
#include <functional>
// ...
vector<File*>::iterator end(partition(inputfiles.begin(), inputfiles.end(),
not1(mem_fun(&File::is_processed))));
for_each(inputfiles.begin(), end, processFile);
但是要小心:您处理的是指向同一地址的两个不同指针,两个容器中的每一对指针都是这样。确保只有一个指针拥有指针对象
我不指望这两种方法都能解决性能问题,但无论如何。如果你大部分工作都是在linux上完成的,那么我强烈建议你只能在windows中编译到发行版模式。这会让生活更轻松,特别是考虑到所有windows不灵活的库处理问题。我怀疑ct问题不在于std::map,而在于File*类。您是否尝试过确定性能下降的阈值?Windows和linux对打开的文件数量有不同的限制。如果您注释掉foo()
,需要多长时间?要获取更多信息,请删除foo调用。这可能是Linux/Windows中STL、编译器或文件处理的不同。问题肯定不在于映射性能!上面的示例中没有std::vector add。已处理的文件已存储在映射中,因此该步骤是正确的。否,gProcessedFileList[]是已处理文件的缓存,以避免重复重新处理同一文件。我将检查文件是否正在关闭。1.在第一篇文章发表时,我无意中检查了调试版本的行为,认为这是发布版本。对此我很抱歉。2.foo()也大量使用STL…正如我之前所做的那样
vector<File*> processed(inputfiles.size(), 0);
for( vector<File*>::size_type i(0); i != inputfiles.size(); ++i ) {
if( processed[i] != 0 ) return; // O(1)
// ...
processed[i] = inputfiles[i]; // O(1)
}