如何使用 tensorflow 在 GPU 上使用 fp16 进行卷积?(使用 __half 或 Eigen::half 的 python api)。
我想在 tensorflow 上用 fp16 测试一个模型,但我被卡住了。实际上,我发现 tensorflow 中的 fp16 卷积似乎将 fp32 卷积的结果转换为 fp16,这不是我需要的。
我试图给 tf.nn.conv2d 一个 fp16 格式的 fp16 输入,并给 tf.nn.conv2d 一个 fp32 格式的 fp16 输入(tf.cast 到 fp32)然后 tf.cast 结果到 fp16,他们给出了完全相同的结果。但正如我所想,在 fp16 中进行卷积与在 fp32 中进行卷积然后将其转换为 fp16 是不同的,我错了吗?请帮助我,谢谢。
environment:
ubuntu 16.04
tensorflow 1.9.0
cuda 9.0
Tesla V100
import tensorflow as tf
import numpy as np
import os
def conv16_32(input, kernel): # fake fp16 convolution
input = tf.cast(input, tf.float16)
kernel = tf.cast(kernel, tf.float16)
input = tf.cast(input, tf.float32)
kernel = tf.cast(kernel, tf.float32)
out = tf.nn.conv2d(input, kernel, [1,1,1,1], padding='VALID')
out = tf.cast(out, tf.float16)
out = tf.cast(out, tf.float64)
return out
def conv16(input, kernel): # real fp16 convolution
input = tf.cast(input, tf.float16)
kernel = tf.cast(kernel, tf.float16)
out = tf.nn.conv2d(input, kernel, [1,1,1,1], padding='VALID')
out = tf.cast(out, tf.float64)
return out
x = np.random.rand(16, 32, 32, 16).astype('float64')
w = np.random.rand(3, 3, 16, 16).astype('float64')
x = tf.get_variable('input', dtype=tf.float64, initializer=x)
w = tf.get_variable('weight', dtype=tf.float64, initializer=w)
out_16 = conv16(x, w)
out_16_32 = conv16_32(x, w)
os.environ['CUDA_VISIBLE_DEVICES'] = '1'
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
sess = tf.Session(config = config)
sess.run(tf.global_variables_initializer())
sess.run(tf.local_variables_initializer())
print(sess.run(tf.reduce_max(out_16_32 - out_16)))
上述两个函数给出相同的结果,假设最终的“打印”结果为零。
fp16卷积和fp32卷积的结果应该不一样(在我看来)。如何使用 tensorflow 在 GPU 上使用真正的 fp16 进行卷积?(使用 __half 或 Eigen::half 的 python api)