Slurm环境下PyTorch多进程训练频繁触发PermissionError权限拒绝问题求助
看起来你遇到的这个问题确实挺棘手的——以前正常跑的多进程训练,现在突然在Slurm集群上频繁触发PermissionError,还都是随机的不同文件,权限检查也没问题对吧?结合你在大学计算节点用远程存储的场景,我来帮你分析下可能的原因和对应的解决办法:
先明确下你的问题场景和报错信息:
你在大学计算节点运行PyTorch训练,数据存储在学校远程文件系统,设置了num_workers>0且同时跑多个训练任务;之前相同配置能正常运行,但现在所有任务都会随机在不同时间、不同文件上触发如下权限错误:
PermissionError: Caught PermissionError in DataLoader worker process 6. Original Traceback (most recent call last): File "/root/miniconda3/envs/MASynth/lib/python3.9/site-packages/torch/utils/data/_utils/worker.py", line 308, in _worker_loop data = fetcher.fetch(index) # type: ignore[possibly-undefined] File "/root/miniconda3/envs/MASynth/lib/python3.9/site-packages/torch/utils/data/_utils/fetch.py", line 51, in fetch data = [self.dataset[idx] for idx in possibly_batched_index] File "/root/miniconda3/envs/MASynth/lib/python3.9/site-packages/torch/utils/data/_utils/fetch.py", line 51, in <listcomp> data = [self.dataset[idx] for idx in possibly_batched_index] File "/remote/fs/users/UNet/code/mat_unet/version_4/data_3.py", line 183, in __getitem__ sample['semantic']= to_tensor(normalize_images(np.expand_dims(cv2.resize(read_npz(semantic_dir), dsize=(256, 256), interpolation=cv2.INTER_NEAREST), axis=0), max_val=40)) File "/remote/fs/users/users/UNet/code/mat_unet/version_4/utils.py", line 469, in read_npz with np.load(file) as data: File "/root/miniconda3/envs/MASynth/lib/python3.9/site-packages/numpy/lib/npyio.py", line 427, in load fid = stack.enter_context(open(os_fspath(file), "rb")) PermissionError: [Errno 13] Permission denied: '/remote/fs/datasets/dataset_name/version_2.0/folder1/folder2/file.npz
可能的原因及解决办法
远程存储系统的并发连接配额超限
大部分大学集群的远程存储(比如Lustre、NFS)都会限制单用户或单任务的并发文件连接数,当你同时跑多个训练任务,每个任务又有多个DataLoader worker并行读文件,很容易触发这个限制——而且有些存储系统会把“并发超限”伪装成“权限拒绝”返回给用户。
解决办法:- 先尝试降低
num_workers的数值,比如从当前的数降到2或4,减少并发读取的进程数; - 开启DataLoader的
persistent_workers=True,让worker进程在不同epoch之间保持存活,避免重复创建进程和重复打开文件,降低对存储系统的压力。
- 先尝试降低
进程文件打开数达到系统上限
集群可能最近调整了Slurm任务的资源限制,比如每个进程允许打开的最大文件数(ulimit -n)被调低了,多worker场景下很容易打满这个限制,触发权限错误。
解决办法:在你的Slurm提交脚本里,或者训练脚本的开头添加ulimit -n 65536(或者更大的数值,具体要看集群允许的最大值),调高文件打开数的限制。远程存储元数据临时锁或故障
有时候远程存储的元数据服务器会出现临时的锁冲突,导致短时间内无法读取文件,表现为随机的PermissionError。
解决办法:在你的read_npz函数里添加重试逻辑,遇到PermissionError时重试几次,比如:import time def read_npz(file, retry_times=3): for i in range(retry_times): try: with np.load(file) as data: return data except PermissionError: if i == retry_times - 1: raise time.sleep(0.5)绕过远程存储的并发限制:预加载数据到本地节点
集群的计算节点一般都有本地临时存储(比如/tmp、/scratch),读写速度快且没有远程存储的并发限制。你可以在训练前把需要的数据集拷贝到本地节点的临时目录,然后从本地读取数据。
解决办法:在Slurm提交脚本里增加预处理步骤,比如用rsync或cp把数据集拷贝到本地:# Slurm脚本里的预处理部分 LOCAL_DATA=/scratch/$USER/dataset mkdir -p $LOCAL_DATA rsync -av /remote/fs/datasets/dataset_name/version_2.0/ $LOCAL_DATA/ # 然后训练脚本读取LOCAL_DATA路径下的数据联系集群管理员排查
如果以上方法都没有效果,大概率是集群的存储系统最近调整了全局配额、IO调度规则,或者存储系统本身出现了故障。直接联系集群管理员,把你的报错信息和运行场景告诉他们,请他们帮忙检查存储系统的并发连接数、用户IO配额等配置是否有变化。
备注:内容来源于stack exchange,提问作者mahnoor.fatima




