我希望在托比亚斯·施内克的回答基础上进行补充,同时回答原始问题:如何从pb
文件中获取FLOP。
在TensorFlow 1.6.0中运行托比亚斯回答中的第一段代码:
g = tf.Graph()
run_meta = tf.RunMetadata()
with g.as_default():
A = tf.Variable(tf.random_normal([25,16]))
B = tf.Variable(tf.random_normal([16,9]))
C = tf.matmul(A,B)
opts = tf.profiler.ProfileOptionBuilder.float_operation()
flops = tf.profiler.profile(g, run_meta=run_meta, cmd='op', options=opts)
if flops is not None:
print('Flops should be ~',2*25*16*9)
print('TF stats gives',flops.total_float_ops)
我们得到以下输出:
Flops should be ~ 7200
TF stats gives 8288
那么,为什么我们得到了8288
而不是预期的结果7200=2*25*16*9
[a]?答案在于张量A
和B
的初始化方式。用高斯分布进行初始化会消耗一些FLOP。通过改变A
和B
的定义来解决:
A = tf.Variable(initial_value=tf.zeros([25, 16]))
B = tf.Variable(initial_value=tf.zeros([16, 9]))
给出预期输出7200
。
通常,网络的变量会初始化为高斯分布等方案之一。大多数情况下,我们对初始化FLOP不感兴趣,因为它们只在初始化过程中执行一次,并且不会在训练或推断过程中发生。那么,如何获得完全忽略初始化FLOP的确切FLOP数量呢?
冻结图表使用pb
。实际上,从pb
文件计算FLOP是OP的使用情况。
以下代码片段说明了这一点:
import tensorflow as tf
from tensorflow.python.framework import graph_util
def load_pb(pb):
with tf.gfile.GFile(pb, "rb") as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
with tf.Graph().as_default() as graph:
tf.import_graph_def(graph_def, name='')
return graph
g = tf.Graph()
sess = tf.Session(graph=g)
with g.as_default():
A = tf.Variable(initial_value=tf.random_normal([25, 16]))
B = tf.Variable(initial_value=tf.random_normal([16, 9]))
C = tf.matmul(A, B, name='output')
sess.run(tf.global_variables_initializer())
flops = tf.profiler.profile(g, options = tf.profiler.ProfileOptionBuilder.float_operation())
print('FLOP before freezing', flops.total_float_ops)
output_graph_def = graph_util.convert_variables_to_constants(sess, g.as_graph_def(), ['output'])
with tf.gfile.GFile('graph.pb', "wb") as f:
f.write(output_graph_def.SerializeToString())
g2 = load_pb('./graph.pb')
with g2.as_default():
flops = tf.profiler.profile(g2, options = tf.profiler.ProfileOptionBuilder.float_operation())
print('FLOP after freezing', flops.total_float_ops)
输出
FLOP before freezing 8288
FLOP after freezing 7200
[a] 矩阵乘法的 FLOP 通常是 mq(2p-1) 其中 A[m,p] 和 B[p,q] 的乘积 AB,但是 TensorFlow 出于某些原因返回了 2mpq。已经开放了一个问题以了解原因。