来自bash的多个python调用但没有加速

时间:2018-08-24 14:20:33

标签: python-3.x shell parallel-processing gnu-parallel

我想使用不同的超参数多次运行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。反正有加快我的代码的速度吗?

1 个答案:

答案 0 :(得分:1)

感谢@TomFenech的回复,我确实应该添加CPU使用率信息:

  • 本地(4个vCPU):单次调用=〜390%,两次调用〜190-200%
  • Google集群(8个vCPU):一次调用约400%,两次调用约400%(按预期)

结论示例:您是对的。当我调用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)上运行此操作

  • 单个过程给出线性时间12.6,矩阵时间9.2 。 (第一部分中的CPU为100%,第二部分中的CPU为500%)
  • 并行进程python3 speed_test2.py & python3 speed_test2.py给出两个进程的线性时间12.6,矩阵时间15.4
  • 添加第三个过程将使线性时间〜12.7,矩阵时间25.2

结论:尽管这里有8个vCPU,但是代码的Pytorch / matrix(第二个)部分实际上在两个以上的进程中变慢了。代码的线性部分当然会增加(最多8个并行进程)。我认为这完全可以解释为什么在实践中,启动多个并发进程时,Numpy / PyTorch代码可能未显示出太大的改进。而且,当您看到8个vCPU时,天真地启动8个进程可能并不总是有益的。如果我在这里某处不对,请纠正我。