我佛了,bug的一个合适的解决途径终于找到了,一定要开GPU硬件加速
那我这些天的debug真是醉了
如果有想在Ubuntu20.04上用3090和TensorFlow2.4的同学
可以下载这个我编译好的直接用tensorflow-2.4.0-cp38-cp38-linux_x86_64.whl
事件背景如下:30系显卡出来后,需要针对8.6算力对TensorFlow2.x进行重新编译,才可顺畅使用,若非重新编译,每次运行都会进行一次预编译,极其浪费时间。一般的,大家会选择一下两种办法:
这里,我一直以来都是选择后者,自行编译使用。自从解决了TF2.3.x在win10下的编译问题后,已经在TF2.3.x 使用了半年之久。下面总结一下TF2.3.x 在win10下对8.6算力的卡的编译问题:
TF2.4 吸取了TF2.3的问题经验,没有在Win10下报恶性的编译错误(不再需要自行修改文件等等),编译很顺畅。
TF2.4在Win10下编译完成后,并没有如期可以正常使用。可以过官方的MNIST-demo,但是过不了很多自定义模型。以我自行设计的可以支持谱范数正则化和混合精度的层为例:
Layer | 特性 | SN | Mixed Precision | Activation | Padding |
---|---|---|---|---|---|
BatchNorm | keras复刻 | × | √ | - | - |
InstanceNorm | 自行实现 | × | √ | - | - |
Dense | keras复刻 | √ | √ | more | - |
Conv2d | keras复刻 | √ | √ | more | more |
Conv2dTranspose | keras复刻 | √ | √ | more | more |
UpsamplingConv2d | 自行实现 | √ | √ | more | more |
Conv3d | keras复刻 | √ | √ | more | more |
Conv3dTranspose | keras复刻 | √ | √ | more | more |
UpsamplingConv3d | 自行实现 | √ | √ | more | more |
这些自定义层并非完全不能通过测试,而是其中的某些层,在某些情况下,无法通过,出现卡死,线程冻结、假死、CPU占用为0%的一系列BUG现象,无法确保正常使用时不出错,一般的大型网络都会在若干个batch或者甚至一个batch都跑不完的情况下,被冻结而无法训练继续。这其中,自行设计的Conv3d在一定程度的测试下,几乎可以百分百出现BUG。
测试代码如下:
layer = BaseLayers.Conv3D
layer0 = tf.keras.layers.Conv3D
input_shape_list=[]
args_list=[]
kwargs_list=[]
input_shape = [[4,64,65,66,1]]
filters=[1,4]
kernel_size=[[3,3,3]]
strides=[[1,1,1],[2,2,2]]
padding=["SAME","VALID"]
use_bias=[True]
kernel_initializer='ones'
bias_initializer='zeros'
activation=["relu","leaky_relu","linear",None,"sigmoid","tanh"]
spectral_normalization=[True,False]
iter_k=[1,3,5]
approach = ["sparse_matrix"]
for item1 in input_shape:
for item2 in filters:
for item3 in kernel_size:
for item4 in strides:
for item5 in padding:
for item6 in use_bias:
for item7 in activation:
for item8 in spectral_normalization:
for item9 in iter_k:
for item10 in approach:
input_shape_list.append(item1)
args_buf=[]
args_list.append(args_buf)
kwargs_buf = {
}
kwargs_buf["filters"]=item2
kwargs_buf["kernel_size"]=item3
kwargs_buf["strides"]=item4
kwargs_buf["padding"]=item5
kwargs_buf["use_bias"]=item6
kwargs_buf["kernel_initializer"]='ones'
kwargs_buf["bias_initializer"]='zeros'
kwargs_buf["activation"]=item7
kwargs_buf["spectral_normalization"]=item8
kwargs_buf["iter_k"]=item9
kwargs_buf["approach"]=item10
kwargs_list.append(kwargs_buf)
result=test_func(layer=layer,layer0=layer0,policy_list=policy_list,input_shape_list=input_shape_list,args_list=args_list,kwargs_list=kwargs_list,file_name="./test_24_logs/test_conv3d.txt")
print(result)
if result:
print(result)
recode[str(BaseLayers.Conv3D)]={
"passed"}
else:
print(result)
recode[str(BaseLayers.Conv3D)]={
"failed"}
print(recode)
运行时,会遇到如下三种情况之一
截图参考
情况1 假死
情况2 报错
以上的情况,都是在不修改代码,而是先后运行测试程序下的考证,随机出现,没有规律。
后来,单步调试该问题,发现并没有出错,于是脑洞一开
加上一个延时,模拟单步调试的过程,代码如下
def test_func(layer,layer0,policy_list,input_shape_list,args_list,kwargs_list,training=None,file_name=None):
if (len(input_shape_list)!=len(args_list))or(len(input_shape_list)!=len(kwargs_list)):
raise ValueError("!!! Can not test because of mismatching args")
n = len(input_shape_list)
data=open(file_name,'w+')
print(layer,file=data)
print(layer0,file=data)
for i in range(n):
time.sleep(0.1)#给每次测试加上0.1秒延迟
...
...
现象总结为,自定义层测试时出现线程冻结、假死、CPU占用为0% 或者 Non-OK-status的报错,给测试代码加上延时,解决上述问题,但是拖长了运行时间,得不偿失。
显而易见:
为了缩小范围,我针对6.1算力的1080重新编译了TF2.4 问题依旧。那么可以大概率的确定,不是新卡的问题,旧卡也会出现一样的情况。如果是驱动问题,那为何TF2.3就可行呢。退回最原始的驱动456.38,新的报错接踵而至,但是是一样的位置
在Ubuntu20.04下,驱动455.23,Cuda11.1,cudnn8.0.5和GCC9.3下,编译安装Python3.8.6后,再次针对8.6算力编译了TF2.4。情况如下:
如果有想在Ubuntu20.04上用3090和TensorFlow2.4的同学
可以下载这个我编译好的直接用tensorflow-2.4.0-cp38-cp38-linux_x86_64.whl
但并不能止于此
回望目前的问题,如果说是谷歌团队的问题,为何在LINUX下可以正常编译、使用呢?因为没有修改任何源码部分。如果说是驱动的问题,Win10下若干版本驱动也没有OK的情况。如果是新卡的问题,旧卡为何还是一样的错误呢?如果是Cuda和Cudnn的版本问题,同版本Linux却可行。
所以目前的总结是,WIN10下,驱动、cuda、cudnn TF2.4 和操作系统之间,一定存在某个BUG,让TF2.4 出现上述问题。
另外,目前也见过很多Pytorch出现相似表象的问题,但Pytorch的编译使用我不熟悉,希望这些问题的本质是一致的,可以被尽快解决,大家早日用上好用的工具,别再泥坑里陷下去了。