【发布时间】:2021-12-07 18:59:11
【问题描述】:
我在 python 上运行了一个“令人尴尬的并行”问题,我想我可以使用 concurrent.futures 模块来并行化这个计算。我之前成功地做到了这一点,这是我第一次尝试在比我的笔记本电脑更强大的计算机上做到这一点。这台新机器有 32 核 / 64 线程,而我的笔记本电脑只有 2/4。
我正在使用来自concurrent.futures library 的ProcessPoolExecutor 对象。我将max_workers 参数设置为10,然后在一个循环中一个接一个地提交我所有的工作(其中可能有100 个)。模拟似乎有效,但即使经过一番激烈的谷歌搜索,也有一些我不明白的行为。我在 Ubuntu 上运行它,所以我使用 htop 命令来监控我的处理器。我看到的是:
- 创建了 10 个进程。
- 每个进程请求 > 100% 的 CPU 功率(例如,高达 600%)
- 还创建了一大堆进程。 (我认为这些是“任务”,而不是进程。当我按 SHIFT+H 时,它们就会消失。)
- 最令人担忧的是,所有处理器的假脱机似乎都达到了 100%。 (我说的是终端顶部的“均衡器条”:
我的问题是——如果我只派出 10 名工人,为什么我的所有处理器似乎都在以最大容量使用?我的工作理论是,我调用的 10 名工人是“保留的”,而其他处理器只是跳进来帮忙......如果其他人要运行其他东西并要求一些处理能力(但不包括我要求的 10 名工人),我的其他任务将退后并归还。但是……这并不是“创建 10 个流程”对我的直观感觉。
如果你想要一个 MWE,我的代码大致是这样的:
def expensive_function(arg):
a = sum(list(range(10 ** arg)))
print(a)
return a
def main():
import concurrent.futures
from random import randrange
with concurrent.futures.ProcessPoolExecutor(max_workers=4) as executor:
# Submit the tasks
futures = []
for i in range(100):
random_argument = randrange(5, 7)
futures.append(executor.submit(expensive_function, random_argument))
# Monitor your progress:
num_results = len(futures)
for k, _ in enumerate(concurrent.futures.as_completed(futures)):
print(f'********** Completed {k + 1} of {num_results} simulations **********')
if __name__ == '__main__':
main()
【问题讨论】:
-
我要猜测 concurrent.futures 创建了十个进程并在它们之间/向它们分配数百个任务,并且操作系统在内核之间分配工作负载以它认为合适的方式。
-
那么,如果操作系统只是要将代码分发到所有内核,那么保留大量工作人员的意义何在?单个进程有“600%”的 CPU 消耗是什么意思?
-
??尝试使用 max_workers 参数,看看性能或完成时间是否会发生变化。
标签: python linux concurrency htop