将Numpy数组转换为TensorFlow张量的成本是多少?

将Numpy数组转换为TensorFlow张量的成本是多少?,tensorflow,keras,Tensorflow,Keras,我在GPU上使用tf.keras.Model.fit(),输入为tf.keras.utils.Sequence生成批Numpy数组。当生成的输入或目标Numpy数组很大时,我注意到训练速度显著减慢。当然,部分原因是由于主机(CPU)到设备(GPU)的传输,但我看到的时间表明在其他地方会有额外的开销 下面是一个再现该问题的最小示例。为了简单起见,Numpy数组是在data\u sequence开始生成批之前创建的,因此data\u sequence[idx]几乎不做任何工作。此外,该模型由单个线性

我在GPU上使用
tf.keras.Model.fit()
,输入为
tf.keras.utils.Sequence
生成批
Numpy
数组。当生成的输入或目标
Numpy
数组很大时,我注意到训练速度显著减慢。当然,部分原因是由于主机(CPU)到设备(GPU)的传输,但我看到的时间表明在其他地方会有额外的开销

下面是一个再现该问题的最小示例。为了简单起见,
Numpy
数组是在
data\u sequence
开始生成批之前创建的,因此
data\u sequence[idx]
几乎不做任何工作。此外,该模型由单个线性激活组成,该激活应转换为NoOp

导入tqdm
将numpy作为np导入
导入tensorflow作为tf
从tensorflow.keras.utils导入序列
类numpsequence(序列):
定义初始化(self,x,y):
self.x=x
self.y=y
定义(自我):
返回len(self.x)
def uu getitem uu(self,idx):
返回self.x[idx],self.y[idx]
工人=1
每个历元的步数,历元=100,10
N、 H,W,C=41000010
x_列车=[]
y_train=[]
rng=np.random.default\u rng()
对于tqdm.tqdm中的步长(范围(每个历元的步长)):
x\u序列附加(rng.standard\u normal(大小=(N,H,W,C),数据类型=np.float32))
y\u序列追加(rng.standard\u normal(大小=(N,H,W,C),数据类型=np.float32))
数据序列=数字序列(x序列、y序列)
model=tf.keras.models.Sequential([tf.keras.layers.Activation(“linear”)]))
compile(optimizer='adam',loss=tf.keras.loss.CategoricalCrossentropy())
拟合(数据顺序,历元=历元,工作者=工作者)
在NVIDIA Tesla V100 GPU上,我得到:

Epoch 1/10
100/100 [==============================] - 90s 899ms/step - loss: -3.4149e-04
Epoch 2/10
100/100 [==============================] - 91s 907ms/step - loss: -3.4149e-04
...
每批组合的输入和目标
Numpy
数组的大小为
2*N*H*W*C*sizeof(np.float32)=320 MB
。CPU到GPU的传输带宽应约为
12.4 GB/s
,例如,根据NVIDIA提供的:

Host to Device Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)        Bandwidth(GB/s)
   32000000                     12.4
因此,CPU到GPU的传输无法单独解释每批的1s。增加工人数量并不能带来进步

是不是
TensorFlow
Numpy
数组进行了一些额外的序列化或内存拷贝?如果是的话,有什么方法可以预防吗?

我知道
tf.data.Dataset
及其应用的优化。不幸的是,我实际的预处理管道(上面的例子只是一个简单的漫画)太复杂,无法移植到
tf.data.Dataset
。另外,如果我理解正确,
tf.keras.Model.fit()
使用
from_generator
generator方法将
tf.keras.utils.Sequence
内部转换为
tf.data.Dataset