解决TensorFlow sess.run内存溢出:避免循环内动态构建计算图
本文针对TensorFlow在批量测试时因sess.run导致的内存溢出问题,分析发现根源在于for循环内部动态创建tf操作节点,导致计算图无限膨胀。通过将resize_bilinear和argmax等Op移出循环至初始化阶段,可有效防止图节点重复增加,显著降低内存占用并提升推理速度。
问题现象:sess.run导致的内存溢出与性能下降
在调用模型进行批量测试时,代码出现了内存溢出错误。起初怀疑是数据读取方式导致的问题,尝试了tf、PIL和cv等多种图片读取方式,结果发现读取速度越来越慢,内存占用持续飙升。经过调试定位,问题核心在于sess.run的执行过程:随着for循环次数的增加,程序运行速度显著下降,内存消耗急剧上升。
原始代码分析:循环内动态构建计算图
# Creates graph from saved GraphDef
create_graph(pb_path)
# Init tf Session
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
sess = tf.Session(config=config)
init = tf.global_variables_initializer()
sess.run(init)
input_image_tensor = sess.graph.get_tensor_by_name("create_inputs/batch:0")
output_tensor_name = sess.graph.get_tensor_by_name("conv6/out_1:0")
for filename in os.listdir(image_dir):
image_path = os.path.join(image_dir, filename)
start = time.time()
image_data = cv2.imread(image_path)
image_data = cv2.resize(image_data, (w, h))
image_data_1 = image_data - IMG_MEAN
input_image = np.expand_dims(image_data_1, 0)
raw_output_up = tf.image.resize_bilinear(output_tensor_name, size=[h, w], align_corners=True)
raw_output_up = tf.argmax(raw_output_up, axis=3)
predict_img = sess.run(raw_output_up, feed_dict={input_image_tensor: input_image}) # 1,height,width
predict_img = np.squeeze(predict_img) # height, width
voc_palette = visual.make_palette(3)
masked_im = visual.vis_seg(image_data, predict_img, voc_palette)
cv2.imwrite("%s_pred.png" % (save_dir + filename.split(".")[0]), masked_im)
print(time.time() - start)
print(">>>>>>Done")
以下是解决该溢出问题的代码示例,主要改进点是将部分TensorFlow操作代码移至for循环外部执行。
解决方案:将Op操作移出循环
# Creates graph from saved GraphDef
create_graph(pb_path)
# Init tf Session
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
sess = tf.Session(config=config)
init = tf.global_variables_initializer()
sess.run(init)
input_image_tensor = sess.graph.get_tensor_by_name("create_inputs/batch:0")
output_tensor_name = sess.graph.get_tensor_by_name("conv6/out_1:0")
##############################################################################################################
raw_output_up = tf.image.resize_bilinear(output_tensor_name, size=[h, w], align_corners=True)
raw_output_up = tf.argmax(raw_output_up, axis=3)
##############################################################################################################
for filename in os.listdir(image_dir):
image_path = os.path.join(image_dir, filename)
start = time.time()
image_data = cv2.imread(image_path)
image_data = cv2.resize(image_data, (w, h))
image_data_1 = image_data - IMG_MEAN
input_image = np.expand_dims(image_data_1, 0)
predict_img = sess.run(raw_output_up, feed_dict={input_image_tensor: input_image}) # 1,height,width
predict_img = np.squeeze(predict_img) # height, width
voc_palette = visual.make_palette(3)
masked_im = visual.vis_seg(image_data, predict_img, voc_palette)
cv2.imwrite("%s_pred.png" % (save_dir + filename.split(".")[0]), masked_im)
print(time.time() - start)
print(">>>>>>Done")
总结与优化建议:
核心原因:避免循环内重复添加Op节点
在迭代过程中,务必避免在sess.run的for循环内部添加新的TensorFlow op操作。如果在循环中动态添加op,会导致TensorFlow的计算图节点不断累积。随着迭代进行,计算图体积越来越大,最终引发内存溢出错误。
数据读取建议:替换tf.gfile.FastGFile
此外,建议避免使用tf.gfile.FastGFile(image_path, 'rb').read()的方式读取数据,这种方式可能导致内存溢出风险。推荐使用OpenCV等库进行图像读取,以提高稳定性和效率。
以上关于解决TensorFlow sess.run导致内存溢出问题的内容分享完毕,希望能对读者有所帮助。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









