我想使用不同的超参数多次运行Python3进程。为了充分利用可用的CPU,我想多次生成该进程。但是,在实践中,我几乎观察不到任何加速。下面,我将重现一个说明效果的小测试。
首先是一个Python测试脚本:
(speed_test.py)
import numpy as np
import time
now = time.time()
for i in range(50):
np.matmul(np.random.rand(1000,1000),np.random.rand(1000,1000))
print(round(time.time()-now,1))
单次通话:python3 speed_test.py
打印 10.0
秒。
但是,当我尝试并行运行两个进程 :
python3 speed_test.py & python3 speed_test.py & wait
打印 18.6 18.9
。parallel python3 speed_test.py ::: {1..2}
打印 18.3 18.7
。似乎并行化几乎不给我买任何东西(两次执行几乎是两倍)。我知道我不能指望线性加速,但这似乎没有什么区别。我的系统有1个插槽,每个插槽2个核心,每个核心2个线程(总共4个CPU)。我在8 CPU Google Cloud实例上看到了相同的效果。大致来说,并行运行时,每个进程的计算时间提高不超过〜10-20%。
最后,将CPU固定到进程也无济于事:
taskset -c 0-1 python3 speed_test.py & taskset -c 2-3 python3 speed_test.py & wait
打印 17.1 17.8
由于全局解释器锁,我认为每个Python进程只能使用1个CPU。反正有加快我的代码的速度吗?
答案 0 :(得分:1)
感谢@TomFenech的回复,我确实应该添加CPU使用率信息:
结论示例:您是对的。当我调用htop
时,实际上每个启动的作业看到4个进程,而不是1个。因此,该作业在内部进行分配。我认为this是相关的,BLAS / MKL的(矩阵)乘法发生分布。
继续从事真正的工作:因此,上面的玩具示例实际上涉及更多,而不是我的真实剧本的完美案例。我的真实(机器学习)脚本仅部分依赖于Numpy(不适用于矩阵乘法),但是大多数繁重的计算都是在PyTorch中执行的。当我在本地调用脚本(4个vCPU)时,它使用约220%的CPU。当我在Google Cloud集群(8个vCPU)上调用该脚本时,令人惊讶的是,它甚至达到了约700%(htop
实际上显示了7-8个进程)。因此,PyTorch在分发自身方面似乎做得更好。
(可以使用np.__config__.show()
来获取Numpy BLAS版本。我的本地Numpy使用 OpenBlas ,Google集群使用 MKL (Conda安装)。找不到)类似的命令来检查BLAS版本的PyTorch,但假定使用相同的命令。)
通常,结论似乎表明,在涉及矩阵乘法时,Numpy和PyTorch本身已经负责分发代码(并且所有CPU在本地都是可见的,即没有群集/服务器设置)。因此,如果您的大多数脚本是矩阵乘法,那么比(至少是我)期望自己分发脚本的原因要少。
但是,并不是我所有的代码都是矩阵乘法。因此,从理论上讲,我仍然应该能够从并行过程中获得加速。我用50/50线性和矩阵乘法代码编写了一个新测试:
(speed_test2.py)
import time
import torch
import random
now = time.time()
for i in range(12000):
[random.random() for k in range(10000)]
print('Linear time',round(time.time()-now,1))
now = time.time()
for j in range(350):
torch.matmul(torch.rand(1000,1000),torch.rand(1000,1000))
print('Matrix time',round(time.time()-now,1))
在Google Cloud(8 vCPU)上运行此操作
:python3 speed_test2.py & python3 speed_test2.py
给出两个进程的线性时间12.6,矩阵时间15.4 。 结论:尽管这里有8个vCPU,但是代码的Pytorch / matrix(第二个)部分实际上在两个以上的进程中变慢了。代码的线性部分当然会增加(最多8个并行进程)。我认为这完全可以解释为什么在实践中,启动多个并发进程时,Numpy / PyTorch代码可能未显示出太大的改进。而且,当您看到8个vCPU时,天真地启动8个进程可能并不总是有益的。如果我在这里某处不对,请纠正我。