使用 vsync (OpenGL) 时 CPU 利用率为 100%
Posted
技术标签:
【中文标题】使用 vsync (OpenGL) 时 CPU 利用率为 100%【英文标题】:100% CPU utilization when using vsync (OpenGL) 【发布时间】:2014-03-22 10:18:24 【问题描述】:这是一个非常简单的测试程序。当 vsync 被禁用时,该程序以 100FPS 运行,几乎占用了 0% 的 CPU。当我启用 vsync 时,我得到 60FPS 和 25%(100% 的一个核心在 4 核系统上)的 CPU 利用率。这是使用 Nvidia GPU。在线搜索导致我建议在 Nvidia 控制面板中禁用“多线程优化”。这确实降低了 CPU 利用率,但仅降低了 10%。此外,如果我在 SwapBuffers 之后删除睡眠调用,即使禁用了多线程优化,我也会再次获得 25% 的利用率。任何人都可以对此有所了解吗?难道我做错了什么? Nvidia 的 OpenGL 实现是否存在无可救药的缺陷?
#include <GLFW/glfw3.h>
#include <thread>
#include <cstdlib>
#include <cstdio>
int main(int argc, char *argv[])
if(!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Vsync Test", nullptr, nullptr);
if(!window)
glfwTerminate();
exit(EXIT_FAILURE);
glfwMakeContextCurrent(window);
#ifdef USE_VSYNC
glfwSwapInterval(1);
#else
glfwSwapInterval(0);
#endif
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
double lastTime = glfwGetTime();
double nbFrames = 0;
while(!glfwWindowShouldClose(window))
double currentTime = glfwGetTime();
nbFrames++;
if (currentTime - lastTime >= 1.0)
char cbuffer[50];
snprintf(cbuffer, sizeof(cbuffer), "OpenGL Vsync Test [%.1f fps, %.3f ms]", nbFrames, 1000.0 / nbFrames);
glfwSetWindowTitle(window, cbuffer);
nbFrames = 0;
lastTime++;
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
//limit to 100FPS for when vsync is disabled
std::chrono::milliseconds dura(10);
std::this_thread::sleep_for(dura);
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
【问题讨论】:
【参考方案1】:我不愿给出这个答案,因为我真的不知道“答案”,但希望我能对此有所了解。
我也有一个 nVidia GPU,我也注意到了同样的事情。我的猜测是驱动程序本质上是在旋转等待:
while(NotTimeToSwapYet())
(或任何花哨的驱动程序版本)。
使用process hacker从nvoglv32.dll
的线程中采样一些堆栈跟踪,大约99%的时间在列表顶部的东西是
KeAcquireSpinLockAtDpcLevel()
通常在
之类的东西的下游KiCheckForKernelApcDelivery()
和EngUnlockDirectDrawSurface()
我在 Windows 驱动程序编程方面还不够精通,无法得出结论,但这当然也不能告诉我我错了。
而且看起来你也没有做任何明显错误的事情。根据我的经验,非独占 Windows 应用程序中的交换时间非常痛苦:涉及大量的反复试验,并且不同系统之间存在很多可变性。据我所知,没有一种“正确”的方法可以一直有效(请有人告诉我我错了!)。
过去,我一直能够依靠 vsync 来保持较低的 CPU 使用率(即使它确实使事情的响应速度降低了一些),但现在似乎不再如此了。我最近从 DirectX 切换到了 OpenGL,所以我无法告诉你这是否是 nVidia 驱动程序的最新变化,或者他们是否只是在 vsync 方面对 DX 和 OpenGL 进行了不同的处理。
【讨论】:
不是很明确,但绝对有帮助。我确实找到了这篇文章 (forum.openscenegraph.org/viewtopic.php?t=3653#18283),有人从驱动程序开发人员那里得到了一些反馈。根据他们的反应,司机让步了。为了自己测试这一点,我加载了我选择的 3D 渲染套件,并在运行 OpenGL 程序的同时将我的所有四个 CPU 内核最大化。它的 CPU 利用率从 25% 下降到 0%。似乎虽然它最大化了一个核心,但它并没有实际上占用它。 @Chis_F 谢谢,很高兴知道(而且有点令人鼓舞)。但我对高 CPU 使用率的主要担忧是它会阻止笔记本电脑进入低功耗模式。我不确定“人造”的用法是否会有所不同。也许移动驱动程序的设置有所不同——我没有要测试的。 这当然是一个问题。就功耗而言,产量不会有任何影响,但也许他们的移动 GPU 的驱动程序运行方式不同。 我注意到 Blender 在空闲时几乎不使用 CPU,即使我强制打开 vsync 也是如此。据我所知,它使用 OpenGL。我想知道他们采取了哪些不同的措施来管理这一点。 Blender 似乎只有在某些情况发生变化时才会渲染帧。我用 Fraps 对其进行了测试。我会在可能的情况下做类似的事情并解决问题。在 3d 编辑器中很好,但在制作游戏或演示时不是一个选项。我正在使用 winpai,如果我使用 GetMessage 而不是 PeekMessage,那么应用程序将在每一帧之前等待用户输入。所以只有当用户移动鼠标或其他东西时才会渲染帧。【参考方案2】:交换缓冲区后,调用DwmFlush();
,它将不再使用 100% cpu!
【讨论】:
以上是关于使用 vsync (OpenGL) 时 CPU 利用率为 100%的主要内容,如果未能解决你的问题,请参考以下文章