在张量流模型训练中启用混合精度会降低速度而不是增加速度

时间:2021-02-25 10:50:22

标签: python tensorflow keras

我使用 NVIDIA RTX-2060(带有图灵核心)进行深度学习模型训练。正如在线论坛上提到的,启用混合精度训练有助于图灵架构卡比没有混合精度训练的训练速度更快。当我启用混合精度训练时,每步时间增加而不是减少。我无法理解为什么会发生这种情况,我真的很感激有人提出解决方案。我花了这么多钱买这个gpu,不能让它更快地训练模型也没有用。

代码:

import tensorflow as tf
def create_model():
    model = keras.Sequential([
        keras.layers.Flatten(input_shape=(32,32,3)),
        keras.layers.Dense(3000, activation='relu'),
        keras.layers.Dense(1000, activation='relu'),
        keras.layers.Dense(10, activation='sigmoid')
    ])

    
    model.compile(optimizer= 'SDG',
                 loss= 'categorical_crossentropy',
                 metrics=['accuracy'])
    
    return model

tf.keras.mixed_precision.set_global_policy('mixed_float16')

%%timeit -n1 -r1 # time required toexecute this cell once

model = create_model()
model.fit(X_train_scaled, y_train_categorical, epochs=50)

您必须知道的事情:

<块引用>

我已经成功安装了 cuda 和 cudnn,tensorflow 可以检测到我的 gpu。

<块引用>

我已经安装了 tensorflow-gpu。

<块引用>

我正在使用 nvidia rtx 2060 gpu 在 ciphar10 数据集上训练我的模型。

我一直使用 Jupyter Notebook 进行基准测试:Link

2 个答案:

答案 0 :(得分:3)

当您使用 CIFAR 数据集时,我认为您的最后一层激活应该 softmax 而不是 sigmoid,您的损失函数也是 categorical_crossentropy .并确保它是 float32

keras.layers.Dense(10, activation='softmax', dtype=tf.float32)

您应该在刚开始导入 tf 之后设置混合精度全局策略。以下是在 GPU 上使用混合精度时的一些提示。来自Doc

增加批量大小

如果不影响模型质量,请在使用 batch size 时尝试使用双倍 mixed precision 运行。由于 float16 张量使用一半的内存,这通常允许您将 batch size 加倍而不会内存不足。增加 batch size 通常会增加训练吞吐量,即您的模型每秒可以运行的训练元素数。

确保使用 GPU Tensor 核心

现代 NVIDIA GPU 使用称为张量核心的特殊硬件单元,可以非常快速地乘以 float16 矩阵。但是,张量核心要求张量的某些维度是8的倍数。

在下面的示例中,当且仅当参数需要是 8 的倍数才能使用 Tensor Core 时,参数才为粗体。

  • tf.keras.layers.Dense(units=64)
  • tf.keras.layers.Conv2d(filters=48, kernel_size=7, stride=3)
  • tf.keras.layers.LSTM(units=64)
  • tf.keras.Model.fit(epochs=2, batch_size=128)

如果您正确遵循此过程,那么您应该可以利用 mixed-precisionHere 是 NVIDIA 的一本好读物。

答案 1 :(得分:0)

根据 Tensorflow 的官方指南,要正确使用混合精度,模型末尾的 sigmoid 激活应为 float32。因为我们设置了策略 mixed_float16,所以激活的 compute_dtypefloat16。因此,我们必须将此层的策略覆盖为 float32

def create_model():
    model = keras.Sequential([
        keras.layers.Flatten(input_shape=(32, 32, 3)),
        keras.layers.Dense(3000, activation='relu'),
        keras.layers.Dense(1000, activation='relu'),
        # keras.layers.Dense(10, activation='sigmoid'), # NOTE: Replaced this line by two lines below
        keras.layers.Dense(10,),
        keras.layers.Activation('sigmoid', dtype='float32'),
    ])

    model.compile(optimizer='SGD',
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])

    return model

将所有内容放在一起,我们就有了用于训练混合精度 CIFAR10 数据集的完整源代码:

import tensorflow as tf
from tensorflow import keras


def create_model():
    model = keras.Sequential([
        keras.layers.Flatten(input_shape=(32, 32, 3)),
        keras.layers.Dense(3000, activation='relu'),
        keras.layers.Dense(1000, activation='relu'),
        # keras.layers.Dense(10, activation='sigmoid'),
        keras.layers.Dense(10,),
        keras.layers.Activation('sigmoid', dtype='float32'),
    ])

    model.compile(optimizer='SGD',
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])

    return model


tf.keras.mixed_precision.set_global_policy('mixed_float16')

(X_train, y_train), (X_test, y_test) = tf.keras.datasets.cifar10.load_data()

# There are 10 image classes
classes = ["airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", "ship", "truck"]

X_train_scaled = X_train / 255
X_test_scaled = X_test / 255

y_train_categorical = keras.utils.to_categorical(y_train, num_classes= 10, dtype='float')
y_test_categorical = keras.utils.to_categorical(y_test, num_classes= 10, dtype='float')

with tf.device('/GPU:0'):
    model = create_model()
    model.fit(X_train_scaled, y_train_categorical, epochs=50)

model.evaluate(X_test_scaled, y_test_categorical)

使用我的 GPU NVIDIA RTX2080,我使用混合精度比较了使用(称为 P1)和不使用(称为 P2)的性能,发现:

  1. 训练时间:因为每一步的时间是四舍五入的,而且 P1P2 的时间是一样的(~6 毫秒),我比较了 50 次的总训练时间P1 的 epochs 明显快于 P2(464s 与 501s)。
  2. 测试时间P1 仍然比 P2 快(3 毫秒/步 vs 4 毫秒/步)
  3. 测试性能 (acc)P1 优于 P2(~55.61% vs ~50.77%)