fix: keep only latest DeepSpeed checkpoint
parent
0425c4f622
commit
e9c93951cc
|
|
@ -27,6 +27,7 @@ from trainer.trainer_utils import (
|
||||||
add_model_profile_args,
|
add_model_profile_args,
|
||||||
apply_model_profile,
|
apply_model_profile,
|
||||||
build_lm_config,
|
build_lm_config,
|
||||||
|
assert_no_training_output_collision,
|
||||||
init_model,
|
init_model,
|
||||||
is_main_process,
|
is_main_process,
|
||||||
get_cuda_peak_memory_gb,
|
get_cuda_peak_memory_gb,
|
||||||
|
|
@ -149,6 +150,7 @@ def parse_args():
|
||||||
parser.add_argument("--data_path", type=str, default="../dataset/sft_t2t_mini.jsonl")
|
parser.add_argument("--data_path", type=str, default="../dataset/sft_t2t_mini.jsonl")
|
||||||
parser.add_argument("--from_weight", default="pretrain", type=str)
|
parser.add_argument("--from_weight", default="pretrain", type=str)
|
||||||
parser.add_argument("--from_resume", default=0, type=int, choices=[0, 1])
|
parser.add_argument("--from_resume", default=0, type=int, choices=[0, 1])
|
||||||
|
parser.add_argument("--overwrite_output", default=0, type=int, choices=[0, 1])
|
||||||
parser.add_argument("--use_wandb", action="store_true")
|
parser.add_argument("--use_wandb", action="store_true")
|
||||||
parser.add_argument("--wandb_project", type=str, default="SearchLM-Full-SFT-DS")
|
parser.add_argument("--wandb_project", type=str, default="SearchLM-Full-SFT-DS")
|
||||||
parser.add_argument("--use_compile", default=0, type=int, choices=[0, 1])
|
parser.add_argument("--use_compile", default=0, type=int, choices=[0, 1])
|
||||||
|
|
@ -181,6 +183,14 @@ if __name__ == "__main__":
|
||||||
num_key_value_heads=args.num_key_value_heads,
|
num_key_value_heads=args.num_key_value_heads,
|
||||||
intermediate_size=args.intermediate_size,
|
intermediate_size=args.intermediate_size,
|
||||||
)
|
)
|
||||||
|
assert_no_training_output_collision(
|
||||||
|
lm_config,
|
||||||
|
weight=args.save_weight,
|
||||||
|
save_dir=args.save_dir,
|
||||||
|
checkpoint_dir="../checkpoints",
|
||||||
|
from_resume=args.from_resume,
|
||||||
|
overwrite=args.overwrite_output,
|
||||||
|
)
|
||||||
|
|
||||||
model, tokenizer = init_model(lm_config, args.from_weight, device=args.device)
|
model, tokenizer = init_model(lm_config, args.from_weight, device=args.device)
|
||||||
if args.use_compile == 1:
|
if args.use_compile == 1:
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ from trainer.trainer_utils import (
|
||||||
add_model_profile_args,
|
add_model_profile_args,
|
||||||
apply_model_profile,
|
apply_model_profile,
|
||||||
build_lm_config,
|
build_lm_config,
|
||||||
|
assert_no_training_output_collision,
|
||||||
init_model,
|
init_model,
|
||||||
is_main_process,
|
is_main_process,
|
||||||
get_cuda_peak_memory_gb,
|
get_cuda_peak_memory_gb,
|
||||||
|
|
@ -149,6 +150,7 @@ def parse_args():
|
||||||
parser.add_argument("--data_path", type=str, default="../dataset/pretrain_t2t_mini.jsonl")
|
parser.add_argument("--data_path", type=str, default="../dataset/pretrain_t2t_mini.jsonl")
|
||||||
parser.add_argument("--from_weight", default="none", type=str)
|
parser.add_argument("--from_weight", default="none", type=str)
|
||||||
parser.add_argument("--from_resume", default=0, type=int, choices=[0, 1])
|
parser.add_argument("--from_resume", default=0, type=int, choices=[0, 1])
|
||||||
|
parser.add_argument("--overwrite_output", default=0, type=int, choices=[0, 1])
|
||||||
parser.add_argument("--use_wandb", action="store_true")
|
parser.add_argument("--use_wandb", action="store_true")
|
||||||
parser.add_argument("--wandb_project", type=str, default="SearchLM-Pretrain-DS")
|
parser.add_argument("--wandb_project", type=str, default="SearchLM-Pretrain-DS")
|
||||||
parser.add_argument("--use_compile", default=0, type=int, choices=[0, 1])
|
parser.add_argument("--use_compile", default=0, type=int, choices=[0, 1])
|
||||||
|
|
@ -181,6 +183,14 @@ if __name__ == "__main__":
|
||||||
num_key_value_heads=args.num_key_value_heads,
|
num_key_value_heads=args.num_key_value_heads,
|
||||||
intermediate_size=args.intermediate_size,
|
intermediate_size=args.intermediate_size,
|
||||||
)
|
)
|
||||||
|
assert_no_training_output_collision(
|
||||||
|
lm_config,
|
||||||
|
weight=args.save_weight,
|
||||||
|
save_dir=args.save_dir,
|
||||||
|
checkpoint_dir="../checkpoints",
|
||||||
|
from_resume=args.from_resume,
|
||||||
|
overwrite=args.overwrite_output,
|
||||||
|
)
|
||||||
|
|
||||||
model, tokenizer = init_model(lm_config, args.from_weight, device=args.device)
|
model, tokenizer = init_model(lm_config, args.from_weight, device=args.device)
|
||||||
if args.use_compile == 1:
|
if args.use_compile == 1:
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ from trainer.trainer_utils import (
|
||||||
add_model_profile_args,
|
add_model_profile_args,
|
||||||
apply_model_profile,
|
apply_model_profile,
|
||||||
build_lm_config,
|
build_lm_config,
|
||||||
|
assert_no_training_output_collision,
|
||||||
init_model,
|
init_model,
|
||||||
is_main_process,
|
is_main_process,
|
||||||
get_cuda_peak_memory_gb,
|
get_cuda_peak_memory_gb,
|
||||||
|
|
@ -253,6 +254,7 @@ def parse_args():
|
||||||
parser.add_argument("--temperature", type=float, default=0.8)
|
parser.add_argument("--temperature", type=float, default=0.8)
|
||||||
parser.add_argument("--from_weight", default="full_sft_search", type=str)
|
parser.add_argument("--from_weight", default="full_sft_search", type=str)
|
||||||
parser.add_argument("--from_resume", default=0, type=int, choices=[0, 1])
|
parser.add_argument("--from_resume", default=0, type=int, choices=[0, 1])
|
||||||
|
parser.add_argument("--overwrite_output", default=0, type=int, choices=[0, 1])
|
||||||
parser.add_argument("--use_wandb", action="store_true")
|
parser.add_argument("--use_wandb", action="store_true")
|
||||||
parser.add_argument("--wandb_project", type=str, default="SearchShortQA-GRPO-DS")
|
parser.add_argument("--wandb_project", type=str, default="SearchShortQA-GRPO-DS")
|
||||||
parser.add_argument("--use_compile", default=0, type=int, choices=[0, 1])
|
parser.add_argument("--use_compile", default=0, type=int, choices=[0, 1])
|
||||||
|
|
@ -290,6 +292,14 @@ if __name__ == "__main__":
|
||||||
num_key_value_heads=args.num_key_value_heads,
|
num_key_value_heads=args.num_key_value_heads,
|
||||||
intermediate_size=args.intermediate_size,
|
intermediate_size=args.intermediate_size,
|
||||||
)
|
)
|
||||||
|
assert_no_training_output_collision(
|
||||||
|
lm_config,
|
||||||
|
weight=args.save_weight,
|
||||||
|
save_dir=args.save_dir,
|
||||||
|
checkpoint_dir="../checkpoints",
|
||||||
|
from_resume=args.from_resume,
|
||||||
|
overwrite=args.overwrite_output,
|
||||||
|
)
|
||||||
|
|
||||||
model, tokenizer = init_model(lm_config, args.from_weight, device=args.device)
|
model, tokenizer = init_model(lm_config, args.from_weight, device=args.device)
|
||||||
if args.use_compile == 1:
|
if args.use_compile == 1:
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
import math
|
import math
|
||||||
|
import shutil
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import torch
|
import torch
|
||||||
import torch.distributed as dist
|
import torch.distributed as dist
|
||||||
|
|
@ -80,11 +81,16 @@ def unwrap_model(model):
|
||||||
return getattr(raw_model, "_orig_mod", raw_model)
|
return getattr(raw_model, "_orig_mod", raw_model)
|
||||||
|
|
||||||
|
|
||||||
|
def get_model_weight_path(lm_config, save_dir="../out", weight="model", epoch=None, step=None):
|
||||||
|
model_suffix = get_model_suffix(lm_config)
|
||||||
|
step_suffix = f"_epoch{epoch}_step{step}" if epoch is not None and step is not None else ""
|
||||||
|
return f"{save_dir}/{weight}_{lm_config.hidden_size}{model_suffix}{step_suffix}.pth"
|
||||||
|
|
||||||
|
|
||||||
def save_model_weights(lm_config, model, save_dir="../out", weight="model", dtype=torch.float16):
|
def save_model_weights(lm_config, model, save_dir="../out", weight="model", dtype=torch.float16):
|
||||||
"""保存一份轻量推理权重;DeepSpeed完整训练状态由 save_checkpoint 单独保存。"""
|
"""保存一份轻量推理权重;DeepSpeed完整训练状态由 save_checkpoint 单独保存。"""
|
||||||
os.makedirs(save_dir, exist_ok=True)
|
os.makedirs(save_dir, exist_ok=True)
|
||||||
model_suffix = get_model_suffix(lm_config)
|
ckp_path = get_model_weight_path(lm_config, save_dir=save_dir, weight=weight)
|
||||||
ckp_path = f"{save_dir}/{weight}_{lm_config.hidden_size}{model_suffix}.pth"
|
|
||||||
raw_model = unwrap_model(model)
|
raw_model = unwrap_model(model)
|
||||||
state_dict = raw_model.state_dict()
|
state_dict = raw_model.state_dict()
|
||||||
state_dict = {k: v.detach().to(dtype).cpu() for k, v in state_dict.items()}
|
state_dict = {k: v.detach().to(dtype).cpu() for k, v in state_dict.items()}
|
||||||
|
|
@ -218,6 +224,48 @@ def _candidate_deepspeed_tags(lm_config, weight, save_dir="../checkpoints"):
|
||||||
return dedup
|
return dedup
|
||||||
|
|
||||||
|
|
||||||
|
def _prune_old_deepspeed_step_tags(lm_config, weight, keep_tag, save_dir="../checkpoints"):
|
||||||
|
if not os.path.exists(save_dir):
|
||||||
|
return
|
||||||
|
base_tag = get_deepspeed_tag(lm_config, weight)
|
||||||
|
prefix = f"{base_tag}_epoch"
|
||||||
|
for name in os.listdir(save_dir):
|
||||||
|
if name == keep_tag or not name.startswith(prefix):
|
||||||
|
continue
|
||||||
|
path = os.path.join(save_dir, name)
|
||||||
|
if os.path.isdir(path):
|
||||||
|
shutil.rmtree(path, ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
|
def assert_no_training_output_collision(lm_config, weight, save_dir="../out", checkpoint_dir="../checkpoints", from_resume=0, overwrite=0):
|
||||||
|
if int(from_resume) == 1 or int(overwrite) == 1:
|
||||||
|
return
|
||||||
|
base_tag = get_deepspeed_tag(lm_config, weight)
|
||||||
|
latest_weight = get_model_weight_path(lm_config, save_dir=save_dir, weight=weight)
|
||||||
|
latest_file = get_deepspeed_latest_file(lm_config, weight, checkpoint_dir)
|
||||||
|
existing = []
|
||||||
|
if os.path.exists(latest_weight):
|
||||||
|
existing.append(latest_weight)
|
||||||
|
if os.path.exists(latest_file):
|
||||||
|
existing.append(latest_file)
|
||||||
|
if os.path.exists(os.path.join(checkpoint_dir, base_tag)):
|
||||||
|
existing.append(os.path.join(checkpoint_dir, base_tag))
|
||||||
|
if os.path.exists(checkpoint_dir):
|
||||||
|
prefix = f"{base_tag}_epoch"
|
||||||
|
for name in os.listdir(checkpoint_dir):
|
||||||
|
if name.startswith(prefix):
|
||||||
|
existing.append(os.path.join(checkpoint_dir, name))
|
||||||
|
break
|
||||||
|
if not existing:
|
||||||
|
return
|
||||||
|
raise RuntimeError(
|
||||||
|
"检测到同名训练产物,已阻止覆盖。"
|
||||||
|
f" save_weight={weight}, hidden_size={lm_config.hidden_size}, existing={existing}. "
|
||||||
|
"如果是继续训练,请加 --from_resume 1;如果是新实验,请换一个 --save_weight;"
|
||||||
|
"如果确认要覆盖/复用旧目录,请显式加 --overwrite_output 1。"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def save_deepspeed_checkpoint(model_engine, lm_config, weight, epoch=0, step=0, wandb=None, save_dir="../checkpoints", **kwargs):
|
def save_deepspeed_checkpoint(model_engine, lm_config, weight, epoch=0, step=0, wandb=None, save_dir="../checkpoints", **kwargs):
|
||||||
"""DeepSpeed checkpoint 必须所有 rank 都调用,不能只在 rank0 保存。"""
|
"""DeepSpeed checkpoint 必须所有 rank 都调用,不能只在 rank0 保存。"""
|
||||||
os.makedirs(save_dir, exist_ok=True)
|
os.makedirs(save_dir, exist_ok=True)
|
||||||
|
|
@ -237,7 +285,10 @@ def save_deepspeed_checkpoint(model_engine, lm_config, weight, epoch=0, step=0,
|
||||||
model_engine.save_checkpoint(save_dir, tag=tag, client_state=client_state)
|
model_engine.save_checkpoint(save_dir, tag=tag, client_state=client_state)
|
||||||
if is_main_process():
|
if is_main_process():
|
||||||
_write_deepspeed_latest_tag(lm_config, weight, tag, save_dir)
|
_write_deepspeed_latest_tag(lm_config, weight, tag, save_dir)
|
||||||
|
_prune_old_deepspeed_step_tags(lm_config, weight, keep_tag=tag, save_dir=save_dir)
|
||||||
Logger(f"DeepSpeed checkpoint saved: {save_dir}/{tag}")
|
Logger(f"DeepSpeed checkpoint saved: {save_dir}/{tag}")
|
||||||
|
if dist.is_initialized():
|
||||||
|
dist.barrier()
|
||||||
return tag
|
return tag
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue