改动了某模型的python脚本后,训练过程中总是不定期出现程序崩溃,有时能完整跑完几个epoch,有时一个epoch每跑完就崩溃了,错误类似如下:
Traceback (most recent call last):
File "tools/train.py", line 311, in <module>
raise e
File "tools/train.py", line 305, in <module>
args.level,
File "/usr/local/lib/python3.6/site-packages/at/engine/ddptrainer.py", line 234, in launch
args,
File "/root/.local/lib/python3.6/site-packages/torch/multiprocessing/spawn.py", line 230, in spawn
return start_processes(fn, args, nprocs, join, daemon, start_method='spawn')
File "/root/.local/lib/python3.6/site-packages/torch/multiprocessing/spawn.py", line 188, in start_processes
while not context.join():
File "/root/.local/lib/python3.6/site-packages/torch/multiprocessing/spawn.py", line 136, in join
signal_name=name
torch.multiprocessing.spawn.ProcessExitedException: process 0 terminated with signal SIGSEGV
非常讨厌pytorch的multiprocessing里这个用于发起多进程并发调用的spawn,当某个process里出错了,spawn不能返回发生错误的准确位置!而是类似上面这样给出spawn里的发起调用的位置这种没用的信息,再就是进程出错的粗略原因,后者稍微有点用,但是只有这个信息很难快速定位出错的根本原因!像上面这个SIGSEGV错误,花了好一阵时间才定位到出错的地方,居然是一个numpy数组越界访问了,很简单: m = ms[j, i],而python没有任何out of bounds这样的错误抛出来!单步跟踪发现,越界非法访问其实不止崩溃时(譬如说 j = 1649),前面很多索引访问都已经越界了(第一个维度合法最大值应该是12,所以从13-1649都是非法的索引值)但是居然没有报错!而且每次运行程序后崩溃时j的值还不一样,真的是很诡异,平常写个numpy数组然后使用非法的索引值去访问其值总是能抛出类似下面的IndexError:
b[100,200]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: index 100 is out of bounds for axis 0 with size 100
不知为何上面的情况下抛不出IndexError,而是允许非法越界访问直到某个时候发生SIGSEGV错误而崩溃。