OpenGL 程序中奇怪的 CPU 使用率

发布于 2024-11-04 09:03:28 字数 1215 浏览 1 评论 0原文

在我自己构建的 MFC 程序中,我在 CPU 使用方面遇到了一些奇怪的问题。

我加载了大约 360k 点的点云,一切正常(我使用 VBO 缓冲区,根据我的理解,这是执行此操作的方法?)。我可以随意移动它,并且没有发现任何不利影响(CPU 使用率非常低,GPU 完成所有工作)。但在某些角度和缩放值下,我看到我的一个处理器上的 CPU 峰值!然后我可以改变角度或稍微缩放,它会再次下降到 0 左右。这种情况在大窗口中比在小窗口中更有可能发生。

我测量了程序的 FPS,它始终保持在 65,但是当 CPU 峰值达到时,它通常会下降大约 10 个单位到 55。我还测量了 SwapBuffers 所花费的时间,在正常操作期间大约为 0-1 毫秒。一旦 CPU 达到峰值,它就会上升到大约 20 毫秒,因此很明显,在该函数中突然变得非常难以计算(我猜是对于 GPU?)。这个东西不在 DrawScene 函数中(这是一个人们期望在糟糕的实现中消耗 CPU 的函数),所以我有点不知所措。

我知道这不是由于可见点的数量,因为这可以很容易地发生在数据的一个子部分上,就像在整个云上一样。我尝试移动它,看看它是否与深度缓冲区、剪辑或类似的东西有关,但似乎完全是随机的,什么角度会产生问题。不过,这似乎确实有点可重复;将模型移动到曾经滞后的位置,再次移动到那里时也会出现滞后。

我对 OpenGL 很陌生,所以我犯了一些完全明显的错误并非不可能。

这就是渲染循环的样子(它通过周期为 1 毫秒的计时器事件在 MFC 应用程序中运行):

    // Clear color and depth buffer bits
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Draw OpenGL scene
    OGLDrawScene();

    unsigned int time1 = timeGetTime();

    // Swap buffers
    SwapBuffers(hdc);

    // Calculate execution time for SwapBuffers
    m_time = timeGetTime() - time1;

    // Calculate FPS
    ++m_cnt;
    if (timeGetTime() - m_lastTime > 1000)
    {
        m_fps = m_cnt;
        m_cnt = 0;
        m_lastTime = timeGetTime();
    }

In an MFC-program I built myself I have some weird problems with the CPU usage.

I load a point cloud of around 360k points and everything works fine (I use VBO buffers which is the way to do it from what I understand?). I can move it around as I please and notice no adverse effects (CPU usage is very low, GPU does all the work). But then at certain angles and zoom values I see the CPU spike on one of my processors! I can then change the angle or zoom a little and it will go down to around 0 again. This is more likely to happen in a large window than a small one.

I measure the FPS of the program and it's constantly at 65, but when the CPU spike hits it typically goes down around 10 units to 55. I also measure the time SwapBuffers take and during normal operation it's around 0-1 ms. Once the CPU spike hits it goes up to around 20 ms, so it's clear something suddenly gets very hard to calculate in that function (for the GPU I guess?). This something is not in the DrawScene function (which is the function one would expect to eat CPU in a poor implementation), so I'm at a bit of a loss.

I know it's not due to the number of points visible because this can just as easily happen on just a sub-section of the data as on the whole cloud. I've tried to move it around and see if it's related to the depth buffer, clipping or similar but it seems entirely random what angles create the problem. It does seem somewhat repeatable though; moving the model to a position that was laggy once will be laggy when moved there again.

I'm very new at OpenGL so it's not impossible I've made some totally obvious error.

This is what the render loop looks like (it's run in an MFC app via a timer event with 1 ms period):

    // Clear color and depth buffer bits
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Draw OpenGL scene
    OGLDrawScene();

    unsigned int time1 = timeGetTime();

    // Swap buffers
    SwapBuffers(hdc);

    // Calculate execution time for SwapBuffers
    m_time = timeGetTime() - time1;

    // Calculate FPS
    ++m_cnt;
    if (timeGetTime() - m_lastTime > 1000)
    {
        m_fps = m_cnt;
        m_cnt = 0;
        m_lastTime = timeGetTime();
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜唯美灬不弃 2024-11-11 09:03:28

我注意到(至少不久前),ATI 驱动程序倾向于过于激进地旋转等待,而 NVidia 驱动程序倾向于中断驱动。从技术上讲,假设您没有更好的事情可做,那么旋转等待会更快。不幸的是,今天您可能在另一个线程上有更好的事情要做。

我认为OP的显示驱动程序可能确实正在等待旋转。

I've noticed that (at least a while back), ATI drivers tend to like to spin-wait a little too aggressively, while NVidia drivers tend to be interrupt driven. Technically spin-waiting is faster, assuming you have nothing better to do. Unfortunately, today you probably do have something better to do on another thread.

I think the OP's display drivers may indeed be spin-waiting.

倦话 2024-11-11 09:03:28

好的,所以我想我已经弄清楚这是如何发生的。

首先,即使在使用 timeBeginPeriod(1) 时,至少在我的计算机上,WM_TIMER 消息的生成频率似乎最多不会超过每 15 毫秒一次。这导致了我看到的标准 65 fps。

一旦场景渲染时间超过 15 毫秒,SwapBuffers 就会成为限制因素。 SwapBuffers 似乎处于忙等待状态,导致发生这种情况时一个核心上的 CPU 使用率达到 100%。这不是在某些摄像机角度发生的事情,而是根据当时屏幕上显示的点数而流畅地改变 fps 的结果。每当渲染时间超过 15 毫秒时,它就会出现峰值,并开始在 SwapBuffers 处等待。

同样,有人知道像“glReadyToSwap”这样的函数或类似的函数吗?指示缓冲区是否准备好交换的函数?这样我就可以选择另一种更高分辨率的渲染方法(例如 1 毫秒),然后每毫秒检查缓冲区是否准备好交换,如果它们不只是等待另一个毫秒,以免忙等待。

Ok, so I think I have figured out how this can happen.

To begin with the WM_TIMER messages doesn't seem to be generated more often than every 15 ms at best, even when using timeBeginPeriod(1), at least on my computer. This resulted in the standard 65 fps I was seeing.

As soon as the scene took more than 15 ms to render, SwapBuffers would be the limiting factor instead. SwapBuffers seem to busy-wait, which resulted in 100% CPU usage on one core when this happened. This is not something that occurred at certain camera angles, but is a result of a fluidly changing fps depending on how many points were shown on the screen at the time. It just appeared to spike whenever rendering happened to hit a time over 15 ms and started to wait at SwapBuffers instead.

On a similar note, does anyone know of a function like "glReadyToSwap" or something like that? A function that indicates if the buffers are ready to be swapped? That way I could choose another method for rendering with a higher resolution (1 ms for example) and then each ms check if the buffers are ready to swap, if they aren't just wait another ms, so as to not busy-wait.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文