python - with - La evaluación de la operación de Tensorflow es muy lenta en un ciclo
tensorflow tutorial (2)
Simple, session.run tiene mucha sobrecarga, y no está diseñado para usarse de esa manera. Normalmente, al tener, por ejemplo, una red neuronal, se podría llamar a una sola sesión. Ejecutar una docena de multiplicaciones de matrices grandes, entonces este 0,2 ms que llevaría no importaría en absoluto. En cuanto a su caso, probablemente quería algo así. Funciona 5 veces más rápido que la versión numpy en mi máquina.
Por cierto, haces exactamente lo mismo en numpy. Si utilizó loop para reducir en lugar de np.sum, sería mucho más lento.
import tensorflow as tf
import numpy as np
import time
n_trials = 50000
tf.reset_default_graph()
x = tf.random_uniform(shape=(n_trials,), name=''x'')
y = tf.random_uniform(shape=(), name=''y'')
r = tf.sqrt(x**2 + y**2)
hit = tf.Variable(0, name=''hit'')
# perform the monte carlo step
is_inside = tf.cast(tf.less(r, 1), tf.int32)
hit2= tf.reduce_sum(is_inside)
#hit_op = hit.assign_add(is_inside)
with tf.Session() as sess:
# init_op = tf.global_variables_initializer()
sess.run(tf.initialize_all_variables())
# Make sure no new nodes are added to the graph
sess.graph.finalize()
start = time.time()
# Run monte carlo trials -- This is very slow
#for _ in range(n_trials):
sess.run(hit2)
hits = hit2.eval()
print("Pi is {}".format(4*hits/n_trials))
print("Tensorflow operation took {:.2f} s".format((time.time()-start)))
Intento aprender tensorflow codificando algunos problemas simples: estaba tratando de encontrar el valor de pi usando un método de Monte Carlo de muestreo directo.
El tiempo de ejecución es mucho más largo de lo que pensé que sería al usar un for loop
para hacer esto. He visto otras publicaciones sobre cosas similares y he tratado de seguir las soluciones, pero creo que todavía debo estar haciendo algo mal.
Adjunto a continuación está mi código:
import tensorflow as tf
import numpy as np
import time
n_trials = 50000
tf.reset_default_graph()
x = tf.random_uniform(shape=(), name=''x'')
y = tf.random_uniform(shape=(), name=''y'')
r = tf.sqrt(x**2 + y**2)
hit = tf.Variable(0, name=''hit'')
# perform the monte carlo step
is_inside = tf.cast(tf.less(r, 1), tf.int32)
hit_op = hit.assign_add(is_inside)
with tf.Session() as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
# Make sure no new nodes are added to the graph
sess.graph.finalize()
start = time.time()
# Run monte carlo trials -- This is very slow
for _ in range(n_trials):
sess.run(hit_op)
hits = hit.eval()
print("Pi is {}".format(4*hits/n_trials))
print("Tensorflow operation took {:.2f} s".format((time.time()-start)))
>>> Pi is 3.15208
>>> Tensorflow operation took 8.98 s
En comparación, hacer una solución tipo for loop
en numpy es un orden de magnitud más rápido
start = time.time()
hits = [ 1 if np.sqrt(np.sum(np.square(np.random.uniform(size=2)))) < 1 else 0 for _ in range(n_trials) ]
a = 0
for hit in hits:
a+=hit
print("numpy operation took {:.2f} s".format((time.time()-start)))
print("Pi is {}".format(4*a/n_trials))
>>> Pi is 3.14032
>>> numpy operation took 0.75 s
Se adjunta a continuación un gráfico de la diferencia en los tiempos de ejecución general para varios números de ensayos.
Tenga en cuenta: mi pregunta no es sobre "cómo realizar esta tarea más rápido", reconozco que hay formas mucho más efectivas de calcular Pi. Solo he usado esto como una herramienta de evaluación comparativa para comprobar el rendimiento de tensorflow en contra de algo con lo que estoy familiarizado (numpy).
La velocidad lenta tiene que ver con algunos gastos indirectos de comunicación entre Python y Tensorflow en sess.run
, que se ejecuta varias veces dentro de su ciclo. Sugeriría usar tf.while_loop
para ejecutar los cálculos dentro de Tensorflow. Esa sería una mejor comparación sobre numpy
.
import tensorflow as tf
import numpy as np
import time
n_trials = 50000
tf.reset_default_graph()
hit = tf.Variable(0, name=''hit'')
def body(ctr):
x = tf.random_uniform(shape=[2], name=''x'')
r = tf.sqrt(tf.reduce_sum(tf.square(x))
is_inside = tf.cond(tf.less(r,1), lambda: tf.constant(1), lambda: tf.constant(0))
hit_op = hit.assign_add(is_inside)
with tf.control_dependencies([hit_op]):
return ctr + 1
def condition(ctr):
return ctr < n_trials
with tf.Session() as sess:
tf.global_variables_initializer().run()
result = tf.while_loop(condition, body, [tf.constant(0)])
start = time.time()
sess.run(result)
hits = hit.eval()
print("Pi is {}".format(4.*hits/n_trials))
print("Tensorflow operation took {:.2f} s".format((time.time()-start)))