我试图通过编码一些简单的问题来学习tensorflow:我试图找到使用直接采样蒙特卡罗方法的pi的值。评估Tensorflow操作在循环中非常缓慢
运行时间比我认为使用for loop
这样做的时间要长得多。我见过其他类似的东西,我试着按照解决方案,但我认为我仍然必须做错的事情。
附在下面是我的代码:
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
相比较而言,在做numpy的一个for loop
类型的解决方案是一个数量级的速度更快
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
附在下面是整体的差异的曲线图执行不同次数的试验。
请注意:我的问题不是关于“如何执行这一任务最快的”,我承认有计算圆周率的更有效的方法。我只用它作为基准测试工具来检查tensorflow对我熟悉的东西(numpy)的性能。
尽管如此,使用np.sum()并不是一个公平的比较。我更新了我的帖子,总结了使用for循环;但是,速度似乎没有受到影响 – Ben
啊,是的,这个numpy的错了,你应该这样做:'mypi = np.sum(np.sqrt(np.sum(np.square(np.random。统一(size =(2,n_trials))),axis = 0))<1)* 4/n_trials',它比你的代码少100倍的时间。至于问题,我没有说它应该是。它是关于张量流 - 它是为某些操作而设计的,不适用于其他操作。 –
感谢您的回复,但说这是“错误的”是不公平的 - 我只是用它作为基准工具。请您详细说明'sess.run()'中的开销。在这一点上,图表应该最终确定和编制(缺乏更好的术语),并且操作应该非常快速地执行。 – Ben