首页 > 解决方案 > 为什么 tf.concat 比 np.concatenate 和原生 python 列表的“追加”慢得多?如果可能,我们应该避免吗?

问题描述

我正在使用 Tensorflow 实现一个数学库,它tf.concat经常在内部调用。我很好奇它的速度tf.concat。为了测试,我创建了以下简单的代码来比较速度tf.concatnp.concatenate以及append原生 python 列表的方法。当然,在下面的例子中,我们可以使用tf.rangeandnp.arange来获得更好的效率。就我而言,我想检查tf.concat实际数学库中的速度,我需要任意添加元素。

#/usr/bin/python3
import tensorflow as tf
import numpy as np  
import time

x_tf = tf.constant([], dtype=tf.dtypes.float32)
x_np = np.array([], dtype=np.float32)
x_list = []
limit = 10000

start_time = time.time()
for i in range(limit):
    x_list.append(np.float32(i))
print("Elapsed time: {0}".format(time.time() - start_time))

start_time = time.time()
for i in range(limit):
    x_np = np.concatenate((x_np, [i]), axis=0)
print("Elapsed time: {0}".format(time.time() - start_time))

start_time = time.time()
for i in range(limit):
    x_tf = tf.concat((x_tf, [i]), axis=0)
print("Elapsed time: {0}".format(time.time() - start_time))

当我同时使用 CPU 和 GPU 进行测试时,Tensorflow 版本最慢,numpy 版本次之。原生 python 数组在很大程度上是最快的。以下是结果。

2021-01-02 22:00:20.438159: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1402] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 11271 MB memory) -> physical GPU (device: 0, name: GeForce GTX TITAN X, pci bus id: 0000:0a:00.0, compute capability: 5.2)
Elapsed time: 0.004985332489013672
Elapsed time: 0.06686067581176758
Elapsed time: 2.0447843074798584

因为速度上的差异是巨大的,所以如果可能的话,似乎最好避免使用 tf.concat。在这种情况下,似乎最好使用 Native Python 列表进行所有处理,并且只将最终列表转换为张量。

谁能告诉我我的理解是否正确并给出一些建议或意见?

标签: pythonperformancenumpytensorflow

解决方案


np.concatenate正在增长一个数组,这与追加到列表不同;在循环的每一轮中都必须分配一个新的内存块,大小为 n+1,因此如果您一次插入一个项目,列表自然append会更快。

Numpy 和 tensorflow 针对数组或张量操作进行了优化。例如,您可以在没有循环的情况下创建相同的 numpy 数组:np_array = np.arange(limit),这将比您的循环快得多append


推荐阅读