Visual C++ 函数突然变慢 170 毫秒(长 4 倍)

Posted

技术标签:

【中文标题】Visual C++ 函数突然变慢 170 毫秒(长 4 倍)【英文标题】:Visual C++ function suddenly 170 ms slower (4x longer) 【发布时间】:2010-06-15 18:25:14 【问题描述】:

在过去的几个月里,我一直在从事一个 Visual C++ 项目,以从相机中获取图像并进行处理。直到今天,更新数据大约需要 65 毫秒,但现在它突然显着增加。发生的情况是:我启动我的程序,并且在前 30 次左右的迭代中它按预期执行,然后循环时间突然从 65 毫秒增加到 250 毫秒。

奇怪的是,在对每个函数进行计时后,我发现导致速度变慢的代码部分相当基本,并且一个多月没有修改过。进入其中的数据在每次迭代时都保持不变且相同,但最初小于 1 毫秒的执行时间突然增加到 170 毫秒,而其余代码仍按预期执行(时间方面)。

基本上,我一遍又一遍地调用同一个函数,对于前 30 次调用,它按应有的方式执行,之后它会无缘无故地变慢。还可能值得注意的是,这是执行时间的突然变化,而不是逐渐增加。

这可能是什么原因造成的?该代码泄漏了一些内存(约 50 kb/s),但还不足以保证突然减速 4 倍。如果有人有任何想法,我很想听听他们的意见!

编辑:哇,真快!这是减慢速度的代码(减去一些数学)。我知道这是一个函数,如果增加行数,计算时间会迅速增加。这里的关键是,对于相同的数据,在 30 次迭代后速度会变慢。

void CameraManager::IntersectLines()


    // Two custom classes
    TMaths maths;
    TLine line1, line2;

    while(lines.size()>0)
    

        // Save the current line
        line1 = lines[0];

        // Then remove it from the list
        lines.erase(lines.begin());

        CvMat* aPoint;
        for (int i = 0; i<lines.size(); i++)
        

            line2 = lines[i];

            aPoint = cvCreateMat(1, 4, CV_32FC1);

            // Calculate the point of intersection
            maths.Intersect(line1.xyz, line2.xyz, line1.uvw, line2.uvw, aPoint);

            // Add the point to the list
            points.push_back(aPoint);
            

        

    

【问题讨论】:

代码在这里值一千字。典型的缓慢问题涉及 CPU 调度(是否有其他程序正在运行)、IO 绑定进程,尤其是在使用分页内存时等。但如果没有代码,它只是猜测。 修复泄漏。看看它是否能解决问题。处理器上的缓存通常相对较小。任何导致此缓存或二级缓存中的缓存未命中的因素都会导致处理器停顿。 听起来像是内存泄漏,没有代码你指望有人帮忙吗? 数据的密度或数量是否发生了变化?该函数可能未设置为处理更密集或更大的数据。贴出函数的代码,这样我们就可以停止猜测了。 你泄漏 3Mb/min ?我希望你的程序不应该运行太久,或者你正处于紧要关头。 【参考方案1】:

是否有可能在泄漏一定数量的内存后,您的计算机必须开始分页进/出内容?即使是简单的功能,这也肯定会减慢速度。

在不知道函数的作用的情况下,很难确切地说出是什么导致了问题。

编辑:正如问题 cmets 所建议的那样,泄漏一定量的内存也可能会开始将 CPU 缓存中的东西敲出,这也会减慢速度。要么修复内存泄漏,要么在这里发布代码供我们查看,都是个好主意。

编辑 2:您在该循环中调用了几个函数。除了简单的算术计算之外,他们还会做其他事情吗?

【讨论】:

是的,我也在考虑分页,问题是程序使用了大约 40 mb 的内存 (+50kb/s) 和超过 3.5 GB 的空闲空间,所以分页可能不是问题。 不正确。您可能会遇到内存碎片问题。请参阅我上面对最初问题的评论。操作系统堆管理器必须从某个地方获取您尝试分配的内存,这需要时间。如果你对堆进行分段,这肯定会减慢内存分配。为 Windows 搜索“低碎片堆”。 来自 MSDN:“从 LFH 中受益最多的应用程序是多线程应用程序,它们频繁分配内存并使用 16 KB 以下的各种分配大小。但是,并非所有应用程序都能从 LFH 中受益。要评估在您的应用程序中启用 LFH 的效果,请使用性能分析数据。” @Coleman:碎片化,当你只使用 40MB 时?值得怀疑 我读到他的评论是他正在分配 50kb/s,因此在这种情况下可能会出现碎片。【参考方案2】:

如果它泄漏了足够的内存来填满一个页面(50KB/s 可能就足够了),那么 Windows 将不得不切换页面来处理数据。发生这种情况时,程序会变得更加低效。

【讨论】:

【参考方案3】:

显然有些事情发生了变化。尝试将您的代码恢复到减速之前的状态。如果它再次变快,请关注代码更改。如果速度很慢,请在代码之外寻找问题。数据库、操作系统等。

【讨论】:

【参考方案4】:

如果您有内存泄漏,那么您的代码中肯定发生了一些不好的事情。首先解决这个问题,您就有可能发现问题或至少消除一个相当明显的嫌疑人。

正如其他人所提到的,如果您提供一些代码,尝试帮助您会更容易......

[编辑] 我猜你的cvCreateMat 函数分配了一些内存?它会在任何地方被释放吗?

【讨论】:

【参考方案5】:

需要擦除容器中的每一行吗?

    // Then remove it from the list
    lines.erase(lines.begin());

根据容器的不同,擦除元素(一次一个)可能会很慢,尤其是对于大型容器。我建议在计算过程中使用起始索引。在调用函数之前推进索引。索引和迭代器的更新比擦除元素更快。计算完成后,您可以删除或擦除整个容器(如果容器有,请参阅clear 方法)。 clear 方法可能比一次擦除一个元素更快。

【讨论】:

谢谢,现在它在退出之前持续了大约 60 次迭代 :) 这是一个好的开始。【参考方案6】:

分析代码,您就无需猜测答案了。

当然,无论如何,这可能会改变代码的性能,但它是最直接的方法,可以准确了解代码的运行情况...

(根据此问题的当前最佳答案:Profiling in Visual Studio 2008 PRO 您需要 VS 2008 的“团队”版本才能使用内置分析器,否则您需要使用外部分析器)

【讨论】:

【参考方案7】:

如果您想要任何有用的答案,您需要使您的问题更加具体。

【讨论】:

这真的应该写成评论,而不是答案。 @Jerry,您需要 50 名代表才能发表评论。有点不幸,我想。 @Mark:啊,我没注意到。我同意这很不幸,但我想这是元的问题,而不是这里......

以上是关于Visual C++ 函数突然变慢 170 毫秒(长 4 倍)的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio 2015 的 Web 应用程序响应时间变慢

C++ 'true' 和 'false' 关键字在 Visual C++ 6.0 中突然不是真或假

C++ 打印时间 毫秒级

Visual Studio 调试器在内联代码中变慢

用visual studio 2010编写C++突然输入中的很多错误不提示了

什么可能导致函数导入性能变慢?