如何在运行SDL程序时降低CPU使用率?

10

我使用SDL制作了一个非常基础的窗口,想让它一直运行,直到我按下窗口上的X。

#include "SDL.h"
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

int main(int argc, char **argv)
{
    SDL_Init( SDL_INIT_VIDEO );
    SDL_Surface* screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, 0, 
                                            SDL_HWSURFACE | SDL_DOUBLEBUF );
    SDL_WM_SetCaption( "SDL Test", 0 ); 
    SDL_Event event;
    bool quit = false;
    while (quit != false)
    {
        if (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                quit = true;
            }
        }
        SDL_Delay(80);
    }
    SDL_Quit();
    return 0;
}

我尝试在while循环的结尾处添加SDL_Delay(),它的效果还不错。

然而,似乎80毫秒是我能够使用的最大值,以保持程序的平稳运行,即使这样,CPU的使用率也大约为15-20%。

这是最好的方法吗?我是否必须接受它已经在这个点上占用了这么多的CPU呢?

4个回答

19

我知道这篇文章比较旧,但我刚刚在启动一个小型演示项目时遇到了SDL的这个问题。就像用户“thebuzzsaw”所指出的那样,最好的解决方案是使用SDL_WaitEvent来减少事件循环的CPU使用率。

以下是示例中的代码片段,供需要快速解决此问题的任何人参考。希望它有所帮助!

#include "SDL.h"
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

int main(int argc, char **argv)
{
    SDL_Init( SDL_INIT_VIDEO );
    SDL_Surface* screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, 0, 
                                            SDL_HWSURFACE | SDL_DOUBLEBUF );
    SDL_WM_SetCaption( "SDL Test", 0 ); 
    SDL_Event event;
    bool quit = false;
    while (quit == false)
    {
        if (SDL_WaitEvent(&event) != 0) {
            switch (event.type) {
            case SDL_QUIT:
            quit = true;
            break;
            }
        }
    }
    SDL_Quit();
    return 0;
}

14

我会尝试完全阻塞函数(例如SDL_WaitEvent)。 我有一个在Qt中使用OpenGL的应用程序,注意到CPU使用率在0%和1%之间。 在“使用”期间(移动相机和/或导致动画),它可能会飙升至4%。

我正在开发自己的窗口工具包。 我发现当我使用阻塞事件循环时,可以实现类似的CPU使用率。 这将使您所依赖的任何计时器变得复杂,但使用这种新方法实现计时器并不是非常困难。


7
我刚刚找到了减少游戏 CPU 使用率的方法,将其从 50% 减少至小于 10%。 你的程序更加简单,仅仅使用 SDL_Delay() 即可。
我所做的是: 在加载图像时使用 SDL_DisplayFormat(),这样 blitting 会更快。这将 CPU 使用率降至约 30%。
所以我发现游戏背景的 blitting(大型一体化 PNG 文件)消耗了我的 CPU。我在互联网上搜索了解决方案,但所有结果都相同——只需使用 SDL_Delay()。最后,我发现问题非常简单——SDL_DisplayFormat() 将我的 24 位图像转换为 32 位。因此,我将显示器 BPP 设置为 24,CPU 使用率下降至 ~20%。将其降至 16 位对我来说解决了问题,CPU 使用率现在低于 10%。
当然,这意味着损失颜色细节,但由于我的游戏是一个简单的 2D 游戏,图像不是很详细,这是可以接受的。

3
为了真正理解这个问题,你需要了解线程。在一个多线程应用程序中,程序会一直运行直到等待某些东西,然后告诉操作系统可以运行其他任务。本质上,你使用的是SDL_Delay命令来实现这个功能。如果没有任何延迟,我猜测你的程序将以接近100%的容量运行。
在延迟语句中放入的时间只有在其他命令花费了相当长的时间时才会有所影响。通常情况下,我会把延迟设置为与测试轮询命令所需时间相似的时间,但不超过10毫秒。这样做的结果是操作系统至少会等待那么长的时间,从而允许后台运行其他应用程序。
至于如何改进这个问题,看起来你能做的并不多。但请注意,如果有其他占用大量CPU资源的进程正在运行,你的程序的份额将会减少。

在SDL中只使用一个线程是正常的吗?你有SDL_PushEventSDL_AddTimer,那为什么不使用多线程呢? - dyp
使用10毫秒会使CPU使用率接近60%。我很好奇GTK是如何处理的,因为使用它创建类似的虚拟窗口根本不会影响CPU使用率。 - BudwiseЯ
即使程序没有线程,操作系统也有。操作系统负责测量CPU使用率,因此它会报告比实际更高的值。 - PearsonArtPhoto
每隔1000/x毫秒从消息循环中轮询一段时间只是浪费(CPU)时间。在大多数(几乎所有)情况下,固定休眠一段时间(SDL_Delay)不是一个好的解决方案--同步还有什么用?我能想到的唯一情况是你不想无限期地睡眠是定期任务。你可以使用另一个线程甚至SDL_AddTimer来完成这个任务。 - dyp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接