C++为什么这么慢?我已将这个简单的方法从C#转换为C++。它读取路径表并用整数列表(或整数向量的向量)填充它。路径表中的示例行类似于012516n我意识到有更好的方法可以做到这一点,但现在我只想知道为什么我的C++代码需要这么长时间。例如,在C#版本中为10分钟而不是10秒。这是我的C++代码。我猜我正在做一些非常错误的事情。//将文本路径向量解析到引擎中voidLevel::PopulatePathVectors(stringpathTable){//逐行读取文件。ifstreammyFile(路径表);对于(unsignedinti=0;i());for(unsignedintj=0;j());对于(intj=0;j>12%basic_iostream::basic_iostream9%operator+8%_Mutex::Mutex5%getline5%basic_stringbuf::_Init4%locale::_Locimp::_Addfac4%vector::reserve4%basic_string::assign3%operatordelete2%basic_Streambuf::basic_streambuf1%Wcsxfrm5%其他函数有些东西好像来自inline调用,所以很难说它实际上来自哪里。但是您仍然可以理解。这里唯一应该做I/O的是getline,它只占用5%。其余来自流和字符串操作。C++流很慢。代码中的while循环看起来非常混乱和冗长,因为它以不需要的方式做事:一个简单快速的等价物是:intresult;字符串流ss(线);while(ss>>result)//读取所有整数直到遇到非整数{pathLookupVectors[i][j].push_back(result);在C++中,这样的循环也是惯用的。或者,您可以使用std::copy编写1,而不是手动循环:);这取自@David的评论。或者如果你在push_back向量本身时这样做更好:std::istream_iterator开始(ss),结束;pathLookupVectors[i].push_back(向量(开始,结束));}完毕!我不确定这里发生了什么,但我看到了一些可以优化代码的方法。如果那不能让你到达那里,可能还有其他事情正在发生。你的弦有多大?当您在C++版本中传递它们时,您正在制作副本,因为您是在“按值传递”。尝试通过常量引用传递它:voidLevel::PopulatePathVectors(conststring&pathTable)这通过引用传递对象,这意味着它不制作副本。然后,通常将其设为const以确保它不会在您的函数中被修改。使用.append或+=扩展tempString。我相信你正在创建一个新的字符串对象,然后用+替换旧的字符串对象,而+=和.append将修改当前对象:tempString.append(line[count]);在顶部声明变量,然后重新分配它们以调整性能。这将防止它们每次都被重新创建。比如放字符串行;在你的for循环之前,因为它无论如何都会被覆盖。有几个地方可以做到这一点,例如使用tempString。以下是其他人提到的一些我没有看到的东西。它们有点含糊,但无法重现,因此很难详细说明所有内容。穷人的解剖。当代码运行时,只要不断地打断它即可。通常,您会一遍又一遍地看到相同的堆栈帧。开始评论东西。如果您注释掉拆分并立即完成,那么从哪里开始就很清楚了。一些代码是相关的,但您可以将整个文件读入内存,然后对其进行解析以在花费时间的地方创建清晰的分隔。如果两者都是独立完成的,那么它可能是相互作用的。缓冲。我没有看到你的读取缓冲区。如果要将任何内容写入磁盘,这一点就变得尤为重要。磁盘上的arm将在您的读取位置、然后写入位置等之间来回跳转。虽然它看起来不像您在此处编写的内容,但您的主程序可能使用了更多内存。达到最高水位线后,操作系统可能会开始将一些内存分页到磁盘。当您在分页发生时逐行阅读时,您会感到不安。通常,我会设置一个简单的迭代器接口来验证一切正常。然后在它周围写一个装饰器,一次读取500行。标准流也有一些内置的缓冲选项可能会更好。我猜他们的缓冲默认值非常保守。预订。当您同时使用std::vector::reserve时,std::vector::push_back效果最佳。如果您可以在进入紧密循环之前使大部分内存可用,您就赢了。您甚至不必知道确切的数量,只需猜测即可。你也可以用这个击败std::vector::resize性能,因为std::vector::resize使用alloc而std::vector::push_back将使用realloc最后一点是有争议的,尽管我已经阅读了。我没有理由怀疑我错了,尽管我将不得不做更多的研究来证实或否认。但是,如果使用reserve,push_back可以运行得更快。字符串拆分。在处理gb+文件时,我从未见过高性能的C++迭代器解决方案。不过,我还没有特别尝试过那个。我在猜为什么他们倾向于做很多小的分配。这是我通常使用的参考。关于std::vector::reserve将字符数组拆分为两个字符数组适用于此。出于维护方面的考虑,我更喜欢使用boost::lexical_cast的实现,尽管我不能说它比流式实现的性能更高或更低。我想说的是,很少能真正看到对流使用情况进行正确的错误检查。STL技巧。很抱歉故意对这些含糊不清。我经常编写避免这些情况的代码,尽管我确实记得我的同事告诉我的一些考验和磨难。使用STLPort可以完全避免这些问题。在某些平台上,使用流操作默认启用一些奇怪的线程安全。所以我看到使用小的std::cout绝对会破坏算法的性能。你这里什么都没有,但如果你在另一个线程中登录,它可能会导致问题。我在另一条评论中看到了8%的_Mutex::Mutex,这可能与它的存在有关。似乎合理的是,退化的STL实现甚至可能在词法流操作中遇到上述问题。某些容器具有奇怪的性能特征。我对向量没有问题,但我真的不知道istream_iterator在内部使用什么。过去,我发现std::list::size通过行为不当的算法进行调用,例如使用GCC对列表进行完整遍历。不知道新版本是不是没那么疯狂了。通常笨的SECURE_CRT笨应该由笨来照顾。我想知道这是否是Microsoft认为我们愿意花时间做的事情?随着容器的增长,List.Add和vector::push_back会不时地重新分配内存。C++向量按值存储子向量,因此所有数据(在您的情况下看起来很大)都被一次又一次地复制。相反,C#列表通过引用存储子列表,因此在重新分配期间不会复制子列表的数据。典型的矢量实现在重新分配期间将其容量加倍。因此,如果您有100万行,则子向量将被复制log(2,1000000)≈10次。C++11中引入的移动语义应该消除这种影响。在此之前,尝试vector>>、list>,或者,如果您提前知道未来的大小,请使用vector::reserve()以避免重新分配。尚未测试代码,但它通常加载多少?考虑当每个向量达到其容量时会发生什么。矢量增长效率低下-我相信O(n)。C#的列表没有这种行为。考虑使用std::deque、std::list或其他具有更好增长行为的容器。有关详细信息,请参阅本文。如果元素数量非常多,每次向后推vector时都会因重新分配和复制而受到惩罚。尝试在C++中使用不同的容器。由于您的函数本身并不慢1,因此您的程序运行缓慢的原因一定是在填充pathLookupVectors时某些使用此函数乘积的代码速度变慢了。我认为在您的程序上运行探查器是最好的方法,但您也可以查看您的代码并找到依赖于pathLookupVectors的每一段代码,并考虑这是否是您要寻找的瓶颈。1.以您最新的编辑为基础。以上就是C#学习教程:C++为什么这么慢?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: