【问题标题】:Why would ThreadPool cause more than one core worth of CPU usage?为什么 ThreadPool 会导致超过一个核心的 CPU 使用率?
【发布时间】:2021-04-26 18:37:26
【问题描述】:

我的代码如下所示:

def get_image_stats(fp):
    img = cv2.imread(fp)
    return img.shape[0], img.shape[1], img.shape[0]/img.shape[1]

with ThreadPool(16) as pool:
    res = list(tqdm(pool.imap_unordered(get_image_stats, df.file_path), total=len(df)))

heights, widths, ars = list(zip(*res))

唯一特定于库的部分是 cv2.imread,它只是将图像文件加载到 numpy 数组中,因此它是 I/O 绑定的。

为什么我的 CPU 使用率会这样?

关于该图像的注释:

  • 横轴 i 时间以秒为单位,纵轴是 cpu % 使用率,范围从 0% 到 100%。更新间隔为 1 秒。
  • 40s 是我开始脚本的地方
  • 不容易看到,但有16个核心。

另一个注意事项:我没有将 n_workers 设置为 16,因为我有 16 个内核。只是巧合。

那么为什么会同时使用 75% 的 16 个内核?

【问题讨论】:

    标签: python multiprocessing


    【解决方案1】:

    因为如果可以的话,您的线程池将使用每个线程 1 个核心。这就是提供最大并行性和最大化吞吐量的原因。

    【讨论】:

    • 大吃一惊。我认为这就是Pool 的用途。我没有意识到ThreadPool 会启动更多进程。实际上,让我退一步解释一下我的推理:1)你说每个线程 1 个核心,2)我将其解释为多个核心同时工作,3)我了解 GIL 并且知道只有在有 GIL 时才能工作多个进程,4)我认为Pool 是您管理多个进程的方式,我认为ThreadPool 是您在1 个进程中管理多个线程的方式
    • 嗯,你会期待什么?如果它使用多个核心,那么您将获得的最好结果就是一个核心上的高负载。但是所有 16 个内核的负载都很高。 QED。尝试将池的大小减小到 8,看看会发生什么?
    • 我明白了。我想我需要一些时间来重新配置我对 Python 中的多线程的理解。希望你能欣赏。很快就会接受您的回答。
    • 哦,当然,我不是故意打你的。考虑到 GIL 可能是它不是所有内核的 95% 的重要原因。
    猜你喜欢
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多