Python ndarray到TFRecord的序列化速度较慢

Python ndarray到TFRecord的序列化速度较慢,python,numpy,tensorflow,serialization,protocol-buffers,Python,Numpy,Tensorflow,Serialization,Protocol Buffers,我想将大numpyndarray序列化为TFRecord。问题是,这个过程如果慢得令人痛苦。对于大小为(1000000,65)的数组,几乎需要一分钟的时间。将其序列化为其他二进制格式(HDF5、npy、拼花…)只需不到一秒钟。我很确定有一种更快的方法来序列化它,但我就是想不出来 import numpy as np import tensorflow as tf X = np.random.randn(1000000, 65) def write_tf_dataset(data: np.nd

我想将大numpy
ndarray
序列化为
TFRecord
。问题是,这个过程如果慢得令人痛苦。对于大小为(1000000,65)的数组,几乎需要一分钟的时间。将其序列化为其他二进制格式(HDF5、npy、拼花…)只需不到一秒钟。我很确定有一种更快的方法来序列化它,但我就是想不出来

import numpy as np
import tensorflow as tf

X = np.random.randn(1000000, 65)

def write_tf_dataset(data: np.ndarray, path: str):
    with tf.io.TFRecordWriter(path=path) as writer:
        for record in data:
            feature = {'X': tf.train.Feature(float_list=tf.train.FloatList(value=record[:42])),
                       'Y': tf.train.Feature(float_list=tf.train.FloatList(value=record[42:64])),
                       'Z': tf.train.Feature(float_list=tf.train.FloatList(value=[record[64]]))}
            example = tf.train.Example(features=tf.train.Features(feature=feature))
            serialized = example.SerializeToString()
            writer.write(serialized)

write_tf_dataset(X, 'X.tfrecord')
如何提高写入数据集的性能?我的
X
的大小比代码段中的大200倍

我不是第一个抱怨
TFRecord
性能缓慢的人。基于此,我制作了第二个版本的函数:

import pickle

def write_tf_dataset(data: np.ndarray, path: str):
    with tf.io.TFRecordWriter(path=path) as writer:
        for record in data:
            feature = {
                'X': tf.io.serialize_tensor(record[:42]).numpy(),
                'Y': tf.io.serialize_tensor(record[42:64]).numpy(),
                'Z': tf.io.serialize_tensor(record[64]).numpy(),
            }
            serialized = pickle.dumps(feature)
            writer.write(serialized)

。。。但如果表现更糟。想法?

解决方法是使用
多处理
包。您可以将多个进程写入同一个TFRecord文件,或者将每个进程写入不同的文件(我认为建议使用多个(小)TFRecords,而不是单个(大)文件,因为从多个源读取更快):

导入多处理
导入操作系统
将numpy作为np导入
导入tensorflow作为tf
def序列化_示例(记录):
特征={
“X”:tf.train.Feature(float_list=tf.train.FloatList(value=record[:42]),
“Y”:tf.train.Feature(float_list=tf.train.FloatList(value=record[42:64]),
“Z”:tf.train.Feature(float_list=tf.train.FloatList(value=[record[64]]),表示,
}
示例=tf.train.example(特征=tf.train.features(特征=feature))
返回示例.SerializeToString()
def write_tfrecord(tfrecord_路径,记录):
使用tf.io.TFRecordWriter(tfrecord\u路径)作为编写器:
对于记录中的项目:
序列化=序列化\u示例(项)
writer.write(序列化)
如果名称=“\uuuuu main\uuuuuuuu”:
np.random.seed(1234)
数据=np.random.randn(1000000,65)
#选项1:写入单个文件
tfrecord_path=“/home/appuser/data/data.tfrecord”
p=多处理池(4)
使用tf.io.TFRecordWriter(tfrecord\u路径)作为编写器:
例如,在p.map中(序列化\u示例,数据):
writer.write(示例)
#选项2:写入多个文件
过程=[]
n_shard=4
num_per_shard=int(np.ceil(len(数据)/n_shard))
对于范围内的碎片id(n碎片):
filename=f“data_{shard_id+1:04d}of_{n_shard:04d}.tfrecord”
tfrecord_path=os.path.join(“/home/appuser/data”,文件名)
开始索引=碎片id*每个碎片的数量
end_index=min((shard_id+1)*num_per_shard,len(数据))
args=(tfrecord\u路径,数据[开始索引:结束索引])
p=多处理。进程(目标=写入记录,args=args)
p、 开始()
过程附加(p)
对于进程中的进程:
proc.join()

谢谢!这就是我最终所做的,事实证明,从多个文件加载数据需要更长的时间。我有一个像样的CPU和NVMe驱动器,所以它不是硬件差,不能处理IO。我观察到的是,使用并行加载,即使作业数为1(
num\u parallel\u reads=1
),也会带来很大的损失。换句话说,这加快了储蓄的速度,但我要在以后的培训中付出代价(这更糟)。有什么建议吗?我不知道是什么引起的。也许您可以尝试使用调试输入管道,并查看跟踪查看器以了解瓶颈的指示。