首页 文章

是否可以多次创建TensorFlow设备

提问于
浏览
2

我使用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)

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

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我张量/ / stream_executor / dso_loader.cc:135]在本地成功打开了CUDA库libcufft.so.8.0我的tensorflow / stream_executor / dso_loader.cc:135]在本地成功打开了CUDA库libcuda.so.1我的张量/ 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计算 . I tensorflow / stream_executor / cuda / cuda_gpu_executor.cc:910]从SysFS读取的成功NUMA节点有负值(-1),但必须至少有一个NUMA节点,因此返回NUMA节点零I tensorflow / core / common_runtime / gpu /gpu_device.cc:885]找到具有属性的设备0:名称:GeForce GT 730M major:3 minor: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:YI tensorflow / core / common_runtime / gpu / gpu_device.cc:975]创建TensorFlow设备(/ gpu:0) - >(设备:0,名称:GeForce GT 730M,pci总线ID:0000:01:00.0)完成图像3000 th 317 ms I tensorflow / core / common_runtime / gpu / gpu_device.cc:975]创建TensorFlow设备(/ gpu:0) - >(设备:0,名称:GeForce GT 730M,pci总线ID:0000:01:00.0)完成图像3001 th 325 ms 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)完成图像3003 th 147 ms I tensorflow / core / common_runtime / gpu / gpu_device.cc:975 ]创建TensorFlow设备(/ gpu:0) - >(设备:0,名称:GeForce GT 730M,pci总线ID:0000:01:00.0)在447毫秒内完成图像3004

2 回答

  • 0

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

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

  • 2

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

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

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

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

相关问题