Joblib 嵌套并行执行不使用可用内核
Joblib nested Parallel execution not making use of available cores
通过在外部语句上使用 n_jobs>1 的嵌套 Parallel 语句,嵌套 Parallel 函数似乎是 1 个线程而不是 4 个线程可用的受限资源。
IE。考虑以下高度简化的脚本来重现该问题:
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 个进程,从而产生 CPU 使用率为 400%,即每个“父进程”4 cores/threads。但是,这 4 个“子进程”运行 不是并行的。每个“父进程”使用 100% 的 CPU 而不是 400%(只有一个 core/thread)
考虑以下来自 htop 的屏幕截图:
我可以在极简环境中重现问题:
conda create --name py39 python=3.9
conda activate py39
conda install numpy joblib
我的 OS:Ubuntu 18.04.5 LTS
非嵌套方法对我的特定代码不可行,因为嵌套并行位于 class.
的方法中
对如何正确利用可用资源有什么建议吗?这只是一个简单的错误吗?
显然更改嵌套语句中使用的后端的 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))
通过在外部语句上使用 n_jobs>1 的嵌套 Parallel 语句,嵌套 Parallel 函数似乎是 1 个线程而不是 4 个线程可用的受限资源。 IE。考虑以下高度简化的脚本来重现该问题:
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 个进程,从而产生 CPU 使用率为 400%,即每个“父进程”4 cores/threads。但是,这 4 个“子进程”运行 不是并行的。每个“父进程”使用 100% 的 CPU 而不是 400%(只有一个 core/thread)
考虑以下来自 htop 的屏幕截图:
我可以在极简环境中重现问题:
conda create --name py39 python=3.9
conda activate py39
conda install numpy joblib
我的 OS:Ubuntu 18.04.5 LTS
非嵌套方法对我的特定代码不可行,因为嵌套并行位于 class.
的方法中对如何正确利用可用资源有什么建议吗?这只是一个简单的错误吗?
显然更改嵌套语句中使用的后端的 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))