whitecircle/halo · 上手攻略

  • 仓库:whitecircle/halo
  • 链接:https://github.com/whitecircle/halo
  • 分类:ai / multimodal / llm-infra(训练框架,Python,839 star / 42 fork)
  • 作者:Tom
  • 更新:2026-11-02

版本锚点:本文基于 main 分支提交 8d637d1(2026-11-01)与最新 release v1.1.0(2026-10-11,tag commit 41da083)。镜像 tag 与文档随时可能漂移,命令如与官网不一致,以官网 human-docs/ 为准。

一、它是什么

Halo 是 White Circle(PBC)开源的大模型 / 多模态模型训练框架,定位是"给 Hugging Face 原生模型加上分布式训练能力",而不是另起炉灶造一套 Megatron 式框架。

核心主张有四条:

  1. 直接训练 HF 模型。Trainer 是 HuggingFace / TRL trainer 的子类,checkpoint 仍是标准 SafeTensors,from_pretrained 照常能用。官方称接入一个新的模型族通常只需约 140 行集成代码(博客版本写"约 100 行",两处口径略有出入)。
  2. 并行策略是"包裹"而非"重写"。EP 包裹 MoE block、CP 包裹 attention、TP/ETP 就地切分权重,模型本身不需要分布式改写。
  3. 所有训练方法共用同一套并行与 checkpoint 基础设施。预训练、SFT、偏好优化、蒸馏、RL 都不需要各自实现一遍分布式。
  4. RL 是异步的。训练侧保持纯 Transformers,rollout 侧交给 vLLM / SGLang,两者用 NCCL 同步权重。明确不依赖 Megatron 后端、也不依赖 veRL。

二、解决什么问题

核心痛点是:想在多卡/多机上训 MoE 或长上下文模型,又不想为了并行把 Hugging Face 模型重写一遍、再为训练方法各写一遍分布式逻辑;同时不想为了 RL 再去啃一套 Megatron + veRL 的重型栈。

Halo 给出的答案是:一套代码,从单卡 LoRA 一路覆盖到 8×B300 的 EP+CP MoE 多轮异步 RL,checkpoint 格式始终不变。

官方 benchmark(8×B300,Blackwell 镜像;baseline 是 trl.SFTTrainer + Transformers v5 + FSDP2 ZeRO-3,同模型同数据同 bf16 同 FA4 同 Liger 同 grouped GEMM):

  • gpt-oss-20b 在 4k–16k 长度下吞吐为 stock TRL 的 2.6–3.5×(EP2 / dense EP1;EP8 为 1.7–2.8×),loss 到第 100 步与 baseline 差距在 0.8% 以内。
  • gpt-oss-20b dense EP1,4k、batch 4、关 GC:28,700 tok/s/GPU,8 卡合计约 230k tok/s。
  • Qwen3.5-35B-A3B,4k、batch 4、EP2:16,447 tok/s/GPU @ 1,908 TFLOPS。
  • 16k 同一负载下显存 25–76 GiB/GPU:EP8+CP8 为 24.6 GiB @ 7,149 tok/s/GPU,dense EP1 为 75.8 GiB @ 20,690 tok/s/GPU。
  • Qwen3-30B-A3B,2×B300,EP2,8k:Grouped GEMM 2.45×(batch 1 时 4.10×)。
  • 上下文最长 256k:dense EP1 在 64k 处比 TRL 快 2.1×,256k 处 1.28×。

⚠️ 以上全部是官方自测数据,跑在 B300 上、由项目方自己发布;第三方复现目前尚未见到独立验证(该仓库 2026-08-26 才创建,公开时间不足 3 个月)。README 里 2.3–2.8× 的旧口径(博客、新闻稿)与仓库内 2.6–3.5× 的新口径不一致,属版本迭代,请以后者为准并注明测试条件。

三、快速安装

Halo 只在 Docker 镜像里跑,宿主机不需要 Python 环境(编译好的 kernel 只存在于镜像中)。宿主机需要:NVIDIA 驱动、Docker + NVIDIA Container Toolkit、git。

git clone https://github.com/whitecircle/halo
cd halo

# B200/B300 → FA4 + FA2 + DeepEP
docker pull public.ecr.aws/whitecircle/halo:blackwell
docker tag public.ecr.aws/whitecircle/halo:blackwell halo:blackwell

# H100/H200 → FA2 + FA3 + DeepEP
docker pull public.ecr.aws/whitecircle/halo:hopper
docker tag public.ecr.aws/whitecircle/halo:hopper halo:hopper

匿名拉取,无需 AWS 账号。必须 retag 成 halo:blackwell / halo:hopper,因为文档、Makefile、compose 文件默认用本地名。

镜像 tag 规则::blackwell / :hopper 跟随最新 release;:blackwell-1.1.0 / :hopper-1.1.0 固定版本。没有 latest tag(镜像按架构区分,避免 Hopper 主机误拉 Blackwell 镜像)。RL 推理侧镜像::vllm-0.26.0、:sglang-0.5.17,对应固定 tag :vllm-0.26.0-1.1.0、:sglang-0.5.17-1.1.0。

也可以本地构建(首次很慢,DeepEP、DeepGEMM、Flash Attention 要从源码编译):

make build-blackwell   # 或 make build-hopper

缓存必须指向大盘(权重、数据集、checkpoint 加起来几百 GB,根分区通常很小):

df -h
findmnt -T /mnt -no TARGET,AVAIL   # 确认 /mnt 真在大盘上,而不是名字骗人

四个变量指向容器内外的大盘:HF_HOME、HF_DATASETS_CACHE、TMPDIR、HALO_DATA_ROOT。

启动容器(参数基本是硬要求):

docker run --rm -it --gpus all \
  --ipc=host --ulimit memlock=-1 --ulimit stack=67108864 --shm-size=128g \
  --cap-add=SYS_PTRACE \
  --env-file .env \
  -e HF_HOME=/mnt/hf -e HF_DATASETS_CACHE=/mnt/hf/datasets \
  -e TMPDIR=/mnt/tmp -e HALO_DATA_ROOT=/mnt \
  -v $(pwd):/workspace -v /mnt:/mnt -w /workspace \
  halo:blackwell bash

.env 里放 HF_TOKEN / WANDB_API_KEY /(用 s3 数据集才需要)AWS 三件套。Halo 自己从不加载 .env,手敲 docker run 必须带 --env-file。

容器内验证:

nvidia-smi
python -c "import torch; print(torch.cuda.is_available())"
halo launch --list

四、核心用法

halo 命令只有两个动词:halo launch(起训练)和 halo run(跑工具)。

# 单卡 LoRA SFT
halo launch sft examples/sft/qwen3/qwen3-4b-ultrachat-lora.yaml

# 8 卡全参 SFT
halo launch sft examples/sft/qwen3/qwen3-4b-ultrachat.yaml -n 8

# 8 卡 MoE + 专家并行
halo launch sft examples/sft/qwen3_5/qwen3.5-35b-a3b-ultrachat-ep.yaml -n 8

# FSDP2 + Accelerate
halo launch sft examples/sft/qwen3/qwen3-4b-ultrachat.yaml \
  -a launcher-configs/accelerate/fsdp2_gradop_config.yaml -n 8

# 覆盖 YAML 里的字段(config 之后的参数原样传给 trainer)
halo launch sft examples/sft/qwen3_5/qwen3.5-35b-a3b-ultrachat-ep.yaml \
  -n 8 --expert_parallel_size=8 --learning_rate=1e-5 --max_length=32000

# 看看会执行什么,别真跑
halo launch sft config.yaml --dry-run
halo launch --list        # 列出全部训练方法

CLI 会自动选 launcher:单进程用 python,-n > 1 用 torchrun(EP/CP/TP 必需),-a 用 accelerate launch。

方法名就是脚本文件名的 stem:sft、smpo、dpo、kto、offline-grpo、rlvr(在线 GRPO)、environmental-grpo(带环境的异步 GRPO),也支持 preference/smpo 这种带路径的形式。

并行开关(EP 只能与 CP / TP / ETP 三者之一组合,其它组合在 config 校验期直接拒绝):

--expert_parallel_size=N          # MoE 专家切分(DeepEP)
--context_parallel_size=N         # 长序列切分(Ulysses attention)
--tensor_parallel_size=N          # 权重切分(DTensor)
--expert_tensor_parallel_size=N   # 专家 FFN 切分(实验性)

配套工具走 halo run:

halo run merge-ep-shards --input_dir <ep-checkpoint-dir> --output_dir <merged-dir>
halo run quantize-to-lowp --input_dir <bf16-model-dir> --output_dir <nvfp4-out-dir> --format nvfp4
halo run prepare-dataset      # 离线 tokenize / packing / 分片
halo run run-env -- ...        # 在 RL 环境上评测模型
halo run --list

看训练日志(rank 0 的输出会复制到 output_dir):

tail -f checkpoints/sft-qwen3-4b-ultrachat/log/run.log

LoRA 训练产物是 adapter,要单独 merge 或作为 adapter 部署;开了 save_sharded_ep: true 的分片 EP 存档要先 halo run merge-ep-shards。

五、典型适用场景

  • 单卡消费级 GPU 微调:QLoRA 路径。Qwen3-4B QLoRA 官方例子峰值 7.9 GiB(batch 1、4k),Qwen3-8B 在 32k 下 20.9 GiB——24 GB 卡可跑。但 A100/RTX 3090/4090 走 halo:blackwell 的 FA2/SDPA 路径官方明确标注"not validated"。
  • MoE 大规模训练:Qwen3 MoE 是覆盖最广的参考族;GPT-OSS、GLM-4 MoE Lite 覆盖也全。EP + DeepEP 通信。
  • 长上下文:CP(Ulysses attention)专门给长序列准备,只对 SFT / SMPO / offline GRPO 开放(其他 loss 会跨序列 shard 错误池化)。
  • 多轮环境 RL:异步 GRPO + Ray actor + vLLM/SGLang rollout server,多个 server 时用 prefetch queue 把下一轮生成和训练重叠起来。
  • HF 生态迁移:已有 HF Trainer / TRL 脚本、已有 HF checkpoint 格式、想在不改 checkpoint 兼容性的前提下扩到多机。

多模态方面:Gemma 4、Mistral 4、Command A+、Inkling、GLM-5 Next、Step-3.7 Flash、Qwen3.5/3.6、Qwen3-VL 是原生多模态的;带图走 VLM 路径(图片不能 packing),纯文本数据集走文本路径(可用 packing);多模态支持 SFT / DPO / KTO / SMPO 和两个蒸馏器,奖励建模仅限带多模态序列分类头的 checkpoint。

六、坑与注意

  1. 现象:宿主机 pip install 后 import 报 flash_attn / deep_ep 缺失。影响:起不来。修复:别在宿主机装,Halo 的编译 kernel 只在镜像里;按 GPU 选对 halo:blackwell / halo:hopper。
  2. 现象:容器里 GPU 不可见或 token 读不到。影响:训练直接失败或读到错误模型。修复:--gpus all + --env-file .env 都要带;Halo 从不自动加载 .env;检查 NVIDIA Container Toolkit。
  3. 现象:CUDA OOM。影响:训练中断。修复:按顺序调——gradient_checkpointing: true(代价约 20–30% step 时间)→ 减小 per_device_train_batch_size 或 max_length → 切分(dense 用 TP,MoE 用 EP/ETP)→ 或直接用 LoRA/QLoRA。
  4. 现象:EP 在单 NVLink 域内报错"forms K concurrent >2-rank DeepEP dispatch groups"。影响:起不来。修复:单域作业下 EP 取 2 或等于域大小;8 卡 4 路切分用 ep4 + etp2;ep4 + tp2 同样会被拒。
  5. 现象:权重同步组永远组不起来 / trainer 启动即 Errno 98。影响:RL 训练不可用。修复:两个容器都要 network_mode: host(bridge 网络会屏蔽回连端口);默认权重同步端口 51216 落在 Linux 临时端口区(32768–60999),需在 net.ipv4.ip_local_port_range 之外指定 group_port,或写进 ip_local_reserved_ports。
  6. 现象:reward 看着正常但策略退化。影响:RL 训歪且难定位。修复:盯 sampling/logratio_mean;MoE 模型必须用 --moe-backend triton 服务,自动选择的 backend 会静默破坏同步过去的专家权重。
  7. 现象:恢复训练报 "checkpoint(s) are incomplete on at least one node" 或 optimizer_meta.pt is missing。影响:断点续训失败。修复:中断的存档只写了一半(trainer_state.json 最后写),从更早的 checkpoint 恢复;或设 allow_optimizer_warm_restart: true 保留权重、重置优化器动量。
  8. 现象:loss 只在 2048 token 之后明显劣化。影响:长上下文训练质量静默下降。修复:TF32 在长上下文 RoPE 上会掉精度;Halo 默认在加载时把 fp32 matmul 钉死为全精度,只有你手动把 HALO_FP32_MATMUL_PRECISION 设成 high/medium 才会踩到,把它取消设置。
  9. 现象:数据集 map 之后输出乱码或索引越界崩溃。影响:数据流水线不可复现。修复:日志里搜 Dataset-map cache fingerprint;map 的输出依赖了缓存指纹无法哈希的值,代码里用 cache_key_extras 传进去,或直接清 HF_DATASETS_CACHE。
  10. 现象:分布式校验器在启动时直接拒绝配置(must divide / not supported)。影响:跑不起来但错误信息晦涩。影响面:这是设计行为而非 bug——它拦下的是会在跑到一半时挂死或崩溃的形状组合。修复:按报错里点名的规则查 human-docs/parallelism.md。
  11. 现象:写盘中途报写入错误 / 宿主机内存飙升 OOM。影响:中断或影响整机。修复:缓存或输出落在小根分区,重新检查 HF_HOME/HF_DATASETS_CACHE/TMPDIR/HALO_DATA_ROOT;加载模型时默认半数的 rank 同时加载(上限 4),显存紧时设 max_concurrent_loading: 1。
  12. 现象(许可,最容易踩):GitHub API 返回 license 为 NOASSERTION。影响:商用前需人工确认条款。修复:Halo License = Apache-2.0 加 Supplemental Terms:把 Halo 训练功能作为服务卖给第三方,相关年收入在任意连续 12 个月内不超过 2000 万美元是免费的,超过需与 White Circle 签商业协议;年收入超 2000 万美元的用户,用 Halo 训出的模型必须带 "Trained with Halo" 署名。仓库卡片里的 NOASSERTION 不是"无许可"。

补充坑:部分模型有硬性限制,选型前必看 supported-matrix.md——DeepSeek-V4 只支持 eager attention、拒绝 packing 和 padding_free、每行只能一个文档;Gemma 4 无 flash kernel、KV 共享层禁用 CP/TP;Qwen3.5/3.6 混合线性注意力禁用 CP;Zaya 不能开 gradient checkpointing;Laguna / Bailing-Ling 没有自动 fallback,必须手写 attn_implementation: sdpa。CP 只对 SFT、SMPO、offline GRPO 开放(且 offline GRPO 的 CP 只支持全参微调,PEFT / 显式 ref_model 会被拒)。流水并行、TP+CP、ETP+CP 等组合在 config 校验期直接拒绝。

七、与同类对比

维度 Halo Megatron-LM veRL / OpenRLHF TRL + Accelerate(原生 HF)
切入点 给 HF 模型包裹并行 重写模型实现 RL 编排层 最朴素
Checkpoint 格式 标准 SafeTensors,from_pretrained 可用 自有格式,常需转换 依赖底层 trainer 标准
支持方法 预训练 / SFT / SMPO / DPO / KTO / RM / 分类 / 蒸馏 / offline GRPO / 在线 RLVR / 异步多轮 GRPO / embedding 预训练 + SFT 为主 专注 RL(PPO/GRPO) SFT/DPO/GRPO/…
MoE 支持 EP + DeepEP V2 + grouped GEMM 成熟且更深 取决于底层 弱
RL 栈 自带:Transformers 训练侧 + vLLM/SGLang rollout + Ray 不含 RL 强(自带 FSDP/Megatron 后端) 弱
上手成本 拉镜像 + 写 YAML 重,模型要适配 中 最低
门槛 必须有 NVIDIA GPU,x86_64 镜像;GB200/GB300(aarch64)无镜像 同类硬件门槛 同类 最低,但性能天花板低

一句话定位:Halo 是"不想换掉 Hugging Face 模型和 checkpoint 格式,但又要 MoE + 长上下文 + 多卡 + RL"的人的最优解;如果你已经在 Megatron 生态或 veRL 生态里,Halo 更像一个"轻量、可插拔、HF 友好的新选项",而不是要你立刻迁移的必需品。

八、一句话推荐结论

推荐:有 Blackwell/Hopper 集群、要训 MoE 或跑多轮异步 RL、且希望 checkpoint 继续兼容 Hugging Face 的团队,Halo 值得直接试(先跑 examples/sft/qwen3/qwen3-4b-ultrachat-lora.yaml 验证环境,再上 EP 配置);暂缓:只有单张消费级卡或没有 A100 以上算力的团队,性能优势基本无从发挥,先按 TRL 生态走更划算。