Python使用Slurm进行多进程处理

5

我想使用多进程来运行一个简单的任务(我认为这与在Matlab中使用parfor是相同的,对吗?)

例如:

from multiprocessing import Pool
def func_sq(i):
    fig=plt.plot(x[i,:])     #x is a ready-to-use large ndarray, just want
    fig.save(....)           #to plot each column on a separate figure

pool = Pool()
pool.map(func_sq,[1,2,3,4,5,6,7,8])

但是我很困惑如何使用 slurm 提交作业。我一直在寻找答案,但没有找到一个好的解决方案。 目前,在不使用多进程的情况下,我正在使用类似于这样的 slurm 作业提交文件:(命名为 test1.sh)

#!/bin/bash

#SBATCH -N 1
#SBATCH -n 1
#SBATCH -p batch
#SBATCH --exclusive

module load anaconda3
source activate py36
srun python test1.py

然后,在命令行窗口中输入 sbatch test1.sh。

如果我想使用多进程,我应该如何修改我的 sh 文件?我已经尝试过自己修改,但似乎只是将我的 -n 改为 16 和 Pool(16),这样会使我的作业重复 16 次。

或者,如果多进程不适用,有没有一种方法可以最大化我的性能(我听说过多线程,但不知道它的确切工作原理)。

如何有效地使用内存,以免崩溃?(我的 x 矩阵非常大)

谢谢!

对于 GPU,是否可以做同样的事情?我的当前提交脚本不使用多进程:

#!/bin/bash

#SBATCH -n 1
#SBATCH -p gpu
#SBATCH --gres=gpu:1

非常感谢!
2个回答

7
“-n”标志设置了您的sbatch提交要执行的任务数,这就是为什么您的脚本会运行多次的原因。您想要更改的是“-c”参数,它是每个任务分配的CPU数量。您的脚本生成了其他进程,但它们将是父进程的子进程,并共享分配给它的CPU。只需在脚本中添加“#SBATCH -c 16”。至于内存,每个CPU都有一个默认的内存分配量,因此增加CPU数量也会增加可用的内存量。如果您没有获得足够的内存,请添加类似“#SBATCH --mem=20000M”的内容以请求特定数量的内存。

嗨,Colin,感谢您的回复!另一个问题是,如果我想使用GPU来完成这项工作,我应该如何修改我的作业提交脚本?(请参见我的问题发布中的添加部分,非常感激!)- 我只需将--gres = gpu:1更改为更高的数字吗? - Vickyyy
此外,我知道“-N”是节点数,但它如何影响我的计算过程呢? - Vickyyy

0
我并不是要排斥你,但这个问题似乎表明你并不真正理解你在使用的工具。Python Multiprocessing 允许一个 Python 程序启动子进程以帮助它并行执行任务。这特别有用,因为多线程(通常是其他编程语言中实现并行的方式)由于 Python 的全局解释器锁 在 Python 中无法实现并行代码执行。
Slurm(我没有使用过,但从一些快速研究来看)似乎是一个相当高级的实用程序,允许个人将工作提交到某种计算机集群(或超级计算机...通常是类似的概念)。它本质上无法看到启动的程序如何运行;也就是说,它与你的 Python 程序启动 16(或更多)辅助进程的事实没有关系。它的工作是将你的 Python 程序安排为黑盒子运行,然后坐下来确保它成功完成。
您似乎有一些模糊的数据处理问题。您将其描述为一个大矩阵,但是您没有提供足够的信息让我真正理解您想要实现什么。无论如何,如果您不真正了解您正在做什么以及您正在使用的工具如何工作,那么您只会在胡乱猜测中挣扎,直到可能最终幸运地使其工作。停止猜测,弄清楚这些工具的作用,四处查找并阅读文档,然后找出您要实现的目标以及如何以合理的方式分解工作。
以下是我的最佳猜测,但是由于我几乎没有任何可用信息,因此可能没有任何帮助:
您的Python脚本并不知道它被Slurm多次运行(我猜您指的是-n 16)。因此,每次Slurm运行整个脚本,而您的Python脚本每次都会从头开始完成整个任务。因此,任务会重复16次。如果您希望Slurm和您的Python程序进行交互,以便Python程序期望在并行运行中多次运行,则我无法帮助您,您需要深入了解Slurm。
您的数据必须能够按增量或部分读取,否则您将无法将此作业分成几部分。也就是说,如果您只能一次性读取整个矩阵,或者根本不能读取,那么您只能采用将整个矩阵读入内存的解决方案,而这显然不是一个好的选择。假设您可以,且您想独立地对每一行执行一些操作,则您很幸运,因为您的任务被正式称为“尴尬的并行”。如果是这样,那么就非常好了。
假设您的问题是尴尬的并行(因为看起来您只是尝试加载数据矩阵的每一行,以某种方式绘制它,然后将该图像保存到磁盘上),并且您可以逐步加载数据,则应继续阅读Python的multiprocessing模块,Pool().map可能是正确的方向。创建一些Python生成器来产生您的数据矩阵的行,然后将该生成器和func_sq传递给pool.map,等待作业完成即可。
如果您确实需要在多台机器上执行此工作,而不是通过自己的Slurm + Multiprocessing堆栈进行操作,我建议您开始使用实际的数据处理工具,例如PySpark。
这个问题似乎并不是一个微不足道的问题,即使它是,你也没有给出足够的细节让我提供一个强有力的答案。对于你所问的问题,没有“只需修复这一行”的答案,但我希望这可以帮助你了解你的工具在做什么以及如何继续进行。

那是一个冗长而无用的回答。 - quoniam
那是一个冗长而无用的回答。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接