cube studio开源一站式云原生机器学习平台--pytorch分布式训练
全栈工程师开发手册 作者栾鹏一站式云原生机器学习平台前言开源地址https://github.com/data-infra/cube-studiocube studio 开源的国内最热门的一站式机器学习mlops/大模型训练平台支持多租户sso单点登录支持在线镜像调试在线ide开发数据集管理图文音标注和自动化标注任务模板自定义拖拉拽任务流模型分布式多机多卡训练超参搜索模型管理推理服务弹性伸缩支持ml/tf/pytorch/onnx/tensorrt/llm模型0代码服务发布以及配套资源监控和算力存储资源管理。支持机器学习深度学习大模型 开发训练推理发布全链路。支持元数据管理维表指标sqllab数据etl等数据中台对接功能。支持多集群边缘集群serverless集群方式部署。支持计量计费资源额度限制支持vgpurdma国产gpuarm64架构。aihub模型市场支持AI hub模型市场支持400开源模型应用一键开发一键微调一键部署。gpt大模型支持40开源大模型部署一键部署支持rayvolcano,spark等分布式计算框架支持tf,pytorch,mxnet,mpi,paddle,mindspre分布式多机多卡训练框架支持deepspeedcolossalaihorovod分布式加速框架支持llama chatglm baichuan qwen系列大模型微调。支持llama-factory 100llm微调支持大模型vllm推理加速支持智能体私有知识库智能机器人。背景在单机单卡或者单机多卡无法在有限时间内完成训练的情况下我们就需要使用多机多卡分布式训练在多机多卡分布式训练主要存在几个难点1、分布式多机多卡集群2、pytorch多机多卡分布式训练代码3、多机多卡分布式训练gpu利用率问题4、cpu/gpu任务分配不均cpu任务会占用GPU任务分布式训练集群为了方便的实现一个pytorch分布式集群这里直接使用https://github.com/data-infra/cube-studio 开源的云原生一站式机器学习平台。使用pytorchjob这个模板填上自己的启动命令和启动worker数目就可以。分布式原理和代码基本原则每个进程的rank是不能一样的进程总数目是为WORLD_SIZEmaster只能是rank0主要变更分布式集群的每个pod都会提供如下环境变量 NCCL_DEBUGINFO NCCL_IB_DISABLE1MASTER_PORT23456NCCL_SOCKET_IFNAMEeth0 MASTER_ADDRpytorchjob-xxx-master-0WORLD_SIZE3# 一共多少个workerRANK0# 当前是第几个worker注意 masterRANK0worker-0RANK1worker-1RANK2# 初始化集群信息ifint(os.environ.get(WORLD_SIZE,1))1:# 要不专门配置init_method RANK或者WORLD_SIZE 系统会自动识别dist.init_process_group(backendargs.backend,init_methodNone)# 被DDP封装的model的参数的grad才会进行all reduceifis_distributed():Distributornn.parallel.DistributedDataParallelifuse_cudaelsenn.parallel.DistributedDataParallelCPU modelDistributor(model)# 需要DistributedSampler作为实例传递给DataLoader来配合DDP使用这样数据集的样本会为每个进程划分每个进程读取各自的样本。train_samplertorch.utils.data.distributed.DistributedSampler(train_dataset)# 分布式下set_epochtrain_sampler.set_epoch(epoch)启动方式直接python启动your_start.py例如上面的mnist代码torch.distributed.launch启动python-mtorch.distributed.launch--nproc_per_node每个worker的卡数量--nnodes$WORLD_SIZE--node_rank$RANK--master_addr$MASTER_ADDR--master_port$MASTER_PORTtrain.py --自己脚本的其他参数torch.distributed.launch会向你的脚本传递–local_rank参数同时会透传train.py后面的参数你的train.py脚本if__name____main__:parser.add_argument(--local_rank,typeint,default0,helplocal_rank)world_sizeint(os.environ[WORLD_SIZE])rankint(os.environ[RANK])dist.init_process_group(nccl)gpu利用率优化其中gpu由于是整卡占用需要调整任务的部分参数和代码提高gpu显存占用率和gpu使用率平台监控通过监控按钮可以进入查看任务运行的资源使用率对于资源使用超标可以手动配置增加资源。自己监控利用率watchnvidia-smi 或者 pipinstallgpustatwatch--color-n1gpustat-cpugpu利用率低的原因核心cpu操作慢进而阻塞了gpu的计算可能的原因数据加载/网络等待/数据预处理/模型保存/loss 计算/评估指标计算/日志打印/指标上报/进度上报gpu利用率优化1、数据加载相关1、存储计算不在同一个城市数据导入到集群存储2、磁盘io性能太差对于临时数据可以将内存映射为磁盘3、小文件太多频繁io合并为大文件处理4、未启用多进程并行读取数据pytorch提高num_workerstf配置num_parallel_calls/num_parallel_reads5、未启用提前加载机制来实现 CPU 和 GPU 的并行pytorch配置prefetch_factortf配置Dataset.prefetch()6、未设置共享内存 pin_memory设置为true7、每次送入gpu的_size太少模型固定后调整 batch_size尽量增大显存的利用率。然后再调节num_workers提高gpu利用率2、数据预处理相关1、数据处理和训练耦合在一起将数据处理和训练分成两个task训练中需要的配置之类的全部提前加载到内存让gpu只做训练任务。或者使用Nvidia DALI在gpu中做数据处理3、频繁io操作1、模型保存太频繁减少保存模型(checkpoint)的频率2、tensorboard文件保存太频繁xxxx3、日志打印太频繁频繁cpu/gpu切换不要打印训练迭代中个人日志多进程共享gpu通过多进程共享单机的方式提高gpu的利用率概念图。添加多进程共享gpu卡的启动方式shell方式添加start端可以添加启动start.sh启动3个进程。每个进程在原有基础上添加--process_index xx --process_num xx参数。并放在在后端运行并在最后wait所有后端程序。python3 /mnt/pengluan/mytask.py --lr xx ... --process_index 0 --process_num 3 /process0.file 21 python3 /mnt/pengluan/mytask.py --lr xx ... --process_index 1 --process_num 3 /process1.file 21 python3 /mnt/pengluan/mytask.py --lr xx ... --process_index 2 --process_num 3 /process2.file 21 waitpython方式添加start端透传上层参数添加一个start.py通过start.py启动多个任务进程import json import argparse import subprocess import sys if __name__ __main__: # 以下参数列表只是示例实际使用时请按需自己增删改 arg_parser argparse.ArgumentParser(多进程启动) process_num3 python_path/mnt/pengluan/mytask.py commands [[/usr/bin/python3,python_path,--process_index,str(process_index),--process_num,str(process_num)]sys.argv[1:] for process_index in range(process_num)] print(commands) all_process [subprocess.Popen(command) for command in commands] all_returncode [process.wait() for process in all_process]