本地多进程执行模型拟合脚本时n>1出现巨幅性能下降的问题求助
本地多进程执行模型拟合脚本时n>1出现巨幅性能下降的问题求助
我正在开发一个作业提交脚本,用于在Torque、Slurm集群以及本地硬件上处理并行化模型拟合(基于scipy.optimize)。前两者运行正常,但本地执行时遇到了棘手的问题。
我的处理思路如下:
给定模型配置和包含M个响应变量(RVs)的数据,我需要拟合M个模型:
- 将数据拆分为n个块,每个块对应M个RVs的均等部分,然后保存到磁盘。
- 创建一个
.sh脚本,加载数据并对其拟合模型。
问题仅出现在本地机器且n>1的场景下:当n==1时运行完美,但n>1时,进程速度会慢几个数量级,并且会占用所有CPU。我猜测这是因为存在某个共享资源导致进程竞争,但想不出具体是什么——毕竟所有资源都单独存在磁盘上,而且我理解脚本创建的Python进程有自己的GIL。
我已经尝试过这些解决方法,但都没奏效:
- 使用
multiprocess替代bash脚本运行可调用对象。但这也不管用(要么是不可序列化对象的问题,要么是任务莫名消失没有结果),而且我想坚持用作业脚本的方式,因为这样更容易重新运行失败的模型,也和批处理作业的运行方式更一致。 - 尝试使用内部基于
dill或cloudpickle的multiprocess分支,同样没有解决问题。 - 通过自定义
preexec_fn限制每个作业的可用核心数,结果报错:'fork' resource unavailable。
我对multiprocess的经验有限,虽然看过很多相关问题,但还是没搞清楚我的情况有什么特殊之处。如果有人能提供见解,我会非常感激。
问题细节
- 我尝试的操作:用
multiprocess运行bash脚本,该脚本执行一个处理磁盘保存文件的Python脚本。 - 预期结果:进程正常运行,速度和不使用
multiprocess时差不多。 - 实际结果:速度慢了大约5个数量级。
举个直观的例子说明性能下降有多严重:
- 当n==1时,拟合2个模型不到1秒。
- 当n==2时,拟合2个模型要一整晚。
编辑1
这个问题出现在M3处理器的Macbook和Ubuntu系统的联想Thinkpad上。我尝试在HPC计算节点上运行完全相同的脚本(不提交为单独作业,只是在交互式作业中运行本地并行任务),那里运行没有任何问题。
编辑2:最小可复现示例
import subprocess import sys def test_parallel_fitting(n_covariates, n_models, n_processes): # Create two identical but independent processes processes = [] n_covariates = int(n_covariates) n_models = int(n_models) n_processes = int(n_processes) n_models_per_process = n_models // n_processes for i in range(n_processes): command = ["python", "-c", f""" import numpy as np import time from scipy import optimize # Simple model fitting that shouldn't interact with other processes for f in range({n_models_per_process}): start_time = time.time() X = np.random.rand(1500, {n_covariates}) y = np.random.rand(1500) def model(params, X, y): return np.sum((y - np.dot(X, params)) ** 2) result = optimize.minimize(model, x0=np.ones({n_covariates}), args=(X, y)) print(f"Process {i}:",f," finished in ", time.time() - start_time, " seconds") """] p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) processes.append(p) # Wait for completion and time it for p in processes: p.wait() output, error = p.communicate() print(output.decode()) print(error.decode()) print("Parallel fitting completed") if __name__ == "__main__": args = sys.argv[1:] test_parallel_fitting(*args)
测试情况
运行流畅的命令:
python script.py 6 6 3 python script.py 6 120 10 python script.py 7 120 1
运行极慢的命令:
python script.py 7 6 3 python script.py 7 120 10 python script.py 7 120 2
看起来协变量的数量是关键问题——可能当矩阵乘法超过某个规模时,会由某个后台进程处理,导致并行工作进程都在等待这个进程释放资源?想问问大家这个脚本在你们那里的运行情况如何?
编辑3
已调整格式并移除了冗余文本。
备注:内容来源于stack exchange,提问作者Augustijn de Boer
相关产品推荐
相关产品推荐

