【问题标题】:Is it Ok that creating TensorFlow device multiple times多次创建 TensorFlow 设备可以吗
【发布时间】:2017-07-09 08:40:21
【问题描述】:

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

原代码:

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 毫秒。修改后的日志信息显示有不止一个图,并且在运行过程中创建了tensorflow设备,这是为什么呢?

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 节点零 I 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 张量流/核心/common_runtime/gpu/gpu_device.cc:916] 0:是我 tensorflow/core/common_runtime/gpu/gpu_device.cc:975] 创建 TensorFlow 设备 (/gpu:0) -> (设备: 0, 名称: GeForce GT 730M, pci bus id: 0000:01:00.0) 在 317 毫秒内完成第 3000 张图像

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 bus 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 bus id: 0000:01:00.0) 在 447 毫秒内完成第 3004 个图像

【问题讨论】:

    标签: tensorflow


    【解决方案1】:

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

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

    【讨论】:

    • with-statement 离开时如何清理资源?你能更具体地解释一下吗?
    • 我知道 session.close 可以在离开整个会​​话时使用,而在涉及 with-loop 时,我不确定是否应该在每个 with-statement 离开时调用 session.close?
    【解决方案2】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-27
      • 2011-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-28
      • 2022-01-08
      相关资源
      最近更新 更多