- 安装与所用设备兼容的 Docker。
- 从 Releases 中的 Assets 页面下载与所用平台相符的
chitu-<version>.run的文件。 - 为其添加可执行权限:
chmod +x chitu-<version>.run - 运行:
./chitu-<version>.run <arguments>
关于运行参数,请参阅 赤兔 CLI 参数 。
此可执行文件会在内部使用 Docker 容器运行赤兔。
docker run --pid=host --rm --gpus=all --privileged --shm-size=1g \
-v <your_model_path>:<container_model_path> \
<your_image_name> \
<your_command>docker run \
--pid=host \
--rm \
--device /dev/davinci0 \
--device /dev/davinci1 \
--device /dev/davinci2 \
--device /dev/davinci3 \
--device /dev/davinci4 \
--device /dev/davinci5 \
--device /dev/davinci6 \
--device /dev/davinci7 \
--device /dev/davinci_manager \
--device /dev/devmm_svm \
--device /dev/hisi_hdc \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \
-v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v <your_model_path>:<container_model_path> \
<your_image_name> \
<your_command>
docker run \
--pid=host \
--rm \
--device=/dev/dri \
--device=/dev/mxcd \
--group-add video \
--privileged=true \
--security-opt seccomp=unconfined \
--security-opt apparmor=unconfined \
--shm-size=100gb \
--ulimit memlock=-1 \
-v <your_model_path>:<container_model_path> \
<your_image_name> \
<your_command>
docker run -dit \
--pid=host \
-u root \
--network=host \
--privileged \
--device=/dev/kfd \
--device=/dev/dri \
--ipc=host \
--shm-size=100G \
--group-add video \
--cap-add=SYS_PTRACE \
--security-opt seccomp=unconfined \
--ulimit stack=-1:-1 \
--ulimit memlock=-1:-1 \
-v /opt/hyhal:/opt/hyhal:ro \
-v <your_model_path>:<container_model_path> \
<your_image_name> \
<your_command>
docker run -dit \
--network=host \
--privileged \
--shm-size=100G \
--ulimit memlock=-1 \
--env MTHREADS_VISIBLE_DEVICES=all \
--pid=host \
-v <your_model_path>:<container_model_path> \
<your_image_name> \
<your_command>
# 下载源码,注意使用 --recursive 选项获取第三方依赖
git clone --recursive https://github.com/thu-pacman/chitu && cd chitupip install -r requirements-build.txt如果你选择的可选依赖中包含 deep_ep,还需要运行以下之一:
若为 CUDA 12:
pip install -r requirements-build-deep_ep-cu12.txt若为 CUDA 13:
pip install -r requirements-build-deep_ep-cu13.txt在英伟达平台,可以安装最新 PyTorch:
# 选项 A:安装默认 PyTorch 版本
pip install -U torch
# 选项 B:安装以特定版本 CUDA 构建的 PyTorch 版本(将下列命令中的 cu124 修改成你需要的 CUDA 版本)
pip install -U torch --index-url https://download.pytorch.org/whl/cu124在其他平台,请从该平台的提供商处获得相应的 PyTorch 版本。
英伟达平台:
# TORCH_CUDA_ARCH_LIST 的值可通过 `python -c "import torch; print(torch.cuda.get_device_capability())"`` 查看
TORCH_CUDA_ARCH_LIST=9.0 pip install --no-build-isolation . -c <(pip list --format freeze | grep -v "flash-mla" | grep -v "flash_mla")注:
- 通过
-c指定的 constraint 选项使 pip 强制赤兔与系统中已有的软件包兼容,而不是在不兼容时自动升级依赖软件包。这有助于避免安装过程破坏系统中已有的 PyTorch 版本。如果你确实需要升级某些软件包,可以将这些软件包从-c指定的列表中移除。
昇腾平台:
CHITU_ASCEND_BUILD=1 pip install --no-build-isolation . -c <(pip list --format freeze)注:
- 依赖 CANN 和
torch_npu>=2.5。 - 建议通过
third_party/ascend目录中的whl文件安装我们测试过的torch_npu版本。 - 通过
-c指定的 constraint 选项使 pip 强制赤兔与系统中已有的软件包兼容,而不是在不兼容时自动升级依赖软件包。这有助于避免安装过程破坏系统中已有的 PyTorch 版本。如果你确实需要升级某些软件包,可以将这些软件包从-c指定的列表中移除。
海光平台:
CHITU_HYGON_BUILD=1 pip install --no-build-isolation . -c <(pip list --format freeze)
注:
- 通过
-c指定的 constraint 选项使 pip 强制赤兔与系统中已有的软件包兼容,而不是在不兼容时自动升级依赖软件包。这有助于避免安装过程破坏系统中已有的 PyTorch 版本。如果你确实需要升级某些软件包,可以将这些软件包从-c指定的列表中移除。
沐曦平台:
CHITU_MUXI_BUILD=1 pip install --no-build-isolation . -c <(pip list --format freeze)
注:
- 通过
-c指定的 constraint 选项使 pip 强制赤兔与系统中已有的软件包兼容,而不是在不兼容时自动升级依赖软件包。这有助于避免安装过程破坏系统中已有的 PyTorch 版本。如果你确实需要升级某些软件包,可以将这些软件包从-c指定的列表中移除。
摩尔平台:
CHITU_MOORE_BUILD=1 pip install --no-build-isolation . -c <(pip list --format freeze)
注:
- 通过
-c指定的 constraint 选项使 pip 强制赤兔与系统中已有的软件包兼容,而不是在不兼容时自动升级依赖软件包。这有助于避免安装过程破坏系统中已有的 PyTorch 版本。如果你确实需要升级某些软件包,可以将这些软件包从-c指定的列表中移除。
一些可选依赖可通过追加 [optional-dependency-name] 字样安装,例如:
TORCH_CUDA_ARCH_LIST=9.0 pip install --no-build-isolation ".[flash_mla]"当前支持的可选依赖项有:
-
flash_attn: 用于支持infer.attn_type=flash_attn。直接安装 flash_attn 可能很慢,可以到 flash_attn 的 github 上下载相应的预编译包(一个 .whl 文件),然后通过 pip install 这个 .whl 文件。
-
flashinfer: 用于支持infer.attn_type=flash_infer。 -
flash_mla: 用于支持infer.attn_type=flash_mla。 -
flash_linear_attention: 支持通过infer.attn_type=flash_linear_attention运行 Qwen3-Next 系列模型及类似的模型。 -
deep_gemm: 用于支持使用 DeepGEMM 进行 fp8 推理。 -
deep_ep: 用于支持使用 DeepEP 进行 MoE 通信(需要在安装赤兔前先在系统中安装 NVSHMEM,NVSHMEM 已经包含在requirements-build-deep_ep-cu12.txt中) -
cpu: 用于支持 CPU+GPU 混合推理。 -
muxi_layout_kernels: 用于支持在沐曦 GPU 上使用infer.op_impl=muxi_custom_kernel模式,在小 batch 场景性能更优。 -
scipy: 用于支持 DeepSeek-V3.2-Exp 中 FP8 indexer KV cache 的可选依赖。 -
fast_hadamard_transform: 用于支持 DeepSeek-V3.2-Exp 中 FP8 indexer KV cache 的可选依赖。 -
numa: 用于支持 NUMA 绑定。
如果需要用于开发,建议加上 -e 选项启用 editable install,如
TORCH_CUDA_ARCH_LIST=9.0 pip install --no-build-isolation -e .可以通过 CHITU_WITH_CYTHON=1 使用 Cython 对 Python 代码进行编译,如:
TORCH_CUDA_ARCH_LIST=9.0 CHITU_WITH_CYTHON=1 pip install --no-build-isolation .注意:
- 同时设置了
-e和CHITU_WITH_CYTHON=1时,-e不会起作用。如果已经这么做了,需要rm chitu/*.so恢复。
可按如下步骤构建分发产物:
./script/build_for_dist.sh <whether-enable-cython>例如:
./script/build_for_dist.sh true这将创建一个包含 wheel 文件的 dist/ 目录。将它们复制到您想要的位置,然后使用 pip install <wheel_file> 安装它们。如果您必须使用平台的自定义依赖项(例如 torch),请在 pip install 命令后附加 --no-deps。
您也可以选择将 test/ 目录复制到您想要的位置以运行它们。
为了更好的可复现性,可以选择构建容器镜像作为分发产物。
直接使用根目录的 Dockerfile 构建镜像:
docker build \
--build-arg torch_cuda_arch_list='<your_arch_list>' \
--build-arg optional_deps='<comma_separated_optional_deps>' \
--build-arg enable_cython='<true_or_false>' \
--build-arg enable_test='<true_or_false>' \
--build-arg pypi_mirror='<your_pypi_mirror>' \
-t <your_image_name> \
.由于部分依赖需要在构建时访问设备,因此这些依赖必须在 docker run 中安装,而不是 docker build。因此请在构建环境中至少准备一个设备,然后向两阶段构建脚本传入 muxi.Dockerfile 安装:
bash ./script/two-stage-docker-build.sh \
'muxi.Dockerfile' \
'<your_image_name>' \
'<your_image_tag>' \
--optional_deps='<comma_separated_optional_deps>' \
--chitu_setup_jobs='<chitu_setup_jobs>' \
--enable_cython='<true_or_false>' \
--enable_test='<true_or_false>' \
--pypi_mirror='<your_pypi_mirror>' \
-- \
docker run \
--pid=host \
--device=/dev/dri \
--device=/dev/mxcd \
--group-add video \
--privileged=true \
--security-opt seccomp=unconfined \
--security-opt apparmor=unconfined \
--shm-size '<your_shm_size>' \
--ulimit memlock=-1 \
-w /workspace/chitu由于部分依赖需要在构建时访问设备,因此这些依赖必须在 docker run 中安装,而不是 docker build。因此请在构建环境中至少准备一个设备,然后向两阶段构建脚本传入 ascend.Dockerfile 安装:
bash ./script/two-stage-docker-build.sh \
'ascend.Dockerfile' \
'<your_image_name>' \
'<your_image_tag>' \
--optional_deps='<comma_separated_optional_deps>' \
--chitu_setup_jobs='<chitu_setup_jobs>' \
--enable_cython='<true_or_false>' \
--enable_test='<true_or_false>' \
--pypi_mirror='<your_pypi_mirror>' \
-- \
docker run \
--pid=host \
--privileged \
--device /dev/devmm_svm \
--device /dev/hisi_hdc \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \
-v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v /dev/davinci<npu_id>:/dev/davinci<npu_id>
-w /workspace/chitu由于部分依赖需要在构建时访问设备,因此这些依赖必须在 docker run 中安装,而不是 docker build。因此请在构建环境中至少准备一个设备,然后向两阶段构建脚本传入 hygon.Dockerfile 安装:
bash ./script/two-stage-docker-build.sh \
'hygon.Dockerfile' \
'<your_image_name>' \
'<your_image_tag>' \
--optional_deps='<comma_separated_optional_deps>' \
--chitu_setup_jobs='<chitu_setup_jobs>' \
--enable_editable_install='<true_or_false>' \
--enable_cython='<true_or_false>' \
--enable_test='<true_or_false>' \
--pypi_mirror='<your_pypi_mirror>' \
-- \
docker run \
-u root \
--network=host \
--pid=host \
--privileged \
--device=/dev/kfd \
--device=/dev/dri \
--ipc=host \
--shm-size='<your_shm_size>' \
--group-add video \
--cap-add=SYS_PTRACE \
--security-opt seccomp=unconfined \
--ulimit stack=-1:-1 \
--ulimit memlock=-1:-1 \
-v /opt/hyhal:/opt/hyhal:ro \
-w /workspace/chitu您可以将 Docker 镜像转换为 Apptainer 镜像。使用 Apptainer 运行可免于与守护进程交互。
apptainer build <your_apptainer_image.sif> <your_docker_image>chitu.run 是赤兔的一种独立可执行文件形式的分发产物。
即使有了 Docker 或 Apptainer 镜像,你仍然需要通过复杂的命令或脚本来在启动时配置硬件相关设置,并分布式地在多个节点的多个 GPU 上启动。为了解决这个问题,Chitu 支持构建 chitu.run,支持可以通过单条命令启动。
要构建 chitu.run,请先构建 Docker 镜像或 Apptainer 镜像,然后运行以下命令:
从 Apptainer 镜像(.sif 文件)构建:
./boot/build.sh <your_apptainer_image.sif> -o chitu.run从 Docker 镜像构建(将镜像打包到内部):
./boot/build.sh <your_docker_image:tag> -o chitu.run从 Docker 镜像构建但不将镜像打包到内部(生成更小的包;用户将在运行时从在线资源拉取镜像):
./boot/build.sh <your_docker_image:tag> -o chitu.run --online选项:
| 选项 | 说明 |
|---|---|
-o, --output-file <file> |
AppImage 输出文件的路径(必需)。 |
--online |
生成不包含容器镜像的更小的包。用户将从在线资源拉取镜像。 |
-h, --help |
显示帮助信息。 |
输出是一个可独立使用的 AppImage 可执行文件,可直接运行。其中所有的参数均在 赤兔 CLI 参数 定义。
./chitu.run [参数]...如果您与他人共享测试环境,请合理使用作业管理工具进行资源分配,避免资源冲突。
赤兔所使用的所有运行时配置项的定义可参考 赤兔 CLI 参数。您可以使用命令行参数覆盖相关的参数设置(参考 Hydra 文档),也可以使用环境变量 CHITU_CONFIG_PATH=<path/to/config/directory> 及 CHITU_CONFIG_NAME=<your_config_file.yaml> 另行指定配置文件。需要提醒的是,chitu/config/models/ 目录中的 yaml 文件并非完整的配置文件,切勿直接将 CHITU_CONFIG_NAME 指向它们。新指定的配置文件目录应该包含所有直接或间接被使用的配置文件,包括模型配置文件。
注:此示例中的参数可能并非最佳。最佳参数需根据实际应用需求与硬件需求调整。
torchrun --nproc_per_node 8 test/single_req_test.py \
models=deepseek-r1 \
models.ckpt_dir=/data/DeepSeek-R1 \
infer.tp_size=8 \
infer.pp_size=1 \
infer.cache_type=paged \
infer.attn_type=flash_mla \
infer.mla_absorb=absorb-without-precomp \
infer.max_batch_size=1 \
infer.max_seq_len=512 \
request.max_new_tokens=100运行日志存储在 outputs/ 目录下。
python3 script/generate_supported_models_docs.py --print更多模型请参见 支持的模型。
torchrun --nproc_per_node 8 test/single_req_test.py request.max_new_tokens=64 models=DeepSeek-R1 models.ckpt_dir=/data/DeepSeek-R1 infer.pp_size=1 infer.tp_size=8赤兔支持多种并行策略。
对于一般模型,赤兔支持 TP(张量并行)、PP(流水线并行)以及多实例部署,如下图所示:
对于 MoE 模型,模型中的 attention 块和 MoE 块可以通过不同方式并行:
- Attention 块可通过 TP(张量并行)和 DP(数据并行)进行并行。
- MoE 块可通过 ETP(专家张量并行)、EP(专家并行)以及(静态或动态)将专家复制到专家槽位进行并行。
- 在 attention 块和 MoE 块之上,还可以进一步通过 PP(流水线并行)以及多实例部署进行并行。
如下图所示:
赤兔会让通信量大的并行方式优先在更近的设备之间通信:
- 对于一般模型或 MoE 模型中的 attention 块,TP 组由最近的设备组成,DP 组由次近的设备组成,PP 组由最远的设备组成。若以分布式网格的方式描述,网格的形状是 PP * DP * TP。请注意赤兔中的 DP 是用于 MoE 中的 attention 块的,所以 DP 在网格中位于 PP 和 TP 之间,而非 PP 之外。若要通过复制权重的方式扩展非 MoE 模型的并行性,请使用多实例部署而非 DP。
- 对于 MoE 模型中的 MoE 块,ETP 组由最近的设备组成,EP 组由次近的设备组成,PP 组由最远的设备组成。若以分布式网格的方式描述,网格的形状是 PP * EP * ETP。MoE 块还可以通过将专家复制到专家槽位的方式来扩展并行性。这种方式类似 DP,但更加灵活。
TP、DP、ETP、EP 和/或 PP 可通过传入 tp_size、dp_size、etp_size、ep_size 和/或 pp_size 参数开启。ETP 的并行度如不设置,默认等于 tp_size * dp_size // ep_size。
对于带有共享专家的 MoE 模型,infer.fuse_shared_experts 还决定共享专家的切分方式。当 infer.fuse_shared_experts=True 时,共享专家被视为 MoE 块的一部分,并按照 infer.etp_size 切分,与路由专家保持一致。当 infer.fuse_shared_experts=False 时,共享专家被视为普通稠密模块,并按照 infer.tp_size 切分。
TP 样例参数:
torchrun --nproc_per_node 2 test/single_req_test.py models=<model-name> models.ckpt_dir=<path/to/checkpoint> request.max_new_tokens=64 infer.tp_size=2PP 样例参数:
torchrun --nproc_per_node 2 test/single_req_test.py models=<model-name> models.ckpt_dir=<path/to/checkpoint> request.max_new_tokens=64 infer.pp_size=2TP+PP 混合的样例参数:
torchrun --nnodes 2 --nproc_per_node 8 test/single_req_test.py request.max_new_tokens=64 infer.pp_size=2 infer.tp_size=8 models=<model-name> models.ckpt_dir=<path/to/checkpoint>利用 chitu.run(参见 构建 chitu.run)部署 4 个单卡实例样例参数:
./chitu.run boot.remote_launcher=srun boot.n_nodes=1 boot.n_gpus_per_node=4 models=<model-name> models.ckpt_dir=<path/to/checkpoint> multi_inst.n_insts=4关于多实例的更多设计,请参阅此文档。
对于 PP,还可以进一步控制 micro batch:
| 参数 | 默认值 | 说明 |
|---|---|---|
pp_micro_batch_size_prefill |
auto |
当 pp_size > 1 且 cache_type 为 paged 时生效。设置为 max 时,限制最大 prefill micro batch size 为 max_reqs_per_dp / pp_size;设置为具体数字时,限制为该数字;设置为 auto 时,自动采用 max 策略。 |
pp_micro_batch_size_decode |
auto |
当 pp_size > 1 且 cache_type 为 paged 时生效。设置为 max 时,限制最大 decode micro batch size 为 max_reqs_per_dp / pp_size;设置为具体数字时,限制为该数字;设置为 auto 时,按照当前 Decode 请求数在 PP group 间动态分配,并以 max 作为静态上限。 |
具体使用:
# 通过设置 scheduler.pp_config 相关参数调整 micro batch size
torchrun --nnodes 1 \
--nproc_per_node 8 \
--master_port=22525 \
-m chitu \
serve.port=21002 \
infer.cache_type=paged \
infer.pp_size=2 \
infer.tp_size=4 \
models=DeepSeek-R1 \
models.ckpt_dir=/data/DeepSeek-R1 \
infer.mla_absorb=absorb-without-precomp \
infer.raise_lower_bit_float_to=bfloat16 \
infer.max_batch_size=1 \
scheduler.pp_config.pp_micro_batch_size_prefill=8 \
scheduler.pp_config.pp_micro_batch_size_decode=auto \
infer.max_seq_len=4096 \
infer.use_cuda_graph=True
可以使用以下脚本命令运行:
./script/srun_multi_node.sh <num_nodes> <num_gpus_per_node> [[additional srun args]... --] [your command after torchrun]...示例 1(使用默认 srun 参数):
./script/srun_multi_node.sh 2 8 test/single_req_test.py models=Qwen3-235B-A22B models.ckpt_dir=/path/to/Qwen3-235B-A22B infer.dp_size=4 infer.tp_size=4 infer.ep_size=16示例 2(与 node 0 交互):
./script/srun_multi_node.sh 2 8 --pty -- test/single_req_test.py models=Qwen3-235B-A22B models.ckpt_dir=/path/to/Qwen3-235B-A22B infer.dp_size=4 infer.tp_size=4 infer.ep_size=16在构建 chitu.run 后(参见 构建 chitu.run),你可以用一条命令在多个节点上启动它。chitu.run 捆绑了容器镜像(Docker 或 Apptainer),并使用 srun 将任务分发到所有节点。
所有参数都定义在 赤兔 CLI 参数 中。与多节点启动最相关的选项位于 boot 部分:
| 参数 | 默认值 | 说明 |
|---|---|---|
boot.n_nodes |
1 |
要使用的节点(服务器)数量。 |
boot.n_gpus_per_node |
1 |
每个节点要使用的 GPU 数量。 |
boot.platform |
"auto" |
容器硬件平台;显式指定时跳过 SMI 自动探测。 |
boot.target |
["-m", "chitu"] |
在容器内运行的目标 chitu 程序或脚本。 |
boot.remote_launcher |
"local" |
如何在多个节点上运行。设置为 srun 以使用 Slurm。 |
boot.interactive_node_0 |
"auto" |
使第一个节点进入交互模式。"auto" 表示自动决定。 |
boot.extra_srun_args |
[] |
传递给 srun 的额外参数。 |
boot.extra_apptainer_args |
[] |
传递给 apptainer run 的额外参数(例如绑定挂载)。 |
boot.extra_docker_args |
[] |
传递给 docker run 的额外参数(例如卷挂载)。 |
示例 1(本地 Apptainer,单节点):
./chitu.run boot.n_gpus_per_node=8 \
"boot.target=[test/single_req_test.py]" \
"boot.extra_apptainer_args=[-B,/path/to/models:/path/to/models]" \
models=Qwen3-235B-A22B \
models.ckpt_dir=/path/to/Qwen3-235B-A22B \
infer.dp_size=4 infer.tp_size=4 infer.ep_size=16示例 2(srun + Apptainer,多节点):
./chitu.run boot.n_nodes=2 boot.n_gpus_per_node=8 \
boot.remote_launcher=srun \
"boot.target=[test/single_req_test.py]" \
"boot.extra_apptainer_args=[-B,/path/to/models:/path/to/models]" \
models=Qwen3-235B-A22B \
models.ckpt_dir=/path/to/Qwen3-235B-A22B \
infer.dp_size=4 infer.tp_size=4 infer.ep_size=16示例 3(srun + Docker,与 node 0 交互):
./chitu.run boot.n_nodes=2 boot.n_gpus_per_node=8 \
boot.remote_launcher=srun \
"boot.target=[test/single_req_test.py]" \
"boot.interactive_node_0=True" \
"boot.extra_docker_args=[-v,/path/to/models:/path/to/models]" \
models=Qwen3-235B-A22B \
models.ckpt_dir=/path/to/Qwen3-235B-A22B \
infer.dp_size=4 infer.tp_size=4 infer.ep_size=16示例 4(将 chitu 代码挂载到容器中):
./chitu.run boot.n_nodes=2 boot.n_gpus_per_node=8 \
boot.remote_launcher=srun \
boot.source_path=. \
"boot.target=[test/single_req_test.py]" \
"boot.extra_apptainer_args=[-B,/path/to/models:/path/to/models]" \
models=Qwen3-235B-A22B \
models.ckpt_dir=/path/to/Qwen3-235B-A22B \
infer.dp_size=4 infer.tp_size=4 infer.ep_size=16注:运行时使用 Docker 还是 Apptainer 取决于 chitu.run 的构建方式(参见 构建 chitu.run)。如果捆绑了 Docker 镜像,则使用
docker run;否则使用apptainer run。
可以使用以下脚本命令运行 Docker:
./script/srun_docker_run_multi_node.sh <num_nodes> <num_gpus_per_node> [[additional srun args]... --] [extra docker args]... <docker_image> torchrun [your command after torchrun]...或 Apptainer:
./script/srun_apptainer_run_multi_node.sh <num_nodes> <num_gpus_per_node> [[additional srun args]... --] [extra apptainer args]... <sif_file> torchrun [your command after torchrun]...示例 1(使用默认 srun 参数):
Docker:
./script/srun_docker_run_multi_node.sh 2 8 --rm -v /path/to/models:/path/to/models your_image:your_version torchrun test/single_req_test.py models=Qwen3-235B-A22B models.ckpt_dir=/path/to/Qwen3-235B-A22B infer.dp_size=4 infer.tp_size=4 infer.ep_size=16Apptainer:
./script/srun_apptainer_run_multi_node.sh 2 8 -B /path/to/models:/path/to/models /path/to/image.sif torchrun test/single_req_test.py models=Qwen3-235B-A22B models.ckpt_dir=/path/to/Qwen3-235B-A22B infer.dp_size=4 infer.tp_size=4 infer.ep_size=16示例 2(与 node 0 交互):
Docker:
./script/srun_docker_run_multi_node.sh 2 8 --pty -- -it --rm -v /path/to/models:/path/to/models your_image:your_version torchrun test/single_req_test.py models=Qwen3-235B-A22B models.ckpt_dir=/path/to/Qwen3-235B-A22B infer.dp_size=4 infer.tp_size=4 infer.ep_size=16Apptainer:
./script/srun_apptainer_run_multi_node.sh 2 8 --pty -- -B /path/to/models:/path/to/models /path/to/image.sif torchrun test/single_req_test.py models=Qwen3-235B-A22B models.ckpt_dir=/path/to/Qwen3-235B-A22B infer.dp_size=4 infer.tp_size=4 infer.ep_size=16示例 3(将 chitu 代码挂载到容器中):
Docker:
./script/srun_docker_run_multi_node.sh 2 8 --rm -v .:/workspace/chitu -v /path/to/models:/path/to/models -e PYTHONPATH=/workspace/chitu your_image:your_version torchrun test/single_req_test.py models=Qwen3-235B-A22B models.ckpt_dir=/path/to/Qwen3-235B-A22B infer.dp_size=4 infer.tp_size=4 infer.ep_size=16Apptainer:
./script/srun_apptainer_run_multi_node.sh 2 8 -B .:/workspace/chitu -B /path/to/models:/path/to/models --env PYTHONPATH=/workspace/chitu /path/to/image.sif torchrun test/single_req_test.py models=Qwen3-235B-A22B models.ckpt_dir=/path/to/Qwen3-235B-A22B infer.dp_size=4 infer.tp_size=4 infer.ep_size=16首先确保各节点直接可以相互无密码 ssh 访问。
这与上文的 Slurm 用法 类似,区别在于将 boot.remote_launcher 设置为 ssh 而非 srun,并通过 boot.ssh_node_list 提供主机列表,而不是依赖 Slurm 分配节点。其余选项保持不变。
示例:
./chitu.run boot.n_nodes=2 \
"boot.ssh_node_list=[host1,host2]" \
boot.n_gpus_per_node=8 \
boot.remote_launcher=ssh \
"boot.target=[test/single_req_test.py]" \
"boot.extra_apptainer_args=[-B,/path/to/models:/path/to/models]" \
models=Qwen3-235B-A22B \
models.ckpt_dir=/path/to/Qwen3-235B-A22B \
infer.dp_size=4 infer.tp_size=4 infer.ep_size=16请在各个节点上启动(而非仅准备镜像)同名的 Docker 容器,然后执行以下脚本命令:
./script/ssh_docker_exec_multi_node.sh <docker-container-name> <pwd-in-container> <comma-separated-hosts> <num_gpus_per_node> [your command after torchrun]...示例:
./script/ssh_docker_exec_multi_node.sh my_container /workspace "host1,host2" 2 test/single_req_test.py models=<model-name> models.ckpt_dir=<path/to/checkpoint> request.max_new_tokens=64 infer.cache_type=paged infer.tp_size=2此直接脚本不支持 Apptainer。
首先确保各节点直接可以相互无密码 ssh 访问,然后执行以下脚本命令:
./script/ssh_multi_node.sh <comma-separated-hosts> <num_gpus_per_node> [your command after torchrun]...示例:
./script/ssh_multi_node.sh "host1,host2" 2 test/single_req_test.py models=<model-name> models.ckpt_dir=<path/to/checkpoint> request.max_new_tokens=64 infer.cache_type=paged infer.tp_size=2可以通过以下命令设置确定的输入输出长度。
torchrun --nproc_per_node 1 test/single_req_test.py \
models=<model-name> \
models.ckpt_dir=<path/to/checkpoint> \
request.prompt_tokens_len=128 \
request.max_new_tokens=64 \
infer.max_seq_len=192 \
infer.max_batch_size=8 script/preprocess_and_save.py 可用于:
- 从完整模型量化并将其保存到新的检查点。
- 为 TP 或 PP 对模型进行分区并将其保存到新的检查点。
- 合并 Q/K/V 或 Gate/Up 矩阵并将其保存到新的检查点。
首先,运行此脚本来预处理并保存模型:
PREPROCESS_AND_SAVE_DIR=<target_directory> torchrun <torchrun_arguments> script/preprocess_and_save.py [your_additional_overrides_to_config]接下来,在正常运行中覆盖模型路径:
<your normal command> models.ckpt_dir=<target_directory> models.tokenizer_path=<target_directory> skip_preprocess=TrueTP 分区的示例用法:
PREPROCESS_AND_SAVE_DIR=<target_directory> torchrun <torchrun_arguments> script/preprocess_and_save.py models=<model-name> models.ckpt_dir=<path/to/checkpoint> infer.tp_size=2
torchrun <torchrun_arguments> test/single_req_test.py infer.tp_size=2 models.ckpt_dir=<target_directory> models.tokenizer_path=<target_directory> skip_preprocess=True赤兔支持 CPU 和 GPU 异构混合推理,可以根据实际硬件资源和性能需求灵活配置。以下是一个简单的示例:
以 H20 机器为例,在安装时加上 cpu 选项。
TORCH_CUDA_ARCH_LIST=9.0 CHITU_SETUP_JOBS=4 MAX_JOBS=4 pip install --no-build-isolation ".[cpu,flash_mla]"参考下面的启动脚本,其中+cpu_layer_num=58表示将其中58层的MoE部分放在CPU上进行运算,可根据GPU显存的容量适当设定层数。
torchrun --nproc_per_node 1 \
--master_port=22525 \
test/single_req_test.py \
models=DeepSeek-R1-Q4_K_M \
models.ckpt_dir=<模型路径> \
models.tokenizer_path=<tokenizer路径> \
infer.use_cuda_graph=True \
quant=gguf \
+cpu_layer_num=58\
infer.tp_size=1 \
infer.pp_size=1 \
infer.cache_type=paged \
infer.attn_type=flash_mla \
infer.mla_absorb=absorb-without-precomp \
infer.max_batch_size=1 \
infer.max_seq_len=256 \
request.max_new_tokens=100# 华为昇腾平台启动额外设置
# 1. 需要指定 infer.attn_type=npu
# 2. 设置环境变量优化执行
# export TASK_QUEUE_ENABLE=2 # 将部分算子适配任务迁移至二级流水,使两级流水负载更均衡,并减少dequeue唤醒时间
# export CPU_AFFINITY_CONF=2 # 优化任务的执行效率,避免跨NUMA(非统一内存访问架构)节点的内存访问,减少任务调度开销
# export HCCL_OP_EXPANSION_MODE=AIV # 利用Device的AI Vector Core计算单元来加速AllReduce
# 在 localhost:21002 启动服务
export WORLD_SIZE=8
torchrun --nnodes 1 \
--nproc_per_node 8 \
--master_port=22525 \
-m chitu \
serve.port=21002 \
infer.cache_type=paged \
infer.pp_size=1 \
infer.tp_size=8 \
models=DeepSeek-R1 \
models.ckpt_dir=/data/DeepSeek-R1 \
infer.mla_absorb=absorb-without-precomp \
infer.raise_lower_bit_float_to=bfloat16 \
infer.max_batch_size=1 \
infer.max_seq_len=4096 \
infer.use_cuda_graph=True测试 OpenAI 兼容接口:
curl localhost:21002/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "What is machine learning?"
}
]
}'测试 OpenAI 文本补全接口(/v1/completions,原始 prompt、不套 chat template):
curl -s localhost:21002/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Kimi-K2.5",
"prompt": "What is machine learning?",
"max_tokens": 32,
"temperature": 0
}'测试 OpenAI Responses 接口:
curl localhost:21002/v1/responses \
-H "Content-Type: application/json" \
-d '{
"model": "DeepSeek-R1",
"instructions": "You are a helpful assistant.",
"input": [
{
"role": "user",
"content": [
{"type": "input_text", "text": "Summarize this image input."},
{"type": "input_image", "image_url": "https://example.com/cat.png"}
]
}
]
}'注意:input_image / input_file 当前仅做接口兼容,会被转换为文本占位,不会触发真正的多模态推理。
测试 Anthropic 兼容接口:
curl localhost:21002/v1/messages \
-H "Content-Type: application/json" \
-H "x-api-key: example_key" \
-d '{
"model": "DeepSeek-R1",
"max_completion_tokens": 128,
"messages": [
{
"role": "user",
"content": "What is machine learning?"
}
]
}'优雅终止引擎和 API 服务(需要 {"confirm": true} 以防止误操作)。已在处理的请求会在服务退出前完成,终止发起后新请求将被拒绝。
curl localhost:21002/terminate_engine \
-X POST \
-H "Content-Type: application/json" \
-d '{"confirm": true}'OpenAI 兼容、OpenAI Responses 兼容和 Anthropic 兼容接口的参数说明请参见 API_PARAMETERS.md。如果需要为新模型适配工具调用,请参见 工具调用适配指南。
赤兔内置了 Grafana 监控面板,可在启动服务时自动启动 Grafana 服务器,提供实时的性能指标可视化(包括吞吐量、GPU 显存使用、KV cache 使用率等)。
在启动服务时,通过以下参数启用 Grafana:
| 参数 | 默认值 | 说明 |
|---|---|---|
metrics.grafana_enabled |
false |
是否在 Rank 0 上自动启动 Grafana 服务器 |
metrics.grafana_host |
localhost |
Grafana 服务绑定地址。设为 0.0.0.0 可允许外部访问 |
metrics.grafana_port |
9095 |
Grafana HTTP 端口 |
启动成功后,通过浏览器访问 http://<host>:<port> 即可查看预配置的监控面板。
注:Grafana 仅在 Rank 0 进程上启动。使用 Docker 部署时,需要将 Grafana 端口映射到宿主机(如
-p 9095:9095)。
示例:
torchrun --nnodes 1 \
--nproc_per_node 8 \
--master_port=22525 \
-m chitu \
models=DeepSeek-R1 \
models.ckpt_dir=/data/DeepSeek-R1 \
infer.tp_size=8 \
infer.cache_type=paged \
infer.attn_type=flash_mla \
infer.mla_absorb=absorb-without-precomp \
infer.max_batch_size=8 \
infer.max_seq_len=4096 \
metrics.grafana_enabled=true \
metrics.grafana_host=0.0.0.0 \
metrics.grafana_port=9095本项目源码中附带了一个性能测试工具,用于测量推理的性能,包括 latency、throughput、tokens per second 等。
要进行性能测试,请先按照上述方式启动推理服务,然后使用下面的命令进行测试。其中的参数可以自行调整。base-url 需要包含 http:// 字段,否则可能报错。
python benchmarks/benchmark_serving.py \
--model "deepseek-r1" \
--max-concurrency 1 \
--num-requests 10 \
--input-len 128 \
--output-len 1024 \
--warmup-requests 3 \
--request-rate inf \
--base-url http://localhost:21002--request-rate 控制请求到达速率,--max-concurrency 限制同时在途的请求数。要压测固定并发的满载吞吐,请设置 --request-rate inf 并指定有限的 --max-concurrency;请求完成后会立即由下一个请求补位,直到处理完该轮的 --num-requests。
--iterations 会重复完整的“warmup -> benchmark -> result”流程,每轮独立输出一份结果。例如,复现三轮、每轮同时发起 8 个请求且等待该轮完成的场景:--max-concurrency 8 --num-requests 8 --iterations 3 --request-rate inf。
此性能测试假设了如下场景。在不同推理引擎或不同平台间进行性能对比时,应保证这些假设一致:
- 即使回答已经结束,每个请求的输出长度也会被固定为你所设置的值(即推理引擎会无视表示序列结束的 EOS token)。
- 会使用默认的采样参数进行推理。默认的采样参数可在
chitu/task.py中的class UserRequest中查看。 - 不在请求间进行缓存。
注意当 --max-concurrency 较大时,性能测试工具会占用大量文件描述符,可能超过 ulimit 限制。建议在运行性能测试前提升限制,如 ulimit -n 65536。
请参阅性能分析。
一些单元测试可用于定位潜在问题:
单卡测试:
pytest [pytest arguments...] ./test/pytest其中可任意添加 PyTest 选项,以控制输出、筛选测例等。
许多测例还支持性能测试。请为 pytest 追加 -s 选项来显式结果。测试中默认的计时轮次仅为 1,所以还请通过追加 --warmup-round=<rounds> --timing-round=<rounds> 选项来调整及时轮次,来获得准确的测量结果。
示例:
pytest --warmup-round=5 --timing-round=20 -s ./test/pytest多卡测试:
torchrun [torchrun arguments...] --no-python ./run_pytest_with_pretty_print.sh [pytest arguments...] ./test/dist_pytest该命令会用不多于此处通过 torchrun 参数的卡数,来运行测试。
由于分布式程序中的错误时常导致通信过程不能正常结束,经常一个测例发生错误会导致其后的其他测例均无法运行。建议为 pytest 追加 -x 选项,以使其在遇到第一处错误后就退出。
示例:
torchrun --nproc_per_node 8 --no-python ./test/dist_pytest/run_pytest_with_pretty_print.sh -x ./test/dist_pytest安装时:
| 名称 | 可选值 | 描述 |
|---|---|---|
CHITU_WITH_CYTHON |
0, 1 |
利用 Cython 编译 Python 源码。 |
CHITU_ASCEND_BUILD |
0, 1 |
面向昇腾构建。 |
CHITU_HYGON_BUILD |
0, 1 |
面向海光构建。 |
CHITU_HYGON_BUILD_FOR_SHCA |
0, 1 |
CHITU_HYGON_BUILD=1 时,面向 SHCA 网卡构建 |
CHITU_MUXI_BUILD |
0, 1 |
面向沐曦构建。 |
CHITU_MOORE_BUILD |
0, 1 |
面向摩尔线程构建。 |
CHITU_SETUP_JOBS |
整数 | 并行编译的进程数。 |
运行时:
| 名称 | 可选值 | 描述 |
|---|---|---|
CHITU_LOGGING_LEVEL |
<level> 或 <module1>:<level1>;<module2>:<level2>;...,各 level 可为 DEBUG、INFO、WARNING、ERROR、CRITICAL,各 module(如设置)可为源码树中任意模块路径,如 chitu.ops。 |
日志级别。 |
CHITU_LOG_STACK_TRACE |
0, 1 |
在每个日志消息后打印调用栈。 |
CHITU_DEBUG |
0, 1 |
调试模式。当前仅用于启用一些计时器。 |
CHITU_CONFIG_PATH |
指向配置文件目录的路径 | 覆盖默认的配置文件目录。 |
CHITU_CONFIG_NAME |
不含 .yml 后缀的配置文件名 | 覆盖默认的配置文件名。 |
CHITU_PREPROCESS_AND_SAVE_DIR |
指向目录的路径 | script/preprocess_and_save.py 的输出目录。 |
CHITU_TORCH_PROFILER_OUTPUT_ROOT |
指向目录的路径 | Torch Profiler trace 输出根目录。参见 性能分析。 |
CHITU_MEM_TRACK |
0, 1 |
启用启动时 CUDA 显存跟踪。参见 性能分析。 |
CHITU_MEM_TRACK_MAX_ENTRIES |
整数 | CUDA 显存跟踪的环形缓冲区大小。参见 性能分析。 |
CHITU_MEM_TRACK_SNAPSHOT_DIR |
指向目录的路径 | CUDA 显存 snapshot 输出目录。参见 性能分析。 |

