初始化:不同于torch.distributed使用torch.distributed.init_process_group,deepspeed需要使用以下方法进行分布式多进程的初始化
deepspeed.init_distributed(dist_backend='nccl',init_method='env://',distributed_port=8080,)其他操作:都可以使用torch.distributed的操作,如:torch.distributed.barrier(),等价于使用deepspeed.utils.dist.barrier()
model=create_eva_vit_g(img_size=224,drop_path_rate=0.,use_checkpoint=False,precision="fp32").cuda(args.local_rank)zero3直接分片初始化(如果模型太大,无法在一张卡上加载)如果模型太大,无法在一张显卡上加载,可以加载在多卡上,需要在deepspeed.zero.Init()下进行初始化,但只有采用zero3的时候才可用。
withdeepspeed.zero.Init():model=xxxxDataLoader既可以使用DDP的分布式DataLoader(即带上DistributedSampler),也可以直接将Dataset输入给deepspeed.initialize()得到DataLoader
目前发现如果打开zero_optimization的offload_optimizer,是得使用DeepSpeed内部的fused的optimizer的,直接使用torch自带的optimizer会报错:
deepspeed.runtime.zero.utils.ZeRORuntimeException:
用deepspeed_config自然是不会出错的方法,但deepspeed支持的scheduler还是太简单了,甚至不好满足简单的linearwarmup+后续cosinedecay。如果使用torch的scheduler,由于需要提供optimizer参数,假如optimizer是用的deepspeed实现的optimizer,会报错(因为不是torch里的optimizer类):
TypeError:DeepSpeedZeroOptimizerisnotanOptimizer
可以自定义scheduler如下:
ifepoch%save_interval==0:client_sd['global_step']=global_stepclient_sd['epoch']=epochclient_sd['scheduler']=scheduler.state_dict()ckpt_id=loss.item()model_engine.save_checkpoint(save_dir=save_dir,tag=f'epoch_{epoch}',client_state=client_sd)加载checkpointdefload_ckpt(model_engine,scheduler,ckpt_dir,ckpt_tag):_,client_sd=model_engine.load_checkpoint(load_dir=ckpt_dir,tag=ckpt_tag)global_step=client_sd['global_step']start_epoch=client_sd['epoch']scheduler.load_state_dict(client_sd['scheduler'])returnstart_epoch,global_step后续需要在for循环处修改开始的epoch和dataloader的step数,如下:
使用deepspeed的fp16或bf16,在数据输入、中间算子等位置常常会出现数据类型的问题,在输入处直接改dtype可能还行,但其他位置一直修改dtype终究有些不美观,甚至会出现错误,解决方法:可以直接和torch.cuda.amp.autocast联动:
首先,借用我个人上篇博客的分析采用混合精度时的显存占用:
在ViT模型使用时,一般情况激活值还是会占很大比例的(经验性的结论可能会占50%,当然也和batch_size有关),且这里并不开启Gradient-Checkpointing
这里想说几个点,用MiniGPT4Qwen,由于只训练中间的一个linearprojection层(几M的参数量),导致实际上ZERO系列对显存的优化并不明显(尤其是ZERO-1和ZERO-2,几乎不会有提升,甚至由于通信的缘故导致实际显存占用有较少的增加,ZERO-3我还在调),但如果想多训练一些部分(如:把BLIP2的Q-former也打开,给Qwen上LoRA,甚至想训练ViT),在3090上,你不开ZERO优化就是不可能的哈。
这里放一个使用示例吧~额滴麦麦~
请在代码中加入
"zero_optimization":{"stage":2,"allgather_partitions":true,"allgather_bucket_size":3e8,"overlap_comm":true,"reduce_scatter":true,"reduce_bucket_size":3e8,"contiguous_gradients":true}Zero-3(optimizer-state+gradient+model-paramsshard)"zero_optimization":{"stage":3,"offload_optimizer":{"device":"cpu","pin_memory":true},"offload_param":{"device":"cpu","pin_memory":true},"overlap_comm":true,"contiguous_gradients":true,"sub_group_size":1e9,"reduce_bucket_size":1e6,"stage3_prefetch_bucket_size":4e6,"stage3_param_persistence_threshold":1e4,"stage3_max_live_parameters":1e9,"stage3_max_reuse_distance":1e9,"stage3_gather_16bit_weights_on_model_save":true},ZeRO-3中不使用allgather_partitions、allgather_bucket_size和reduce_scatter配置参数
"offload_optimizer":{"device":"cpu","pin_memory":true},"offload_param":{"device":"nvme","pin_memory":true}