python-3.x - Joblib 嵌套并行执行不使用可用内核
问题描述
通过在外部语句上使用 n_jobs>1 的嵌套 Parallel 语句,嵌套 Parallel 函数似乎是从 1 个线程而不是 4 个线程可用的受限资源。即考虑以下高度简化的脚本来重现该问题:
from joblib import Parallel, delayed
import numpy as np
def parallel_in_parallel_test(i):
a = np.ones((1000,1000))
for j in range(2000):
a *= np.random.randn(1000,1000)
return a.sum()
def parallel_in_parallel_wrapper(j, n_threads=4):
out2 = Parallel(n_jobs=n_threads)(delayed(parallel_in_parallel_test)(i) for i in range(100))
return np.array(out2).sum()
out = Parallel(n_jobs=3)(delayed(parallel_in_parallel_wrapper)(j, n_threads=4) for j in range(100))
我原本预计 3 个并行进程会产生 4 个进程,从而产生 400% 的 CPU 使用率,即每个“父进程”有 4 个内核/线程。但是,这 4 个“子进程”不是并行运行的。每个“父进程”使用 100% 的 CPU 而不是 400%(只有一个核心/线程)
我可以用简约的环境重现该问题:
conda create --name py39 python=3.9
conda activate py39
conda install numpy joblib
我的操作系统:Ubuntu 18.04.5 LTS
对于我的特定代码,非嵌套方法是不可行的,因为嵌套并行位于类的方法中。
任何建议如何正确利用可用资源?这只是一个简单的错误吗?
解决方案
显然,更改嵌套语句中使用的后端的 inner_max_num_threads 限制是可行的——我仍然不清楚为什么首先需要这样做。
from joblib import Parallel, delayed, parallel_backend
import numpy as np
def parallel_in_parallel_test(i):
a = np.ones((1000,1000))
for j in range(2000):
a *= np.random.randn(1000,1000)
return a.sum()
def parallel_in_parallel_wrapper(j, n_threads=4):
with parallel_backend("loky", inner_max_num_threads=n_threads):
out2 = Parallel(n_jobs=n_threads)(delayed(parallel_in_parallel_test)(i) for i in range(100))
return np.array(out2).sum()
out = Parallel(n_jobs=3)(delayed(parallel_in_parallel_wrapper)(j, n_threads=4) for j in range(100))
推荐阅读
- c++ - 添加所需库后使用 TShark C++ 源文件剖析消息时未定义的引用
- java - Sentry Android - 构建发布 apk 时出现问题
- django - Spring MVC 和 Django
- c# - 当我在 C# 中使用“While”时,我不想打印最后一个计算
- java - 使用springboot连接oracle
- hyperledger-fabric - 织物样本中的高吞吐量链代码为 10 tps,我可以将其扩展到 100 tps 吗?我看到织物可以扩展到 100,000 tps
- javascript - 从渲染道具组件获取状态
- struts2 - 没有为命名空间 [/] 和操作名称 [hello] 映射的操作与上下文路径 [/HelloWorldStrut2] 关联
- mongodb - 有没有办法使用聚合来获取多个条件下的数据
- android - 是否有可能以编程方式在 android 中获得 SAR 值?如果可能比怎么做?