有意地只限制一个线程的CPU使用

Throttle CPU usage of only one thread intentionally

本文关键字:一个 线程 使用 CPU      更新时间:2023-10-16

关于SO还有其他几个类似的问题,但没有一个有令人满意的/相关的答案。

我有一个单线程c++程序,它基本上是这样做的:

while(true) {
    //do things which are cpu bound
}

问题是,当我运行这个程序时,它通常是我的整个计算机上唯一一个正在进行活动工作的进程。

由于没有其他事情可调度,操作系统自然会大量调度这个程序,我的CPU使用率飙升到屋顶,我不想要。当然,我的风扇也开始嗡嗡作响,这特别烦人。

我解决这个问题的方法是在循环中添加sleep(100)(这对我来说是正确的),但是当它工作时,它惹恼了我,它不是技术上正确的解决方案。

这是因为如果我想睡眠一个非常准确的时间,我有很多其他进程在我的计算机上运行,这将不是一个很好的解决方案,因为sleep是不准确的,它也不允许其他进程使用CPU,而我的程序仍在调度-但这不是我真正的问题。

在不使用sleep的情况下减少CPU使用的正确解决方案是什么,假设这是唯一正在积极运行的程序?

这里有三种情况需要考虑。

轮询循环

对于轮询循环,"正确"的解决方案更像是:

while(true) {
    wait_for_something();
    //do things which are cpu bound
}

问题是决定你应该等待什么(时间,按键,垂直同步信号,收到的数据包,....?);然后试着去找一些你真正需要的东西。

CPU绑定终端条件

对于这种情况,"正确"的解决方案更像是:

do {
    //do things which are cpu bound
} while (running);
在这种情况下,你可以(应该)将线程的优先级设置为"非常低优先级",这样它就不会干扰其他线程。当只有低优先级线程运行时,操作系统可以决定是否(或不)降低CPU功率/速度;但这不是你的决定(这是操作系统的决定,希望有一些用户/管理员的电源管理控制)。

CPU Bound Without Terminal Condition

这种情况极其罕见(罕见到我想不出一个合理的场景,我甚至不确定它是否存在于实践中)。大多数情况下,如果你认为你的情况是"CPU绑定没有终端条件",你可能错了,它可能是其他情况之一。

如果它实际上是"CPU绑定没有终端条件",那么它基本上就像"CPU绑定与终端条件"一样,除了没有条件(你仍然想要一个低优先级的线程,当只有低优先级的线程运行时电源管理仍然不是你的决定)。

这在程序内部是比较困难的。可以说,大多数有效的方法(至少是我所知道的)都是从外部强加的。

在Linux上,一种可能是cpulimit,它监视CPU使用情况,并在必要时周期性地暂停您的程序,以将其CPU使用降低到您指定的水平。

Linux确实有setrlimit和cgroups之类的东西来控制进程的资源使用情况,但是这些都不适用于您指定的场景(例如,限制CPU使用,即使系统处于空闲状态)。传统上,您能够设置的限制是进程的 CPU使用率,而不是使用率,所以像setrlimitrctl这样的东西有点类似,但不能提供您想要的东西。

如果你使用的是Windows,你可以通过Windows Job Object来实现。您创建一个作业对象,然后使用JOBOBJECT_CPU_RATE_CONTROL_INFORMATION使用SetInformationJobObject在该作业对象上设置限制。

在处理数字运算问题时,我经常遇到使用perl脚本的类似情况。在运行这些脚本时,我将机器置于省电模式(通过设置最大cpu阈值限制)。帮助。

相关文章: