针对Win10 Tensorflow-2.4 训练 线程冻结(假死、卡住、几个epoch后、中途停滞、CPU占用0%) 等问题的排查总结

2020.12.22更新

我佛了,bug的一个合适的解决途径终于找到了,一定要开GPU硬件加速
针对Win10 Tensorflow-2.4 训练 线程冻结(假死、卡住、几个epoch后、中途停滞、CPU占用0%) 等问题的排查总结_第1张图片
那我这些天的debug真是醉了

如果有想在Ubuntu20.04上用3090和TensorFlow2.4的同学
可以下载这个我编译好的直接用tensorflow-2.4.0-cp38-cp38-linux_x86_64.whl


0.前言(事情很复杂)

事件背景如下:30系显卡出来后,需要针对8.6算力对TensorFlow2.x进行重新编译,才可顺畅使用,若非重新编译,每次运行都会进行一次预编译,极其浪费时间。一般的,大家会选择一下两种办法:

  1. 等官方编译发行到:PyPI 上,安装官方使用的环境,进行使用
  2. 自行编译,可以决定想要的Cuda和cudnn版本。一般会选择更加新的版本,获得一点点优化和提升。

这里,我一直以来都是选择后者,自行编译使用。自从解决了TF2.3.x在win10下的编译问题后,已经在TF2.3.x 使用了半年之久。下面总结一下TF2.3.x 在win10下对8.6算力的卡的编译问题:

  1. 官方环境仅支持cuda11.0 但是编译过的同学都知道,cuda11.0不支持8.6算力,自行编译会报错,提示一个和8.6算力相关的文件无法取得。这其中是否还有在cuda11.0下正确编译8.6算力的方法,我无从得知,但是似乎官方的编译是可以做到的,可我不会,以我会的角度,必须升级到至少cuda11.1 才可以
  2. TF2.3.0 TF2.3.1 在Win10、Cuda11.1、cudnn8.0.5 和python3.8.6下 是可以对8.6算力编译成功的,完全可以正常使用,所有的原来在7.5算力的卡下跑过的程序都完全正常运行。
  3. 但是,TF2.3.x 目前已经算旧版本了,尤其是混合精度部分,变化很大,而我的实验又必须使用混合精度,所以,即便TF2.3.x 可以正常使用,我还是要去TF2.4试试

1. TF2.4的编译与使用问题

TF2.4 吸取了TF2.3的问题经验,没有在Win10下报恶性的编译错误(不再需要自行修改文件等等),编译很顺畅。

1.1 编译问题

  1. Cuda11.0不支持8.6算力,编译失败
  2. Cuda11.1 依据官方教程,即可编译成功,Cudnn为8.0.5
  3. Cuda11.2 依据官方教程,即可编译成功,但是目前还没有出Cuda11.2对应的Cudnn,用的是Cuda11.1的cudnn8.0.5代替
  4. 编译过程中,CPU、内存会影响C++编译器,报一些很奇怪的编译器错误(因为我没法完全记录这个过程,编译器错误大致会出现很多地址,如果选择默认C++路径的话会是C:/Program File(x86)…然后直指编译器balabala)甚至蓝屏,编译时尽量不要超CPU和超内存,同时尽量减少计算机的使用,可以用 -j n 命令控制bazel的线程数 避免吃满线程。血泪教训的经验,我不知怎么解释,但是真的是事实。另外还有一个经验,如果两次编译,都在后半段报错,且报错的内容不一致,很可能没有错,只是超频了或者线程吃满影响编译器了。(我不知道我怎么说得出这么不专业的话的,希望专业人士可以解释一二,CPU和内存超频很多后,会报错,降频后编译正常成功,这就是我自己的事实依据。)

1.2 使用问题(大坑)

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. 线程假死、卡住,此时运行的python控制台无法ctrl+C结束,对应CPU占用为0%
  2. F .\tensorflow/core/kernels/conv_2d_gpu.h:714] Non-OK-status: GpuLaunchKernel( SwapDimension1And2InTensor3UsingTiles, total_tiles_count, NumThreads, 0, d.stream(), input, input_dims, output) status: Internal: unspecified launch failure 的报错,对应CPU占用也为0%,但一段时间后,可以自行结束
  3. 正常通过,几乎没出现过。

截图参考
情况1 假死
针对Win10 Tensorflow-2.4 训练 线程冻结(假死、卡住、几个epoch后、中途停滞、CPU占用0%) 等问题的排查总结_第2张图片
情况2 报错
针对Win10 Tensorflow-2.4 训练 线程冻结(假死、卡住、几个epoch后、中途停滞、CPU占用0%) 等问题的排查总结_第3张图片
以上的情况,都是在不修改代码,而是先后运行测试程序下的考证,随机出现,没有规律。
后来,单步调试该问题,发现并没有出错,于是脑洞一开
加上一个延时,模拟单步调试的过程,代码如下

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秒延迟
        ... 
        ...

发现,以上的情况1 情况2再也没有遇到过。截图为证
针对Win10 Tensorflow-2.4 训练 线程冻结(假死、卡住、几个epoch后、中途停滞、CPU占用0%) 等问题的排查总结_第4张图片

1.3 后续

现象总结为,自定义层测试时出现线程冻结、假死、CPU占用为0% 或者 Non-OK-status的报错,给测试代码加上延时,解决上述问题,但是拖长了运行时间,得不偿失。

显而易见:

  1. 并非自定义层的写法问题。
  2. 可能是TF2.4的问题
  3. 可能是Cuda的问题
  4. 可能是Cudnn的问题
  5. 可能是Win10的问题
  6. 可能是驱动的问题。但是TF2.3.x则不会如此,如果是驱动问题,也无法断定哪个版本可行。
  7. 可能是新卡的问题

为了缩小范围,我针对6.1算力的1080重新编译了TF2.4 问题依旧。那么可以大概率的确定,不是新卡的问题,旧卡也会出现一样的情况。如果是驱动问题,那为何TF2.3就可行呢。退回最原始的驱动456.38,新的报错接踵而至,但是是一样的位置
针对Win10 Tensorflow-2.4 训练 线程冻结(假死、卡住、几个epoch后、中途停滞、CPU占用0%) 等问题的排查总结_第5张图片

2 Linux下尝试TF2.4尝试

在Ubuntu20.04下,驱动455.23,Cuda11.1,cudnn8.0.5和GCC9.3下,编译安装Python3.8.6后,再次针对8.6算力编译了TF2.4。情况如下:

  1. 编译通过(编译过程中出现的都是小问题,轻松解决)
  2. 测试通过
  3. 正常运行所有原先的TF程序!!!终于可以开始新的科研了。

如果有想在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的编译使用我不熟悉,希望这些问题的本质是一致的,可以被尽快解决,大家早日用上好用的工具,别再泥坑里陷下去了。

你可能感兴趣的:(深度学习,tensorflow,pytorch)