2 张天数智芯 天垓 150(单卡 64GB,计 128GB HBM)可跑最大 Qwen3-8B、Qwen3-14B FP16 LoRA 模型 + 完整实操步骤 、 命令
2 张天数智芯 天垓 150(单卡 64GB,计 128GB HBM)可跑最大 Qwen3-8B、Qwen3-14B FP16 LoRA 模型 + 完整实操步骤 、 命令
一、硬件上限结论(分两种训练模式)
1)标准 DDP 数据并行(每卡完整加载全套模型,无模型分片,生产稳定首选)
- 流畅无压力:Qwen3-6B、Qwen3-8B(batch 可开到 8~12,4096 上下文)
- 极限勉强可跑:Qwen3-14B(必须极小 batch、短序列,极易 OOM,不推荐长期训练)
- 完全跑不动:Qwen3-30B/32B 及以上(单卡 FP16 权重就 64GB+,加载即爆显存)
2)FSDP 模型分片并行(权重 / 梯度 / 优化器分散双卡,极限拉满)
2 张 150 128GB 总显存启用 FSDP ZeRO 分片,最大可稳定微调 Qwen3-14B FP16 LoRA;
Qwen3-30B 依然不足,至少 4 张天垓 150。
客户常规交付、长期稳定训练优先:Qwen3-8B;需要更大基座才用 FSDP 跑 Qwen3-14B。下面分两套完整流程:
方案 A:DDP 双卡训练 Qwen3-8B(推荐,稳定简单)
方案 B:FSDP 双卡极限训练 Qwen3-14B(最大模型,资源拉满)
前置统一环境(两套方案通用)
1 驱动与依赖安装
bash
# 安装CoreX+TorchAdapter
sudo bash corex-4.4.0-linux64.run --silent --driver --toolkit --torchadapter
# 全局环境变量写入/etc/profile
echo "export COREX_HOME=/opt/corex" >> /etc/profile
echo "export LD_LIBRARY_PATH=$COREX_HOME/lib:$LD_LIBRARY_PATH"
echo "export PATH=$COREX/bin:$PATH"
source /etc/profile
# AI依赖
pip install torch torchvision torchaudio torchadapter
pip install transformers peft datasets accelerate sentencepiece
2 双卡通信校验(必做,0&1 同组 INTE 直连)
bash
# 查看拓扑确认0、1直连
ixsmi topo -m
# AllReduce带宽测试
numactl --cpunodebind=0 --membind=0 mpirun -np 2 ./all_reduce_perf -b 8 -e 1G -g 0,1
验收:无 #wrong,平均带宽≥9GB/s
3 NVMe 高速盘目录(统一存储,挂载参数defaults,noatime,nodiratime,discard)
bash
mkdir -p /data01/models
mkdir -p /data01/train_data
mkdir -p /data01/lora_out
mkdir -p /data01/train_logs
数据集格式/data01/train_data/train.jsonl
json
{"instruction":"问题","input":"","output":"标准答案"}
方案 A:DDP 双卡稳定微调 Qwen3-8B(日常业务首选)
1 训练脚本 train_qwen8b_ddp.py
python
import os, torch
import torch.distributed as dist
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer
from peft import LoraConfig, get_peft_model
from datasets import load_dataset
# 初始化ixCCL分布式
dist.init_process_group(backend="ixccl")
local_rank = int(os.environ["LOCAL_RANK"])
torch.cuda.set_device(local_rank)
device = torch.device("cuda", local_rank)
# 路径
MODEL_PATH = "/data01/models/Qwen3-8B-Instruct"
DATA = "/data01/train_data/train.jsonl"
SAVE = "/data01/lora_out/qwen8b_lora"
MAX_LEN = 4096
# LoRA配置
lora_cfg = LoraConfig(
r=16, lora_alpha=32, lora_dropout=0.05, bias="none",
target_modules=["q_proj","k_proj","v_proj","o_proj","gate_proj","up_proj","down_proj"],
task_type="CAUSAL_LM"
)
# 加载FP16基座+梯度检查点省显存
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(
MODEL_PATH, torch_dtype=torch.float16, device_map={"":device},
trust_remote_code=True, gradient_checkpointing=True
)
model = get_peft_model(model, lora_cfg)
model.print_trainable_parameters()
# 数据处理
def fmt(s):
return f"<|im_start|>user\n{s['instruction']}<|im_end|>\n<|im_start|>assistant\n{s['output']}<|im_end|>"
def tok(sample):
out = tokenizer(fmt(sample), truncation=True, max_length=MAX_LEN, padding="max_length")
out["labels"] = out["input_ids"].copy()
return out
ds = load_dataset("json", data_files=DATA, split="train")
train_ds = ds.map(tok, remove_columns=ds.column_names)
# DDP训练参数
train_args = TrainingArguments(
output_dir=SAVE,
per_device_train_batch_size=8,
gradient_accumulation_steps=2,
learning_rate=2e-4, num_train_epochs=3, fp16=True,
logging_dir="/data01/train_logs/qwen8b", logging_steps=10,
save_steps=100, save_total_limit=2, dataloader_num_workers=8,
local_rank=local_rank, ddp_backend="ixccl", ddp_timeout=1800,
report_to="none", overwrite_output_dir=True, ddp_find_unused_parameters=False
)
trainer = Trainer(model=model, args=train_args, train_dataset=train_ds, tokenizer=tokenizer)
trainer.train()
if local_rank == 0:
trainer.save_model(SAVE)
dist.destroy_process_group()
print("Qwen3-8B LoRA训练完成")
2 启动脚本 run_8b_ddp.sh
bash
#!/bin/bash
export COREX_HOME=/opt/corex
export LD_LIBRARY_PATH=$COREX_HOME/lib:$LD_LIBRARY_PATH
export GOMP_CPU_AFFINITY="0-15,32-47"
export OMP_NUM_THREADS=16
# ixCCL通信优化
export IXCCL_TIMEOUT=1200
export IXCCL_ALLREDUCE_TIMEOUT=900
export IXCCL_SEND_BUFFER_SIZE=16777216
export IXCCL_RECV_BUFFER_SIZE=16777216
export IXCCL_TRANSPORT_PRIORITY=pcie
export IXCCL_CHUNK_SIZE=4194304
export IXCCL_P2P_ENABLE=0
numactl --cpunodebind=0 --membind=0 \
mpirun --allow-run-as-root -np 2 --bind-to none python3 train_qwen8b_ddp.py
运行命令:
bash
chmod +x run_8b_ddp.sh
./run_8b_ddp.sh
3 训练监控(新开终端)
bash
# 硬件负载
watch -n 2 ixsmi -d 2
# 磁盘IO
watch -n 2 iostat -x /dev/nvme0n1
# 报错实时抓取
dmesg -w | grep -E "iluvatar|ixccl|OOM"
# 查看loss
tail -f /data01/train_logs/qwen8b/runs/*
4 训练后合并权重 merge_8b.py
python
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
base="/data01/models/Qwen3-8B-Instruct"
lora="/data01/lora_out/qwen8b_lora"
merged="/data01/models/Qwen3-8B-MERGED"
tok=AutoTokenizer.from_pretrained(base,trust_remote_code=True)
m=AutoModelForCausalLM.from_pretrained(base,torch.float16,trust_remote_code=True)
m=PeftModel.from_pretrained(m,lora).merge_and_unload()
m.save_pretrained(merged)
tok.save_pretrained(merged)
print("合并完成")
5 推理验证 infer_8b.py
python
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
md="/data01/models/Qwen3-8B-MERGED"
tok=AutoTokenizer.from_pretrained(md,trust_remote_code=True)
m=AutoModelForCausalLM.from_pretrained(md,torch.float16,device_map="cuda",trust_remote_code=True)
def chat(q):
p=f"<|im_start|>user\n{q}<|im_end|>\n<|im_start|>assistant\n"
inp=tok(p,return_tensors="pt").to("cuda")
out=m.generate(**inp,max_new_tokens=512,temperature=0.7)
return tok.decode(out[0],skip_special_tokens=True)
print(chat("天垓150双卡训练规范"))
方案 B:FSDP 双卡极限微调 Qwen3-14B(2 卡能跑最大模型)
核心说明
FSDP 将模型权重、梯度、优化器分片到两张 64GB 卡,突破单卡 64GB 限制,是 2 张天垓 150 能承载最大 Qwen3 基座;
约束:per_device_train_batch_size=1,max_seq_len≤2048,开启全分片 + 梯度检查点。
1 FSDP 训练脚本 train_qwen14b_fsdp.py
import os, torch
import torch.distributed as dist
from torch.distributed.fsdp import FullyShardedDataParallel as FSDP, ShardingStrategy, MixedPrecision
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer
from peft import LoraConfig, get_peft_model
from datasets import load_dataset
# 初始化ixCCL分布式
dist.init_process_group(backend="ixccl")
local_rank = int(os.environ["LOCAL_RANK"])
torch.cuda.set_device(local_rank)
device = torch.device("cuda", local_rank)
MODEL_PATH = "/data01/models/Qwen3-14B-Instruct"
DATA = "/data01/train_data/train.jsonl"
SAVE = "/data01/lora_out/qwen14b_lora"
MAX_LEN = 2048
lora_cfg = LoraConfig(
r=8, lora_alpha=16, lora_dropout=0.05, bias="none",
target_modules=["q_proj","k_proj","v_proj","o_proj"], task_type="CAUSAL_LM"
)
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(
MODEL_PATH, torch.float16, trust_remote_code=True, gradient_checkpointing=True
)
model = get_peft_model(model, lora_cfg)
# FSDP分片配置
fp16_policy = MixedPrecision(
param_dtype=torch.float16, reduce_dtype=torch.float16, buffer_dtype=torch.float16
)
model = FSDP(
model,
sharding_strategy=ShardingStrategy.FULL_SHARD,
mixed_precision=fp16_policy,
device_id=device
)
# 数据处理(同上模板省略,复用前面fmt/tok函数)
def fmt(s):
return f"<|im_start|>user\n{s['instruction']}<|im_end|>\n<|im_start|>assistant\n{s['output']}<|im_end|>"
def tok(sample):
out = tokenizer(fmt(sample), truncation=True, max_length=MAX_LEN, padding="max_length")
out["labels"] = out["input_ids"].copy()
return out
ds = load_dataset("json", data_files=DATA, split="train")
train_ds = ds.map(tok, remove_columns=ds.column_names)
# 极小batch适配14B大模型
train_args = TrainingArguments(
output_dir=SAVE,
per_device_train_batch_size=1,
gradient_accumulation_steps=4,
learning_rate=1.5e-4, num_train_epochs=3, fp16=True,
logging_dir="/data01/train_logs/qwen14b", logging_steps=5,
save_steps=50, save_total_limit=1, dataloader_num_workers=4,
local_rank=local_rank, ddp_backend="ixccl", ddp_timeout=2400,
report_to="none", overwrite_output_dir=True
)
trainer = Trainer(model=model, args=train_args, train_dataset=train_ds, tokenizer=tokenizer)
trainer.train()
if local_rank == 0:
trainer.save_model(SAVE)
dist.destroy_process_group()
print("Qwen3-14B FSDP LoRA训练完成")
2 FSDP 启动脚本 run_14b_fsdp.sh
bash
#!/bin/bash
export COREX_HOME=/opt/corex
export LD_LIBRARY_PATH=$COREX_HOME/lib:$LD_LIBRARY_PATH
export GOMP_CPU_AFFINITY="0-15,32-47"
export OMP_NUM_THREADS=16
export IXCCL_TIMEOUT=1800
export IXCCL_ALLREDUCE_TIMEOUT=1200
numactl --cpunodebind=0 --membind=0 \
mpirun --allow-run-as-root -np 2 --bind-to none python3 train_qwen14b_fsdp.py
执行:
bash
chmod +x run_14b_fsdp.sh
./run_14b_fsdp.sh
3 合并 & 推理(和 8B 流程一致,更换模型路径即可)
二、交付选型总结
- 常规 AI 微调、稳定长期训练:Qwen3-8B(DDP 双卡),速度快、显存充足、无 OOM 风险;
- 必须更大基座、硬件上限拉满:Qwen3-14B(FSDP 双卡分片),2 张天垓 150 硬件能承载的最大 Qwen3 模型;
- Qwen3-30B/32B:2 张 64GB HBM 无论 DDP/FSDP 均无法正常微调,需 4 卡及以上。
三、交付归档全套必备日志
- ixsmi 硬件识别、双卡拓扑截图
- all_reduce_perf 双卡通信带宽日志
- NVMe SSD 测速完整日志
- 训练终端完整输出、loss 收敛记录
- 训练全程 ixsmi 硬件监控截图
- LoRA 适配器权重 + 合并后完整模型
- 推理问答效果样例
更多推荐


所有评论(0)