TensorFlow: есть ли способ измерить флопы для модели?
ближайший пример, который я могу получить, находится в этой проблеме:https://github.com/tensorflow/tensorflow/issues/899
С этим минимальным воспроизводимым кодом:
import tensorflow as tf
import tensorflow.python.framework.ops as ops
g = tf.Graph()
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) # shape=[25,9]
for op in g.get_operations():
flops = ops.get_stats_for_node_def(g, op.node_def, 'flops').value
if flops is not None:
print 'Flops should be ~',2*25*16*9
print '25 x 25 x 9 would be',2*25*25*9 # ignores internal dim, repeats first
print 'TF stats gives',flops
однако возвращаемые флопы всегда отсутствуют. Есть ли способ конкретно измерить флопы, особенно с файлом PB?
2 ответов
немного поздно, но, возможно, это поможет некоторым посетителям в будущем. Для вашего примера я успешно протестировал следующий фрагмент:
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) # shape=[25,9]
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('25 x 25 x 9 would be',2*25*25*9) # ignores internal dim, repeats first
print('TF stats gives',flops.total_float_ops)
также можно использовать профилировщик в сочетании с Keras
как следующий фрагмент:
import tensorflow as tf
import keras.backend as K
from keras.applications.mobilenet import MobileNet
run_meta = tf.RunMetadata()
with tf.Session(graph=tf.Graph()) as sess:
K.set_session(sess)
net = MobileNet(alpha=.75, input_tensor=tf.placeholder('float32', shape=(1,32,32,3)))
opts = tf.profiler.ProfileOptionBuilder.float_operation()
flops = tf.profiler.profile(sess.graph, run_meta=run_meta, cmd='op', options=opts)
opts = tf.profiler.ProfileOptionBuilder.trainable_variables_parameter()
params = tf.profiler.profile(sess.graph, run_meta=run_meta, cmd='op', options=opts)
print("{:,} --- {:,}".format(flops.total_float_ops, params.total_parameters))
надеюсь, я мог бы помочь!
я хотел бы построить на ответе Тобиаса шнека, а также ответить на первоначальный вопрос: Как получить флоп от .
запуск первого фрагмента кода из ответа Tobias с 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
несколько инициализированный. Инициализация с гауссовским распределением стоит некоторого флопа. Изменение определения A
и B
by
A = tf.Variable(initial_value=tf.zeros([25, 16]))
B = tf.Variable(initial_value=tf.zeros([16, 9]))
дает ожидаемый результат 7200
.
обычно переменные сети инициализируются гауссовыми распределениями среди других схем. В большинстве случаев нас не интересует флоп инициализации, поскольку они выполняются один раз во время инициализации и не происходят во время обучения или вывода. Итак,как может один получает точное количество флопа, игнорируя флоп инициализации?
заморозить графе С pb
. Расчет флопе от pb
файл был, на самом деле, вариантом использования 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
# ***** (1) Create 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)
# *****************************
# ***** (2) freeze graph *****
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())
# *****************************
# ***** (3) Load frozen graph *****
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] обычно флоп умножения матрицы равен mq (2p -1) для произведения AB, где A[m, p]
и B[p, q]
но TensorFlow почему-то возвращает 2mpq. Ан вопрос был открыт, чтобы понять, почему.