导读:飞桨(PaddlePaddle)致力于让深度学习技术的创新与应用更简单。在单机训练速度方面,通过高并行、低开销的异步执行策略和高效率的核心算子,优化静态图训练性能,在Paddle Fluid v1.5.0的基准测试中,在7个典型模型上进行了测试(图像领域5个,NLP领域2个),其中5个模型的速度显著优于对标框架(大于15%),2个模型与对标框架持平(5%之内)。如果想让单机训练速度更快,可以根据这篇文档的建议从网络构建、数据准备、模型训练三个方向了解飞桨单机训练中常用的优化方法。来一组测试数据先睹为快。
测试环境如下:
• PaddlePaddle version:1.5.0
• Tensorflow version:1.12.0
• PyTorch version:1.1.0
• MXNet version:1.4.1
• GPU:Tesla V100-SXM2
• CPU:Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz,38核
• Nvida driver: 418.39
• CUDNN VERSION:7.4.2.24
• CUDA VERSION:9.0.176,单卡模式
1. 网络构建过程中的配置优化
减少模型中Layer的个数
为方便用户使用,飞桨提供一些不同粒度的Layer,其中有些Layer的组合可以通过单个Layer完成。比如:
(1)fluid.layers.softmax_with_cross_entropy,该操作其实是fluid.layers.softmax和fluid.layers.cross_entropy的组合,因此如果模型中有出现fluid.layers.softmax和fluid.layers.cross_entropy的组合,可以直接用fluid.layers.softmax_with_cross_entropy替换。
(2)如果模型中需要对数据进行标准化,可以直接使用fluid.layers.data_norm,而不用通过一系列layer组合出数据的标准化操作。
因此,建议在构建模型时优先使用飞桨提供的单个Layer完成所需操作,这样减少模型中Layer的个数,并因此加速模型训练。
2. 数据准备优化
数据准备通常分为两部分:第一部分是数据加载,即程序从磁盘中加载训练/预测数据;第二部分是数据预处理,程序对加载的数据进行预处理,比如图像任务通常需要进行数据增强、Shuffle等。这两部分需要用户根据自己的模型需要进行设置,只需要最后得到Data Reader接口即可。Data Reader返回iterable对象,可以每次返回一条样本或者一组样本。代码示例如下:
def data_reader (width, height):
defreader():
while True:
yield np.random.uniform(-1, 1,size=width*height), \
np.random.randint(0,10)
return reader
train_data_reader = data_reader(32, 32)
飞桨提供了两种方式从Data Reader中读取数据:同步数据读取和异步数据读取。
2.1 同步数据读取
同步数据读取是一种简单并且直观的数据准备方式,代码示例如下:
Image = paddle.layer.data("image",...)
label = paddle.layer.data("label",...)
# 模型定义
# ……
prediction = fluid.layers.fc(input= image,size=10)
loss = fluid.layers.cross_entropy(input=prediction, label= label)
avg_loss = fluid.layers.mean(loss)
# ……
# 读取数据
# paddle.dataset.mnist.train()返回数据读取的Reader,每次可以从Reader中读取一条样本,batch_size为128
train_reader =paddle.batch(paddle.dataset.mnist.train(), 128)
end = time.time()
for batch_id, batch in enumerate(train_reader):
data_time = time.time() - end
# 训练网络
executor.run(feed=[...], fetch_list=[...])
batch_time = time.time() - end
end= time.time()
用户首先需要通过fluid.layers.data定义模型的输入,然后根据输入构建模型,最后从事先自定义的Reader函数中获取一个batch的数据,并将数据传递给执行器。
可以看出,采用同步数据读取方式时,用户可通过加入计时函数来统计数据准备部分和执行部分所占用的时间。由于数据准备和执行是顺序进行的,所以程序的执行速度可能较慢。如果用户想进行模型调试的话,同步数据读取是一个不错的选择。
更多同步数据读取的介绍请参考:
https://www.paddlepaddle.org.cn/documentation/docs/en/1.5/user_guides/howto/prepare_data/reader.html
2.2 异步数据读取
飞桨里面使用py_reader接口来实现异步数据读取,代码示例如下:
train_py_reader = fluid.layers.py_reader(
capacity=10,
shapes=((-1, 784), (-1, 1)),
dtypes=('float32', 'int64')