The solution depends on what you want to do. Here are a few options:
降低进程优先级
您可以nice
子进程。这样,虽然它们仍会占用100%的CPU,但当您启动其他应用程序时,操作系统会优先考虑其他应用程序。如果您想让一个工作密集型计算在笔记本电脑的后台运行,并且不关心CPU风扇一直运转,那么使用psutils
设置nice值就是您的解决方案。此脚本是一个测试脚本,会在所有核心上运行足够长的时间,以便您了解其行为。
from multiprocessing import Pool, cpu_count
import math
import psutil
import os
def f(i):
return math.sqrt(i)
def limit_cpu():
"is called at every process start"
p = psutil.Process(os.getpid())
p.nice(psutil.BELOW_NORMAL_PRIORITY_CLASS)
if __name__ == '__main__':
pool = Pool(None, limit_cpu)
for p in pool.imap(f, range(10**8)):
pass
这个技巧在于
limit_cpu
在每个进程开始时运行(参见
文档中的initializer
参数)。而 Unix 有从 -19(最高优先级)到 19(最低优先级)的级别,Windows 则有
几个不同的级别来给予优先级。
BELOW_NORMAL_PRIORITY_CLASS
可能最符合您的要求,还有一个
IDLE_PRIORITY_CLASS
,它告诉 Windows 只在系统空闲时运行您的进程。
您可以在任务管理器中切换到详细模式并右键单击进程来查看优先级:
![enter image description here](https://istack.dev59.com/K9QY4.webp)
进程数减少
虽然您已经拒绝了这个选项,但它仍然可能是一个不错的选择:假设您使用 pool = Pool(max(cpu_count()//2, 1))
将子进程数量限制为CPU核心数的一半,则操作系统最初会在一半的CPU核心上运行这些进程,而其他核心则保持空闲状态或只运行当前正在运行的其他应用程序。过了一段时间,操作系统会重新安排这些进程,并可能将它们移动到其他CPU核心等。无论是 Windows 还是基于 Unix 的系统都可以这样处理。
Windows:在4个核心上运行2个进程:
![](https://istack.dev59.com/HNKNA.webp)
OSX:在8个核心上运行4个进程:
![enter image description here](https://istack.dev59.com/rrRDD.webp)
你会发现两个操作系统都在核心之间平衡进程,虽然不是完全均匀的,所以你仍然会看到一些核心的百分比比其他核心高。
睡眠
如果你绝对想确保你的进程从不占用某个核心的100%(例如,如果你想防止CPU风扇加速),那么你可以在处理函数中运行sleep:
from time import sleep
def f(i):
sleep(0.01)
return math.sqrt(i)
这将使操作系统每次计算后调度你的进程
0.01
秒,并为其他应用程序腾出空间。如果没有其他应用程序,则CPU内核处于空闲状态,因此它永远不会达到100%。您需要尝试不同的睡眠时间,它也会因运行计算机而异。如果你想变得非常复杂,你可以根据
cpu_times()
的报告调整睡眠时间。