- 分布式训练常见问题
- 综合问题
- Fleet API的使用
- 问题:飞桨2.0版本分布式Fleet API的目录在哪?
- 问题:飞桨2.0版本的fleet配置初始化接口init和init_server用法有什么变化?
- 问题: 飞桨2.0版本的分布式paddle.static.nn.sparse_embedding和paddle.nn.embedding有什么差别?
- 问题:飞桨2.0分布式可以用哪些配置类?
- 问题:飞桨2.0分布式配置项统一到DistributedStrategy后有哪些具体变化?
- 问题:飞桨2.0分布式Fleet的program接口是否还能继续用?
- 问题:怎样在本地测试Fleet API实现的分布式训练代码是否正确?
- 问题:Paddle Fleet怎样做增量训练,有没有文档支持?
- 问题:飞桨2.0分布式distributed_optimizer如何使用自动混合精度amp的optimizer?
- 问题:Paddle Fleet可以在K8S GPU集群上利用CPU资源跑pserver模式的MPI程序吗?
- 问题:使用 Fleet Collective 模式进行开发时,已使用 fleet.distributed_optimizer 对 optimizer 和 fleet.DistributedStrategy 包了一层。想确认模型是否也需要使用 fleet.distributed_model 再包一层?
- 环境配置和训练初始化
- 分布式的动态图模式
- 报错查错
分布式训练常见问题
综合问题
问题:怎样了解飞桨分布式Fleet API用法?
问题:机房训练模型的分布式环境用什么比较合适?
- 答复: 推荐使用K8S部署,K8S的环境搭建可参考文档
问题:目前飞桨分布式对哪些模型套件/工具支持?
- 答复:
多机多卡支持paddlerec,PGL,paddleHelix,paddleclas,paddlenlp,paddledetection。
单机多卡支持全部飞桨的模型套件和高层API写法,无需修改单卡训练代码,默认启用全部可见的卡。
问题:怎样自定义单机多卡训练的卡数量?
答复:如果直接使用飞桨模型套件(paddleclas,paddleseg等)或高层API写的代码,可以直接用这条命令指定显卡启动程序,文档源代码不用改(文档内不要用set_device指定卡):
python3 -m paddle.distributed.launch --gpus="1, 3" train.py
使用基础API的场景下,在程序中修改三处:第1处改动,import库
import paddle.distributed as dist
第2处改动,初始化并行环境
dist.init_parallel_env()
第3处改动,对模型增加paddle.DataParallel封装
net = paddle.DataParallel(paddle.vision.models.LeNet())
修改完毕就可以使用python3 -m paddle.distributed.launch --gpus="1, 3" xxx
来启动了。可参考AIstudio项目示例
Fleet API的使用
问题:飞桨2.0版本分布式Fleet API的目录在哪?
答复:2.0版本分布式API从paddle.fluid.incubate.fleet目录挪至paddle.distributed.fleet目录下,且对部分API接口做了兼容升级。import方式如下:
import paddle.distributed.fleet as fleet
fleet.init()
不再支持老版本paddle.fluid.incubate.fleet API,2.0版本会在分布式计算图拆分的阶段报语法相关错误。未来的某个版本会直接移除废弃paddle.fluid目录下的API。
问题:飞桨2.0版本的fleet配置初始化接口init和init_server用法有什么变化?
- 答复:
fleet.init
接口,2.0版本支持role_maker
,is_collective
,strategy
等参数,且均有缺省值,老版本仅支持role_maker
,且无缺省配置。点击这里 参考2.0 Fleet API的使用方式。fleet.init_server
接口,除支持传入model_dir
之外,2.0版本还支持传入var_names
,加载指定的变量。
问题: 飞桨2.0版本的分布式paddle.static.nn.sparse_embedding和paddle.nn.embedding有什么差别?
- 答复:
paddle.nn.embedding
和paddle.static.nn.sparse_embedding
的稀疏参数将会在每个PServer段都用文本的一部分保存,最终整体拼接起来是完整的embedding。推荐使用paddle.static.nn.sparse_embedding
直接采用分布式预估的方案。虽然nn.embedding
目前依旧可以正常使用,但后续的某个版本会变成与使用paddle.static.nn.sparse_embedding
一样的保存方案。老版本中使用的0号节点的本地预测功能在加载模型的时候会报模型加载错误。
问题:飞桨2.0分布式可以用哪些配置类?
- 答复:2.0之后统一为
paddle.distributed.fleet.DistributedStrategy()
,与下述老版本配置类不兼容。2.0之前的版本参数服务器配置类:paddle.fluid.incubate.fleet.parameter_server.distribute_transpiler.distributed_strategy.DistributedStrategy
,2.0之前的版本collective模式配置类:paddle.fluid.incubate.fleet.collective.DistributedStrategy
问题:飞桨2.0分布式配置项统一到DistributedStrategy后有哪些具体变化?
- 答复: 2.0版本之后,建议根据 DistributedStrategy文档 和 BuildStrategy文档 修改配置选项。
2.0版本将3个环境变量配置变为DistributedStrategy
配置项,3个环境变量将不生效,包括
FLAGS_sync_nccl_allreduce
→strategy.sync_nccl_allreduce
FLAGS_fuse_parameter_memory_size
→strategy.fuse_grad_size_in_MB
FLAGS_fuse_parameter_groups_size
→strategy.fuse_grad_size_in_TFLOPS
DistributedStrategy中exec_strategy
配置项不兼容升级为execution_strategy
。
DistributedStrategy中forward_recompute
配置项不兼容升级为recompute
。
DistributedStrategy中recompute_checkpoints
配置项不兼容升级为recompute_configs
字典下的字段,如下:
import paddle.distributed.fleet a fleet
strategy = fleet.Distributedstrategy()
strategy.recompute = True
strategy.recompute_configs = {
"checkpoints": ["x","y"],
"enable_offload": True,
"checkpoint_shape": [100, 512, 1024]}
DistributedStrategy中use_local_sgd
配置项变为不兼容升级为localsgd。
问题:飞桨2.0分布式Fleet的program接口是否还能继续用?
- 答复:2.0版本后,fleet接口下main_program和_origin_program均已废弃,会报错没有这个变量,替换使用
paddle.static.default_main_program
即可。
问题:怎样在本地测试Fleet API实现的分布式训练代码是否正确?
答复:首先写好分布式train.py文件
在PServer模式下,命令行模拟启动分布式:
python -m paddle.distributed.launch_ps --worker_num 2 --server_num 2 train.py
在Collective模式下,命令改为
python -m paddle.distributed.launch --gpus=0,1 train.py
问题:Paddle Fleet怎样做增量训练,有没有文档支持?
- 答复:增量训练可参考文档示例
问题:飞桨2.0分布式distributed_optimizer如何使用自动混合精度amp的optimizer?
- 答复:
amp_init
接口支持pure_fp16,可以直接调用optimizer.amp_init
。
问题:Paddle Fleet可以在K8S GPU集群上利用CPU资源跑pserver模式的MPI程序吗?
- 答复:可以,GPU可设置为trainer。
问题:使用 Fleet Collective 模式进行开发时,已使用 fleet.distributed_optimizer 对 optimizer 和 fleet.DistributedStrategy 包了一层。想确认模型是否也需要使用 fleet.distributed_model 再包一层?
- 答复:需要将
fleet.distributed_model
在封装一层。原因是动态图主要在fleet.distributed_model
进行分布式设计,静态图是在fleet.distributed_optimizer
进行分布式设计。所以,如果不区分动态图和静态图,两个接口都是需要的。
环境配置和训练初始化
问题:分布式环境变量FLAGS参数定义可以在哪查看,比如communicator相关的?
- 答复:参考使用DistributedStrategy配置分布式策略。
问题:2.0分布式训练的启动命令有什么变化?
- 答复:为了统一启动分布式Collective/PS模式任务方式以及易用性考虑,2.0版本中launch/fleetrun启动分布式任务时参数产生不兼容升级,
--cluster_node_ips
改为--ips
,--selected_gpus
改为--gpus
、--node_ip
、--use_paddlecloud
、--started_port
、--log_level
、--print_config
5个参数已废弃,使用旧参数会直接报错没有此参数。代码迁移至python/paddle/distributed/fleet/launch.py。
问题:分布式环境依赖为什么出现第三方libssl库的依赖?
- 答复:分布式RPC从GRPC迁移至BRPC, 会导致在运行时依赖libssl库。使用docker的情况下,基础镜像拉一下官方最新的docker镜像,或自行安装libssl相关的依赖也可以。未安装libssl的情况下,import paddle的时候,出现找不到libssl.so的库文件相关报错。使用MPI的情况下,需要将编译包时用到的libssl.so、libcrypto.so等依赖手动通过
LD_LIBRARY_PATH
进行指定。
分布式的动态图模式
问题:飞桨2.0版本动态图DataParallel用法有哪些简化?
+答复:老版本用法依然兼容,建议使用以下新用法:apply_collective_grads
、scale_loss
可以删除不使用。loss会根据环境除以相应的卡数,scale_loss
不再进行任何处理。
问题:飞桨2.0版本调用model.eval之后不再自动关闭反向计算图的构建,引入显存的消耗增加,可能会引入OOM,怎么解决?
- 答复:动态图
no_grad
和model.eval
解绑,应使用with paddle.no_grad():
命令,显示关闭反向计算图的构建。
问题:飞桨2.0版本动态图环境初始化新接口怎样用?
- 答复:建议调用新接口
paddle.distributed.init_parallel_env
,不需要输入参数。1.8的fluid.dygraph.prepare_context
依然兼容。
问题:分布式支持哪些飞桨2.0版本的模型保存和加载接口?
- 答复: 与单机相同,分布式动态图推荐使用
paddle.jit.save
保存,使用paddle.jit.load
加载,无需切换静态图,存储格式与推理模型存储一致。对比1.8动态图使用不含控制流的模型保存接口TracedLayer.save_inference_model
,含控制流的模型保存接口ProgramTranslator.save_inference_model
,加载模型需要使用静态图接口fluid.io.load_inference_model
。fluid.save_dygraph
和fluid.load_dygraph
升级为paddle.save
和paddle.load
,推荐使用新接口。paddle.save
不再默认添加后缀,建议用户指定使用标椎后缀(模型参数:.pdparams,优化器参数:.pdopt)。
问题:飞桨2.0版本为什么不能使用minimize 和 clear_gradient?
- 答复:2.0版本中重新实现optimizer,放在
paddle.optimizer
,建议使用新接口和参数。老版本的paddle.fluid.optimizer
仍然可用。
新版增加接口step
替换minimize
。老版动态图需要调用loss.backward()
,用minimize来表示梯度的更新行为,词语意思不太一致。
新版使用简化的clear_grad
接口替换clear_gradient
。
报错查错
问题:集合通信Collective模式报参数未初始化的错误是什么原因?
- 答复:2.0版本需要严格先
run(startup_program)
,然后再调用fleet.init_worker()
启动worker端通信相关,并将0号worker的参数广播出去完成其他节点的初始化。先init_worker
,再run(startup_program)
,会报参数未初始化的错误
2.0之前的版本是在server端做初始化,无需0号节点广播,所以init_worker()
可以在run(startup_program)
执行。
问题:分布式任务跑很久loss突然变成nan的原因?
- 答复:可设置环境变量
export FLAGS_check_nan_inf=1
定位出错的地方,可以从checkpoint开始训练,参数服务器和集合通信模式均可使用这种方式查错。
问题:任务卡在role init怎么解决?
- 答复:通常可能是gloo的初始化问题,需要检查是否有节点任务挂了。建议调小
train_data
配置的数据量,由于启动trainer前要下载数据,大量数据会导致拖慢。