C++ OSX Simple OpenGL消耗了200%的CPU

C++ OSX Simple OpenGL消耗了200%的CPU,c++,macos,opengl,cpu-usage,glfw,C++,Macos,Opengl,Cpu Usage,Glfw,在OSX上,我有一个非常简单的游戏循环,它运行一些OpenGL代码,这些代码只是一些矩阵变换(几乎所有矩阵变换都是在GPU上计算的)和一个智能管理绑定的纹理,因此它不会绑定每一帧。纹理只是以中等速度旋转。仅此而已。我以每秒60滴答的速度滴答作响。窗口的大小是1300 x 650(出于某些原因,它在全屏显示时确实更好,但我正在windowed中进行测试)。我得到大约350-400 fps。CPU的使用率始终在200%左右(约占所有设备的50%;是一个四核i5处理器)。而且,奇怪的是,打开垂直同步根

在OSX上,我有一个非常简单的游戏循环,它运行一些OpenGL代码,这些代码只是一些矩阵变换(几乎所有矩阵变换都是在GPU上计算的)和一个智能管理绑定的纹理,因此它不会绑定每一帧。纹理只是以中等速度旋转。仅此而已。我以每秒60滴答的速度滴答作响。窗口的大小是1300 x 650(出于某些原因,它在全屏显示时确实更好,但我正在windowed中进行测试)。我得到大约350-400 fps。CPU的使用率始终在200%左右(约占所有设备的50%;是一个四核i5处理器)。而且,奇怪的是,打开垂直同步根本不起任何作用。正如预期的那样,它只是将FPS锁定在60,CPU使用率保持在200%左右

以下是计算机的统计数据(如有必要):

  • iMac(27英寸,2009年底)
  • 处理器:2.66 GHz四核Intel Core i5(涡轮增压至3.2 GHz)
  • 内存:16 GB 1333 MHz DDR3
  • 图形:ATI Radeon HD 4850 512 MB
下面是游戏循环:

float time = 0.0f;
float currentTime = 0.0f;

float tickTimer = 0.0f;
float frameTimer = 0.0f;

int frames = 0;

float rate = 1.0f / 60.0f;
float deltaTime = rate;

const milliseconds sleepDuration(1);

glfwMakeContextCurrent(nullptr);

thread tickThread([&](){
    while(!glfwWindowShouldClose(window)) {
        while(tickTimer >= rate) {
            tickTimer -= rate;
            time += rate;

            mtx.lock();
            tickCallback(deltaTime);
            mtx.unlock();
        }
    }
});

thread renderThread([&](){
    glfwMakeContextCurrent(window);

    while(!glfwWindowShouldClose(window)) {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        mtx.lock();
        renderCallback();
        mtx.unlock();

        this_thread::sleep_for(sleepDuration);

        frames++;

        if (frameTimer >= 1) {
            frameTimer = 0;
            fps = frames;
            frames = 0;
        }

        glfwSwapBuffers(window);
    }
});

while(!glfwWindowShouldClose(window)) {
    const float newTime = static_cast<float>(glfwGetTime());
    deltaTime = newTime - currentTime;
    currentTime = newTime;

    tickTimer += deltaTime;

    frameTimer += deltaTime;

    glfwPollEvents();
}
浮动时间=0.0f;
浮动电流时间=0.0f;
浮动计时器=0.0f;
浮动帧定时器=0.0f;
int帧=0;
浮动率=1.0f/60.0f;
浮动时间=速率;
常数毫秒睡眠持续时间(1);
glfwMakeContextCurrent(nullptr);
线程([&](){
而(!glfwWindowShouldClose(窗口)){
while(计时>=速率){
计时器-=速率;
时间+=速率;
mtx.lock();
时间间隔(deltaTime);
mtx.unlock();
}
}
});
线程渲染读取([&](){
glfwMakeContextCurrent(窗口);
而(!glfwWindowShouldClose(窗口)){
glClear(GL_颜色_缓冲_位| GL_深度_缓冲_位);
mtx.lock();
renderCallback();
mtx.unlock();
此线程::sleep_for(sleepDuration);
frames++;
如果(帧计时器>=1){
帧定时器=0;
fps=帧;
帧=0;
}
glfwSwapBuffers(窗口);
}
});
而(!glfwWindowShouldClose(窗口)){
const float newTime=静态_cast(glfwGetTime());
deltaTime=新时间-当前时间;
当前时间=新时间;
tickTimer+=deltaTime;
帧定时器+=延迟时间;
glfwPollEvents();
}
在阅读了其他一些类似的问题后,似乎循环运行得太快,完全没有限制,因此消耗的CPU远远超过了需要。为了测试这个假设,我将
sleepDuration
设置为大约100毫秒,这应该足以让CPU自我冷却。没有。使用率仅下降到平均180%左右。我试着在循环的滴答声部分加入一个
this\u thread::sleep\u for(sleepDuration)
,它将使用率降低到了100%左右,这很重要,但对于如此少量的代码来说仍然是非常重要的。Re Logic的Terraria在这台计算机上的最高运行速度约为40%。我尝试过切割多线程,这样所有的东西都只是一个大循环,我尝试过异步,我甚至尝试过用最高级别的优化运行GCC,但什么都没有得到

我不知道这是否会有任何帮助,但我也经历了频繁但相当短的滞后峰值。它们似乎没有出现在FPS中,所以一定是滴答声。我希望is与我的程序消耗了几乎所有的计算机资源有关,而其他程序也必须努力争取它们的份额,但这只是我的理论。我真的不太了解这件事。那么,有人知道我做错了什么吗


编辑:我忘记添加的内容;在类似的问题中,我读到
glfwSwapBuffers()
似乎是罪魁祸首。事实并非如此。当我删除它时,CPU使用率确实下降到了约140%(仍然是一个荒谬的数字),FPS飙升到约6200,这是有道理的,但我不明白为什么CPU如此高。它必须在滴答声中(这只是计算旋转矩阵,仅此而已)。

看看
滴答声线程
滴答声定时器
小于
速率
时会做什么。。。如何避免这种情况?这里有3个线程,每个线程运行一个循环。其中两个线程一直在忙着旋转,第三个线程是GL线程,这应该是您最不关心的,因为它会被GL减慢。我不明白你怎么会期望这段代码至少不超过两个内核。@derhass就像我说的,我真的不太了解这一点,也没有任何头脑。我明白你和德米特里在说什么。由于某种原因,我没有想到当Dmitri说,
tickTimer
小于
rate
时会发生什么(当然,重申一下,并消耗更多CPU)。我总是设法让自己看起来很傻,所以。。。谢谢你!非常感谢如果您想限制线程循环运行的频率,请检查每个循环过程结束时的时间,并将其与上一次进行比较。然后找出循环过程之间的期望间隔和循环迭代所花费的时间之间的差异,并休眠那么长的时间(但要确保它小于期望间隔)。正如derhass所说,没有理由不让这段代码最大化至少两个核心。作为旁注,您有多个线程在没有同步的情况下读取和写入变量(tickTimer和frameTimer)。这被称为数据竞争,是C++中的未定义行为。你应该在操作中订购一个C++并发拷贝,以了解更多关于C++中的多线程的内容。如何避免这种情况?这里有3个线程,每个线程运行一个循环。其中两个线程一直在忙着旋转,第三个线程是GL线程,这应该是您最不关心的,因为它会被GL减慢。我不知道你会怎么想