报错及处理方案合集
vscode相关
无代码补全
一般是python编辑器的问题,注意是否激活了python环境。如果也无法激活python环境,就检查一下python的几个扩展是否存在问题,特别是pylance,尤其是其可能未【启用】。
再记录一个很好用的vscode扩展:IntelliCode Completions,IntelliCode Completions根据当前上下文预测一整行代码。预测显示为灰色文本在光标的右侧。此扩展支持Python、JavaScript和TypeScript。
NaN and Inf
参考:CSDN:Pytorch定位NaN
这种问题常见于网络训练中,较难处理,其中一种可能性是从单卡迁移到多卡时没有降学习率。
debug
但是还有很多可能性,建议在可能出现nan和inf的代码段中加入以下语句,print出每个循环变量的均值、最大值、最小值、nan的变量个数。注:代码中的tensor为需要查看的变量,请根据自己的变量名进行替换。torch.distributed.barrier()
是在等待多进程同步。
torch.distributed.barrier()
print('mean:{},max:{},min:{},nan:{}'.format(torch.mean(tensor),torch.max(tensor),torch.min(tensor),torch.sum(torch.isnan(tensor).float())))
半精度越界
在计算attention的过程中可能会出现最值超过半精度最值65504的问题,需找到inf出现的位置,然后使用:
from torch.cuda.amp import autocast
with autocast(dtype=torch.float32):
……
注意:autocast的囊括范围可以大一些,因为其表示在这个范围内,均使用float32进行计算。autocast(dtype=torch.float32)
结束在数据大小回到65504范围内之后即可。
未知的load影响
问题:在程序里加了下面一行代码后,出现Nan,查找发现是一个毫不相关的transformer层报的Nan,而且经对比debug,加不加这行代码,这个transformer层的输入、权重均相同,但就是一个报Nan一个正常……
sd = torch.load(embed_tokens_path, map_location="cpu")["state_dict"]
原因:未知,推测是load时产生了一些影响。
解决方案:在Class类外的其他地方load这个ckpt,然后把需要的数据传入进来,而不是把路径传入进来再load。
CPU、GPU利用率问题
在深度学习模型训练过程中,在服务器端或者本地pc端,输入nvidia-smi来观察显卡的GPU内存占用率(Memory-Usage),显卡的GPU利用率(GPU-util),然后采用top来查看CPU的线程数(PID数)和利用率(%CPU)。往往会发现很多问题,比如,GPU内存占用率低,显卡利用率低,CPU百分比低等等。
参考:深度学习PyTorch,TensorFlow中GPU利用率较低,CPU利用率很低,且模型训练速度很慢的问题总结与分析
GPU内存占用率问题
这往往是由于模型的大小以及batch size的大小,来影响这个指标。当你发下你的GPU占用率很小的时候,比如40%,70%,等等。此时,如果你的网络结构已经固定,此时只需要改变batch size的大小,就可以尽量利用完整个GPU的内存。GPU的内存占用率主要是模型的大小,包括网络的宽度,深度,参数量,中间每一层的缓存,都会在内存中开辟空间来进行保存,所以模型本身会占用很大一部分内存。其次是batch size的大小,也会占用影响内存占用率。batch size设置为128,与设置为256相比,内存占用率是接近于2倍关系。当你batch size设置为128,占用率为40%的话,设置为256时,此时模型的占用率约等于80%,偏差不大。所以在模型结构固定的情况下,尽量将batch size设置大,充分利用GPU的内存。(GPU会很快的算完你给进去的数据,主要瓶颈在CPU的数据吞吐量上面。)
GPU利用率问题
这个是Volatile GPU-Util表示,当没有设置好CPU的线程数时,这个参数是在反复的跳动的,0%,20%,70%,95%,0%。这样停息1-2 秒然后又重复起来。其实是GPU在等待数据从CPU传输过来,当从总线传输到GPU之后,GPU逐渐起计算来,利用率会突然升高,但是GPU的算力很强大,0.5秒就基本能处理完数据,所以利用率接下来又会降下去,等待下一个batch的传入。因此,这个GPU利用率瓶颈在内存带宽和内存介质上以及CPU的性能上面。最好当然就是换更好的四代或者更强大的内存条,配合更好的CPU。
另外的一个方法是,在PyTorch这个框架里面,数据加载Dataloader上做更改和优化,包括num_workers(线程数),pin_memory,会提升速度。解决好数据传输的带宽瓶颈和GPU的运算效率低的问题。在TensorFlow下面,也有这个加载数据的设置。
torch.utils.data.DataLoader(image_datasets[x],batch_size=batch_size,shuffle=True,num_workers=8,pin_memory=True)
为了提高利用率,首先要将num_workers(线程数)设置得体,4,8,16是几个常选的几个参数。本人测试过,将num_workers设置的非常大,例如,24,32,等,其效率反而降低,因为模型需要将数据平均分配到几个子线程去进行预处理,分发等数据操作,设高了反而影响效率。当然,线程数设置为1,是单个CPU来进行数据的预处理和传输给GPU,效率也会低。其次,当你的服务器或者电脑的内存较大,性能较好的时候,建议打开pin_memory打开,就省掉了将数据从CPU传入到缓存RAM里面,再给传输到GPU上;为True时是直接映射到GPU的相关内存块上,省掉了一点数据传输时间。
CPU的利用率问题
很多人在模型训练过程中,不只是关注GPU的各种性能参数,往往还需要查看CPU处理的怎么样,利用的好不好。这一点至关重要。但是对于CPU,不能一味追求超高的占用率。如图所示,对于14339这个程序来说,其CPU占用率为2349%(我的服务器是32核的,所以最高为3200%)。这表明用了24核CPU来加载数据和做预处理和后处理等。其实主要的CPU花在加载传输数据上。此时,来测量数据加载的时间发现,即使CPU利用率如此之高,其实际数据加载时间是设置恰当的DataLoader的20倍以上,也就是说这种方法来加载数据慢20倍。当DataLoader的num_workers=0时,或者不设置这个参数,会出现这个情况。
库函数
bdb.bdbquit
问题:调试时加入pdb调试代码,定位到断点之后程序直接中断并报错bdb.bdbquit。
解决办法:不能在有多个进程的情况下调试代码,只用单卡,设置workers_per_gpu=0即可正常使用pdb!
tqdm
问题:'module' object is not callable
。
原因:讲真这种报错很迷惑人,这个错并不是因为module不能调用,而是……import错了……应该from tqdm import tqdm
,而不是import tqdm
,讲真,这个包也是有问题,为什么非要这样import……
其他
get unexpected keyword argument
需要定位报错的函数,看看是参数多写了还是函数少写了。
冷门错误:在sh文件设置第三方库Deepspeed环境变量时文件目录设置错了,但是并不会报找不到文件的错误,因为Deepspeed自己就是一个库,会直接用python中的库,而由于这个库被自定义修改了,所以就报了错。
Unicode utf-8
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc3 in position 2: invalid continuation byte
原因:代码的注释中用了中文,对,注释中也不行,删掉就没问题了……
训练结果差
训练集准确率过低,无法拟合,跟随机一摸一样,调模型没效果。
原因:使用了0.1的学习率,对这个任务而言太高了,改成0.01后问题解决。以后调试模型阶段建议从小的学习率(1e-2~1e-4)开始。
库函数管理
问题:ModuleNotFoundError: No module named xxx
解决方法:大概率是import 路径有问题,先用os包查看报错代码的时候对应的绝对路径是什么:print(os.path.abspath("."))
,然后,确定好从绝对路径到需要import的代码的相对位置即可:import sys
;sys.path.append('到报错代码的相对路径')
。
多进程
问题:在dataloader里用了CUDA后,就会出现“RuntimeError: Cannot re-initialize CUDA in forked subprocess. To use CUDA with multiprocessing, you must use the 'spawn' start method”的问题。
解决方案:在dataloader里设置num_workers=0,比如:
DataLoader(train_dataset, shuffle=True, batch_size=batch_size, num_workers=0)
DDP
问题:
[W socket.cpp:436] [c10d] The server socket has failed to bind to [::]:29500 (errno: 98 - Address already in use).
[W socket.cpp:436] [c10d] The server socket has failed to bind to 0.0.0.0:29500 (errno: 98 - Address already in use).
[E socket.cpp:472] [c10d] The server socket has failed to listen on any local network address.
解决方案:有些进程占用了端口,使用ps aux
查看进程,然后把冲突的进程kill -9
关掉。
Git status
问题:把一批 git 项目从一台设备拷到另一台设备之后,未对文件做任何修改,但是进入到项目的根目录下,执行git status却发现所有的文件状态都是modified。
执行git diff --summary
发现大多都是mode change 100644 => 100755
,原来是拷贝文件的过程中,文件的权限被自动修改了,权限值由644变成了755. 这种情况如何处理呢?
解决方案:关闭 git 的 filemode:
- 全局关闭:
git config --global core.filemode false
- 单项目关闭:
git config core.filemode false
run.py error
问题:
run.py: error: the following arguments are required: training_script, training_script_args
bash: line 1: /mnt/iag/user/daiyiheng/model/easyllm/llm/runners/hf_runner.py: Permission denied
原因:在sh文件中,代码是这样写的:
export LAUNCHER="OMP_NUM_THREADS=8 python -m torch.distributed.run \
--nproc_per_node $GPUS_PER_NODE \
--nnodes $NNODES
"
注意倒数第二行,少了一个\
,这种问题真的好烦啊,而且这种问题的报错往往不能反映实际发生的问题。