如何为适当的CPU利用率编写代码
How to code for proper CPU utilization?
请原谅我,这可能有点难以解释清楚。我试图了解如何编写一个程序,只使用它需要的CPU量。这解释起来有点混乱,所以我将使用一个真实的例子。
我制作了一款带有无限主游戏循环的《俄罗斯方块》游戏。我把它限制在每秒40帧。但是循环仍然每秒执行数千甚至数百万次。它只会在足够的时间将其限制在40帧/秒时渲染。因为我有一个4核CPU,当我运行游戏时,一切都很好,游戏运行良好。但是游戏进程的CPU使用率保持在25%。这是预期的,因为它是一个无限循环,并持续运行。
然后我在线读取,在主循环中添加1毫秒的延迟。这立即将使用率降低到1%左右或更少。这很好,但现在我故意在每个循环中等待1毫秒。这是有效的,因为我的主循环需要更少的时间来执行,并且1毫秒的延迟不会影响游戏。
但是如果我制作更大型的游戏呢?具有更长时间和更多处理器密集循环的游戏。如果我需要1毫秒的时间来平稳运行游戏怎么办?然后,如果我移除延迟,处理器将再次跳到25%。如果我添加延迟,游戏就会很慢,可能会有一些延迟。
在这种情况下理想的解决方案是什么?真正的游戏/应用程序如何编码来防止这个问题?
由于您在标记中列出了三种不同的语言,因此我将保持一般性,不提供代码示例。
一般来说,为了避免占用CPU, 永远不要在的每次迭代中都有一个不的循环:
- 做有用的工作
- 基于循环计数器的跳过
- 或调用阻塞调用,阻塞I/O或阻塞线程
wait()
。
sleep()
是阻塞调用的一个例子,但正如您所观察到的,在许多情况下,它有点像一个大杂牌。
:
while(true) {
if(some_condition) {
foo();
}
}
…是坏的。(我的一个朋友曾经用这样的代码使一个共享主机崩溃)
你需要找到一个调用你的显示API阻塞,直到垂直同步。我相信在DirectX, device.Present()
是一个这样的调用,如果设备设置得当。
在单线程游戏中,逻辑可能是:
while(game is active)
read user input
calculate next frame
blocking call to display API
因此,CPU得到休息,等待每次垂直同步。
通常至少有两个线程,一个处理渲染循环,另一个处理游戏状态。在这种情况下,呈现循环需要像以前一样等待垂直同步。游戏状态循环需要阻塞,直到渲染循环准备好。
渲染线程循环:
while(game is active)
notify()
prepare_frame(game_state)
blocking call to display API
游戏状态线程循环:
while(game is active)
read user input
update game_state
wait(display_loop_thread)
一定要理解thread wait/notify/join才能理解这个
这个模型允许你有其他线程也影响游戏状态。例如,另一个线程可能控制一个AI敌人。
另一种选择是使计算事件驱动,并在vsync后触发它们:
while(game is active)
calculate next frame
blocking call to display API
gameLogic.onFrame()
如果onFrame()需要比一帧更长的时间来完成,那么游戏的帧率将受到影响。这是否重要取决于游戏;解决方案超出了这个答案的范围——如果它对你很重要,那么可能是时候买一本关于电子游戏架构的书了。
不是睡1毫秒,而是睡X毫秒,其中X是用公式max(NextDrawingTime-CurrentTime, 0)
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 代码在main()中运行,但在函数中出现错误
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 编译包含字符串的代码时遇到问题
- 我在c++代码中生成了一个运行时#3异常
- 如何在linux终端中同时编译和运行c++代码
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 在Linux for Windows上编译C++代码时出错
- 我的字符计数代码计算错误.为什么
- 孤立代码块在结构中引发异常
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 此代码是否违反一个定义规则
- 为什么我的代码在输出中增加了93天
- 我的简单if-else语句是如何无法访问的代码
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 为什么在这个代码结束循环中没有得到结束
- 在c代码之间共享数据的最佳方式
- 如何为适当的CPU利用率编写代码