是否可以多次创建TensorFlow设备

时间:2017-02-20 06:58:48

标签: tensorflow

我使用tensorflow API运行图像处理脚本。事实证明,当我在会话运行过程之外设置for循环时,处理时间迅速减少。谁能告诉我为什么?有副作用吗?

原始代码:

with tf.Session() as sess:
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
for i in range(len(file_list)):
    start = time.time()
    image_crop, bboxs_crop = sess.run(crop_image(file_list[i], bboxs_list[i], sess))
    print( 'Done image %d th in %d ms \n'% (i, ((time.time() - start)*1000)))
    # image_crop, bboxs_crop, image_debug = sess.run(crop_image(file_list[i], bboxs_list[i], sess))
    labels, bboxs = filter_bbox(labels_list[i], bboxs_crop)
    # Image._show(Image.fromarray(np.asarray(image_crop)))
    # Image._show(Image.fromarray(np.asarray(image_debug)))
    save_image(image_crop, ntpath.basename(file_list[i]))
    #save_desc_file(file_list[i], labels_list[i], bboxs_crop)
    save_desc_file(file_list[i], labels, bboxs)
coord.request_stop()
coord.join(threads)

修改了代码:

for i in range(len(file_list)):
with tf.Graph().as_default(), tf.Session() as sess:
    start = time.time()
    image_crop, bboxs_crop = sess.run(crop_image(file_list[i], bboxs_list[i], sess))
    print( 'Done image %d th in %d ms \n'% (i, ((time.time() - start)*1000)))
    labels, bboxs = filter_bbox(labels_list[i], bboxs_crop)
    save_image(image_crop, ntpath.basename(file_list[i]))
    save_desc_file(file_list[i], labels, bboxs)

原始代码的时间成本将从200毫秒增加到甚至20000毫秒。在修改之后,日志消息表明在运行期间创建了多个图形和张量流设备,为什么会这样?

  

python random_crop_images_hongyuan.py我   tensorflow / stream_executor / dso_loader.cc:135]成功打开了CUDA   库libcublas.so.8.0本地我   tensorflow / stream_executor / dso_loader.cc:135]成功打开了CUDA   本地图书馆libcudnn.so.5我   tensorflow / stream_executor / dso_loader.cc:135]成功打开了CUDA   本地库libcufft.so.8.0我   tensorflow / stream_executor / dso_loader.cc:135]成功打开了CUDA   本地库libcuda.so.1我   tensorflow / stream_executor / dso_loader.cc:135]成功打开了CUDA   库libcurand.so.8.0本地W   tensorflow / core / platform / cpu_feature_guard.cc:45] TensorFlow   库没有被编译为使用SSE3指令,但这些是   在您的机器上可用,可以加快CPU计算。 w ^   tensorflow / core / platform / cpu_feature_guard.cc:45] TensorFlow   库没有被编译为使用SSE4.1指令,但这些是   在您的机器上可用,可以加快CPU计算。 w ^   tensorflow / core / platform / cpu_feature_guard.cc:45] TensorFlow   库没有被编译为使用SSE4.2指令,但这些是   在您的机器上可用,可以加快CPU计算。 w ^   tensorflow / core / platform / cpu_feature_guard.cc:45] TensorFlow   库没有被编译为使用AVX指令,但这些是   在您的机器上可用,可以加快CPU计算。 w ^   tensorflow / core / platform / cpu_feature_guard.cc:45] TensorFlow   库没有被编译为使用AVX2指令,但这些是   在您的机器上可用,可以加快CPU计算。 w ^   tensorflow / core / platform / cpu_feature_guard.cc:45] TensorFlow   库没有被编译为使用FMA指令,但这些是   在您的机器上可用,可以加快CPU计算。一世   tensorflow / stream_executor / cuda / cuda_gpu_executor.cc:910]成功   从SysFS读取的NUMA节点具有负值(-1),但必须存在   至少有一个NUMA节点,因此返回NUMA节点为零   tensorflow / core / common_runtime / gpu / gpu_device.cc:885]找到设备0   具有属性:名称:GeForce GT 730M专业:3个未成年人:5   memoryClockRate(GHz)0.758 pciBusID 0000:01:00.0总内存:   982.88MiB可用内存:592.44MiB I tensorflow / core / common_runtime / gpu / gpu_device.cc:906] DMA:0 I   tensorflow / core / common_runtime / gpu / gpu_device.cc:916] 0:Y I   tensorflow / core / common_runtime / gpu / gpu_device.cc:975]创建   TensorFlow设备(/ gpu:0) - > (设备:0,名称:GeForce GT 730M,pci   bus id:0000:01:00.0)在317 ms完成图像3000 th

     

I tensorflow / core / common_runtime / gpu / gpu_device.cc:975]创建   TensorFlow设备(/ gpu:0) - > (设备:0,名称:GeForce GT 730M,pci   总线ID:0000:01:00.0)在325毫秒内完成图像3001

     

I tensorflow / core / common_runtime / gpu / gpu_device.cc:975]创建   TensorFlow设备(/ gpu:0) - > (设备:0,名称:GeForce GT 730M,pci   总线ID:0000:01:00.0)在312毫秒内完成图像3002

     

I tensorflow / core / common_runtime / gpu / gpu_device.cc:975]创建   TensorFlow设备(/ gpu:0) - > (设备:0,名称:GeForce GT 730M,pci   总线ID:0000:01:00.0)在147毫秒内完成图像3003

     

I tensorflow / core / common_runtime / gpu / gpu_device.cc:975]创建   TensorFlow设备(/ gpu:0) - > (设备:0,名称:GeForce GT 730M,pci   总线ID:0000:01:00.0)在447 ms内完成图像3004

2 个答案:

答案 0 :(得分:2)

我的猜测是,这是因为创建会话是一项昂贵的操作。可能会发生在留下with语句时未正确清理会话的情况,因此设备上的每个新分配都将具有较少的可用资源。简而言之,我不建议这样做,而是初始化一个会话并尝试重用它。

编辑: 回答你的评论:一旦退出with-block,会话就会自动关闭。我在this github issue中读到,GPU上的内存只有在整个程序退出时才会真正释放。但我想当你在关闭最后一个会话后分配一个新会话时,Tensorflow将在内部重新使用以前分配的资源。所以,回顾一下,我的回答可能不是很有见地。对不起,如果我引起混淆。

答案 1 :(得分:0)

如果没有看到所有代码,就不可能100%确定,但我猜想crop_image()函数正在调用各种TensorFlow操作函数来构建图形。

for循环中构建图形几乎绝不是一个好主意。 This answer解释了原因:某些操作(例如对新操作的第一个Session.run()调用)花费的时间与图中的操作数成线性关系。如果在每次迭代中添加更多操作,迭代i将在i中执行线性工作,因此总执行时间将是二次的。

代码的修改版本(循环内部带有with tf.Graph().as_default():块)会更快,因为它会在每次迭代中创建一个新的空tf.Graph,因此每次迭代都会执行一定量的工作

更有效的解决方案是构建图形和会话一次,使用tf.placeholder()张量来表示crop_image的文件名和bbox参数,并在每次迭代中为这些占位符提供不同的值。