【发布时间】:2019-11-21 15:52:20
【问题描述】:
我有多个循环运行的算法。包含 tensorflow 的那些在多次迭代后确实会变慢。
每个文件列表大约有 10,000 个文件,具体取决于它使用的算法。我一次遍历文件列表一个文件,从每个文件创建一个数据框,在数据框上运行我的算法,然后将结果写入数据库。看起来像:
file_list = self.get_files()
for file in file_list:
data = self.get_data(file.fileid)
result = self.get_result(data)
self.write_result
get_result 是针对不同算法的不同函数。他们通常需要 0 - 5 秒来计算每个文件的结果。
我正在使用一种算法,在循环开始时每秒处理 2 个文件,但在几百个文件之后,它会减慢到每个文件一分钟。检查代码它必须是 TF 是瓶颈,因为其余代码相对微不足道。
在get_result 中有以下行,我认为是罪魁祸首:
z = self.evaluate_risk(normalized_X)
def evaluate_risk(self, X):
with tf.device('/cpu:0'):
with tf.Session() as sess:
tf.saved_model.loader.load(sess, model.pb)
graph = tf.get_default_graph()
input_x = graph.get_tensor_by_name("input:0")
risk = graph.get_tensor_by_name("risk:0")
z = sess.run(risk, {input_x: X})
sess.close()
del sess
del graph
return z
鉴于我使用的是with,我不明白为什么这个函数会导致任何问题。我已经添加了sess.close()、del sess 和del graph,但我仍然遇到同样的问题。
每次我有一个新文件并到达 result 时,我都应该从头开始 tensorflow。我的循环变慢有什么明显的原因吗?我猜 tensorflow 的某些部分没有重置。
【问题讨论】:
-
主要问题在于
tf.saved_model.loader.load,它会多次加载模型并用副本填充图形。您可以修复用with tf.Graph().as_default(), tf.Session() as sess:替换with tf.Session() as sess:,但理想情况下,您应该在该函数之外加载模型一次。为了使事情稍微快一点,您也可以只调用一次get_tensor_by_name(例如,将返回值保存在self.input_x等实例变量中)。延迟的第二个来源是会话的创建,创建单个会话并重用它要快得多。 -
在这里加载一次是行不通的。我的 file_list 随着时间的推移而增加,在运行 10k 之后,我预计每天添加约 10 个文件。该模型是根据历史数据开发的,现在用于新的传入数据。为什么
del graph行不处理用副本填充图表? -
KeyError: “名称‘input:0’指的是一个不存在的张量。操作‘input’在图中不存在。”
-
我认为对
file_list的更改不会影响此处,您只会将{input_x: X}中的不同X传递给同一个图表。del graph不执行任何操作,您使用的是默认图,并且仅删除了该引用,但 TensorFlow 内部仍引用它(因此未释放)。
标签: python performance loops tensorflow