附加调试器的 C++/opengl 应用程序运行更流畅

Posted

技术标签:

【中文标题】附加调试器的 C++/opengl 应用程序运行更流畅【英文标题】:C++/opengl application running smoother with debugger attached 【发布时间】:2012-01-13 22:30:02 【问题描述】:

您是否遇到过从 Visual Studio 执行 C++ opengl 应用程序时运行得更快、更流畅的情况?当正常执行时,没有调试器,我得到较低的帧率,50 而不是 80,以及奇怪的滞后,其中 fps 每 20-30 帧下降到大约 25 帧/秒。有没有办法解决这个问题?

编辑: 我们还使用了很多显示列表(使用 glNewList 创建)。并且增加显示列表的数量似乎会增加滞后。

编辑: 该问题似乎是由页面错误引起的。使用 SetProcessWorkingSetSizeEx() 调整流程工作集没有帮助。

编辑: 对于一些大型模型,使用 procexp-utility 的 GPU 内存使用情况很容易发现问题。当每帧有很多 glCallList 调用时,内存使用非常不稳定。没有添加新的几何体,没有加载纹理,但 gpu-memory-allocation 波动 +-20 MB。一段时间后它变得更糟,并且可能一次分配大约 150Mb。

【问题讨论】:

您是在全屏运行,还是在调试器中不全屏运行?这将表明启用了垂直同步。 不是全屏,而是最大化。在这两种情况下都应禁用垂直同步。有时我的 fps 速率超过 100,但仍然滞后。 您应该使用 Process Explorer 之类的工具来查看在这两种情况下加载了哪些 DLL,以及是否从不同路径加载了同一个 DLL 所有 dll 文件似乎都匹配。有几个 dll 仅在从 Visual Studio 执行时才存在:audiodev.dll、WMVCORE.DLL、wpdshext.dll、GdiPlus.dll、WMASF.DLL。理论上这些应该不会影响opengl渲染的流畅度。 opengl.org/resources/faq/technical/displaylist.htm 这个常见问题解答表明内存抖动通常是显示列表的性能限制。也许您的应用程序从父进程继承了一些内存优先级或缓存大小。尝试以管理员身份或从 Visual Studio 命令行启动您的应用程序,看看是否有任何不同。还可以尝试查看任务管理器中的页面错误等内存参数,看看是否有任何显着差异。 【参考方案1】:

我相信您所看到的是调试器锁定了一些页面,因此无法将它们交换为可供调试器立即访问。这在进程切换时为操作系统带来了一些注意事项,通常不建议这样做。

你可能不喜欢听我这么说,但没有好的方法可以解决这个问题,即使你这样做了。

使用 VBO,或者至少是顶点数组,这些可以在驱动程序中得到更好的优化(让我们面对现实吧 - 显示列表已经过时了)。显示列表可以轻松包装以生成顶点缓冲区,因此只需修改少量旧代码。此外,您可以使用旨在避免驱动程序中出现页面错误的“无绑定图形”(GL_EXT_direct_state_access)。

【讨论】:

【参考方案2】:

你有没有 nVidia 显卡?当附加到调试器时,nVidia OpenGL 似乎使用了不同的实现。对我来说,非调试器版本在某些情况下以高达 1 MB/秒的速度泄漏内存,在某些情况下,我绘制到前端缓冲区并且不调用 glClear 每帧。调试器版本绝对没问题。

我不知道为什么它需要为没有变化的场景分配和(有时)释放这么多内存。

而且我没有使用显示列表。

【讨论】:

谢谢!我确认 nVidia OpenGL 驱动程序在某些条件下在 Release 和 Debug 版本之间有很大的性能差异 (x100)。我有一个使用蒙皮动画的 OpenGL 项目,它可以在两台不同的基于 nVidia 的 Windows 机器上以 0.4FPS 的速度运行。然而,该项目将在 AMD 机器或我的 Macbook 的 nVidia 硬件上以大约 30FPS 的速度运行。然而,在 Windows/nVidia 机器上,如果我在 Unity 的 Profiler 窗口打开的情况下运行项目,它会从 .4FPS 加速到 30FPS,如果我通过 OpenGL 调试工具运行独立的,它也会以 30FPS 运行。 @RiazRizvi 我目前遇到了类似的问题,想知道您使用的是哪个 OpenGL 调试工具? 这是不久前的事了,但我认为这是免费的opengl.org/sdk/tools/gDEBugger。我的结论是,为调试而构建的 Window 的 OpenGL DLL 在皮肤动画方面比发布版本执行得更好,因为通过调试工具运行项目会导致加载 OpenGL 驱动程序的调试版本。虽然这是两年前的事了 - 不确定是否仍然如此。【参考方案3】:

这可能是线程或进程的优先级。 Visual Studio 可能会以稍高的优先级启动您的进程,以确保调试器能够响应。尝试在您的应用代码中使用SetPriorityClass():

SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);

“高于正常”课程只是将其推到“普通”课程的其他所有内容之前。正如文档所说,不要给超高优先级打耳光,否则你会搞砸系统的调度程序。

在以 60 fps 运行的应用程序中,您只有 16 毫秒来绘制帧(在 80 fps 时更短!) - 如果需要更长时间,您会丢弃帧,这可能会导致帧率小幅下降。如果您的应用程序与其他应用程序具有相同的优先级,那么另一个应用程序可能会暂时为某些任务占用 CPU,并且您会丢失几帧或至少错过当前帧的 16 毫秒窗口。这个想法是稍微提高优先级意味着 Windows 会更频繁地返回您的应用程序,因此它不会丢掉那么多帧。

【讨论】:

看起来很合理,但你的答案与调试/发布版本之间的性能差异有什么关系? 没有帮助。与 Visual Studio 分开执行时,FPS 速率仍然“不稳定”。顺便说一句,我一直在使用 Release 版本,但从 Visual Studio 或正常执行。 更改 SetProcessPriorityBoost 也无济于事。

以上是关于附加调试器的 C++/opengl 应用程序运行更流畅的主要内容,如果未能解决你的问题,请参考以下文章

未在附加调试器的情况下运行时程序中断

是否可以在 eclipse CDT 中将调试会话附加到正在运行的程序

无法将着色器链接到 OpenGL 中的程序对象,无法调试

为啥我无法将调试器附加到在此订阅中运行的应用服务?

OpenGL - 启用调试 - 运行时 System.AccessViolationException

如何在运行时确定您的 C++ 应用程序何时附加了 Visual Studio 调试器?