Python 为什么线程池会导致超过一个核心的CPU使用率?

Python 为什么线程池会导致超过一个核心的CPU使用率?,python,multiprocessing,Python,Multiprocessing,我有如下代码: 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,

我有如下代码:

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秒
  • 40年代是我开始写剧本的地方
  • 这不容易看到,但有16个核心
另一个注意事项:我没有将n_workers设置为16,因为我有16个内核。只是巧合


那么,为什么这会一次占用16个内核中的75%?

因为您的线程池将在可能的情况下使用每个线程1个内核。这就是实现最大并行性和最大吞吐量的原因。

让人目瞪口呆。我以为那就是游泳池的用途。我没有意识到
ThreadPool
会启动更多进程。事实上,让我退一步解释我的推理:1)你说每个线程1个核,2)我解释为多个核同时工作,3)我知道GIL,并且知道只有在有多个进程的情况下才能工作,4)我认为
是管理多个进程的方式,我认为
ThreadPool
是如何在1个进程中管理多个线程的,这是为了进一步地进行上述操作:。那么,您期望什么?如果它不使用多个核心,那么您将得到的最好结果就是一个核心上的高负载。但您在所有16核上都获得了高负载。QED。试着把游泳池的大小减少到8,看看会发生什么?我明白了。我想我需要一些时间来重新理解Python中的多线程。希望你能欣赏。我很快就会接受你的回答。哦,当然,我不是故意打你的。解释GIL可能是为什么它不是所有核的95%的一个重要部分。