【发布时间】:2019-12-26 16:54:53
【问题描述】:
如何使用 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)
【问题讨论】:
-
还有,当我将tensorflow设置为在CPU而不是GPU上工作时,结果还是一样,所以我认为我使用tensorflow fp16的方式错误。
-
感谢您的澄清,现在帖子已经完成,您有一个合法的关注/问题。
-
可能是小卷积的意外结果。使用 pytorch 再次测试。
-
就像评论一样,
CUDA_VISIBLE_DEVICES只有在导入之前更改它才会对 TensorFlow 产生任何影响。
标签: python c++ tensorflow half-precision-float