Python 3.x 来自bash的多个python调用,但没有加速

Python 3.x 来自bash的多个python调用,但没有加速,python-3.x,shell,parallel-processing,gnu-parallel,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))

我想用不同的超参数多次运行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。 并行python3 speed_test.py::{1..2}打印18.3 18.7。 在这里,并行化似乎很难给我带来任何好处,在几乎两倍的时间内执行两次。我知道我不能期望线性加速,但这似乎差别不大。我的系统有1个插槽,每个插槽2个内核,每个内核4个CPU总共2个线程。我在一个8CPU的Google云实例上看到了同样的效果。大致上,当并行运行时,每个进程的计算时间提高不超过10-20%

最后,将CPU固定到进程也没有多大帮助:

任务集-c 0-1 python3 speed_test.py和任务集-c 2-3 python3 speed_test.py和wait prints 17.1 17.8
我认为由于全局解释器锁,每个Python进程只能使用1个CPU。还有什么可以加快我的代码速度的吗?

谢谢@TomFenech的回复,我真的应该添加CPU使用信息:

本地4个vCPU:单次呼叫约390%,双次呼叫约190-200% Google cluster 8 vCPU:单次呼叫约400%,双次呼叫约400%,按预期 玩具示例的结论:你是对的。当我调用htop时,我实际上看到每个启动的作业有4个进程,而不是1个。因此,这项工作是内部分配的。我认为这与BLAS/MKL的矩阵乘法有关

《真实的工作》的续篇:所以,上面的玩具示例实际上更复杂,对于我的真实脚本来说并不是一个完美的例子。我真正的机器学习脚本仅部分依赖Numpy,而不是矩阵乘法,但大部分繁重的计算都是在PyTorch中执行的。当我在本地调用脚本4 vCPU时,它使用约220%的CPU。当我在Google Cloud cluster 8 vCPU上调用该脚本时,令人惊讶的是,它甚至达到了约700%的htop确实显示了7-8个进程。因此,PyTorch在分销方面似乎做得更好。 Numpy BLAS版本可以使用np.\uuuu config\uuuuu.show检索。我的本地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%,第二部分为500% 并行进程python3 speed_test2.py和python3 speed_test2.py为这两个进程提供了12.6的线性时间和15.4的矩阵时间。 加上第三个过程,线性时间为12.7,矩阵时间为25.2
结论:虽然这里有8个vCPU,但Pytorch/matrix代码的第二部分实际上会变慢,需要2个以上的过程。代码的线性部分当然会增加到8个并行进程。我认为这完全解释了为什么在实践中,当您启动多个并发进程时,Numpy/PyTorch代码可能没有显示出多大的改进。当您看到8个vCPU时,天真地启动8个进程可能并不总是有益的。如果我错了,请纠正我

只是猜测,但当您运行python程序的单个实例时,请尝试运行top。我怀疑您正在使用的numpy版本是针对使用多个内核的低级数学库编译的-如果您看到您的程序使用的CPU超过100%,很可能就是这种情况。@Tom Fenech。在你的评论之后,我做了一些额外的测试,并在下面写了一个新的答案。