AI 工厂是功率受限的系统,只有在充分优化时才能交付最大价值。GPU 工作负载放置是一项关键优化。糟糕的工作负载放置会碎片化拓扑域,迫使流量穿越共享链路,从而降低吞吐量、提高作业成本,并让 GPU 在等待数据时消耗已配置的功率,却无法推进工作负载。
GPU 在训练和推理过程中持续交换数据,因此分布式工作负载受益于通信局部性。NVIDIA NVLink 和 NVLink Switch 在机架级 GPU 域内提供高带宽、全对全的纵向扩展连接,而 NVIDIA Spectrum-X 以太网 则跨系统和机架提供可预测、低延迟的横向扩展网络。
调度器只有掌握这些 GPU 与网络结构关系的当前、准确视图,才能高效地放置工作负载,而随着集群变化保持该视图最新,正是实践中放置失效的环节。
NVIDIA Topograph 解决了这个问题。它从云 API 或本地网络结构系统发现集群拓扑,将其规范化为通用模型,并以每个工作负载管理器期望的格式发布:Kubernetes 节点标签、Slurm 拓扑配置或 Slinky ConfigMap。在 NVIDIA DSX OS 集群编排层中,Topograph 与 动态资源分配 (DRA) 和 KAI Scheduler 协同工作,以在 AI 工厂基础设施上实现拓扑感知的成组调度。
本文介绍如何部署 Topograph,并使用它在 Kubernetes、Slurm 和 Slinky 上调度拓扑感知工作负载。
核心拓扑问题
Topograph 映射集群硬件的连接方式,以便调度器优先选择邻近资源。将网络视为道路系统:同一局部性域内的 GPU 拥有短距离、高带宽路径,而域之间的流量则穿越更多共享链路和交换机。将紧密耦合的工作负载分散到相距较远的域会增加争用和延迟,因此 Topograph 帮助将工作负载放置在最高效的位置,避免这些瓶颈。
现代 NVIDIA Quantum InfiniBand 端口可达到高达 800 Gb/s,而 NVIDIA NVLink 在其第五代(NVIDIA Blackwell,如 GB200/GB300)中通过专用的 NVIDIA NVLink Switch 网络结构为每个 GPU 提供 1.8 TB/s 的双向带宽,在其第六代(Vera Rubin)中为每个 GPU 提供 3.6 TB/s。这种无阻塞、全对全的设计为每个 GPU 提供专属通道,而非在负载下共享带宽。拥有当前视图的调度器可以优先选择最接近拓扑域中的 GPU。
Slurm 和 Kubernetes 都支持拓扑感知分配,但调度器只能根据其观察到的拓扑采取行动。Topograph 在请求时以及监视到集群变化时重新生成该视图,因此调度器基于当前数据工作,而非手动维护的快照。
跨环境的通用模型
Topograph 是一个开源工具包,用于识别集群的网络拓扑,使工作负载管理器能够做出拓扑感知的调度决策。它有两个概念:提供者(provider)和引擎(engine)。提供者从云 API 或本地系统发现拓扑,并将其规范化为一个规范模型。引擎将该模型转换为 Slurm 配置、Kubernetes 标签、Slinky ConfigMap、节点特性发现(NFD)资源或面向实例的拓扑 JSON。
已与 Topograph 实现可用集成的云提供者包括 Google Cloud、Lambda、Nebius、Nscale 和 OCI,还有更多云和托管机房提供者正在开发中。
在本地使用时,请使用 InfiniBand 提供者 配合 ibnetdiscover
,或使用 NetQ 处理 Spectrum-X 或 多节点 NVLink(MNNVL)域。
提供者接口是开放的,因此运维人员可以为其自身环境添加一个提供者,并向上游贡献。
环境与引擎支持
环境或提供者 | Kubernetes | Slurm | Graph | ||
节点标签(k8s) | NFD 资源(nfd) | Slinky ConfigMap(slinky) | |||
云和托管提供者 | |||||
Crusoe | 是 | 是 | 是 | 是 | 是 |
Google Cloud | 是 | 是 | 是 | 是 | 是 |
Lambda | 是 | 是 | 是 | 是 | 是 |
Nebius | 是 | 是 | 是 | 是 | 是 |
Nscale | 是 | 是 | 是 | 是 | 是 |
Oracle Cloud Infrastructure (OCI) | 是 | 是 | 是 | 是 | 是 |
本地部署模型 | |||||
Kubernetes 中的 InfiniBand | 是 | 是 | 是 | 是 | 是 |
裸金属或虚拟机上的 InfiniBand | 否 | 否 | 否 | 是 | 是 |
本地网络与拓扑 | |||||
Spectrum-X 或 NetQ 管理的网络架构 | 是 | 是 | 是 | 是 | 是 |
MNNVL NVLink 分区(仅 DRA 块拓扑) | 否 | 否 | 是 | 否 | 否 |
表 1. 各引擎支持的拓扑提供者
范围与解释。此矩阵反映截至 2026 年 9 月 16 日的当前上游主分支。它展示了受支持的提供者到引擎输出组合;要求可能因 Topograph 版本、环境和提供者配置而异。
- Crusoe 提供者从 Crusoe Managed Kubernetes 节点读取网络架构和加速器域标签;因此对于该提供者,Topograph 在 Kubernetes 中运行。
- Slurm 引擎可以在 Kubernetes 中运行,但它需要一个可写卷用于其配置的
topology.conf
输出路径。 - NFD 引擎需要 alpha 版 NodeFeatureGroupAPI 特性门控。Kubernetes 引擎则发布节点标签。
随集群变化保持最新
五个组件使该视图保持最新:
API 服务器:验证请求、聚合重复请求并分发发现任务节点观察器:监视已配置的 Kubernetes 节点或 Pod 变更及 API 就绪状态,然后通过重试请求重新生成节点数据代理:收集每个节点的属性并将其存储为节点注解提供程序:将云或网络结构数据转换为规范表示引擎:以调度器可理解的格式写入该表示

图 1. Topograph 接受生成请求,从选定的云或网络结构提供程序发现并规范化拓扑,并发布适用于 Slurm 和 Kubernetes 的调度器就绪输出或面向实例的拓扑 JSON。Kubernetes 部署还可以使用运行时辅助组件来响应集群变更并收集每个节点的数据
客户端如何查询拓扑
API 服务器公开五个服务端点:
POST /v1/generate
– 提交异步请求并返回其 ID 及 HTTP 202。GET /v1/topology?uid=<request-id>
– 处理期间返回 HTTP 202,完成后返回 HTTP 200 及结果。POST /v1/lookup
– 对相同的请求体返回缓存的状态或结果,而无需再次提交。GET /healthz
– 是存活探针端点。GET /metrics
– 公开 Prometheus 指标。
聚合延迟是必需的;通常为 15 秒。重复的相同请求会重置尾随计时器,并且只处理一次,从而减少集群事件突发期间的冗余工作。
在没有生产硬件的情况下进行测试时,仿真模型描述节点和交换机层级结构。kwok-nodes
实用工具和 Kind/KWOK 辅助工具将这些模型转换为虚拟 Kubernetes 节点。
在 Kubernetes 上解决该问题(引擎:k8s)
默认的 Kubernetes 调度器不会发现物理互连层级结构。Topograph 通过将提供程序报告的拓扑发布为节点标签来填补这一空白,原生亲和性和拓扑感知调度器可以消费这些标签。
前提条件是 Kubernetes 1.27 或更高版本、Helm 3.10+ 或 4.x、kubectl 权限,以及受支持的提供程序。KAI Scheduler 或 Kueue TAS 对于拓扑感知的 gang 调度是可选的。
使用 Helm 部署 Topograph
Topograph 以 Helm chart 的形式分发:
helm repo add topograph https://dsx-ai-factory.github.io/topograph
helm repo update
helm install topograph topograph/topograph \
--namespace topograph \
--create-namespace \
--set engine.name=k8s \
--set provider.name=<provider>
将 <provider>
替换为与你的环境相匹配的值。
该仓库在 charts/topograph
中包含了示例 Helm values 文件,其命名以 values.k8s
为前缀,并附有简短的场景描述。每个文件都带有内联配置注释。
安装完成后,请验证部署是否已成功完成:
helm test topograph --namespace topograph
捆绑的测试钩子在集群内查询 /healthz
和 /metrics
并确认响应中包含 topograph_version
指标。
确认 Pod 正在运行:
kubectl get pods -n topograph
验证节点上的拓扑标签
Topograph 使用可变深度标签族表示结构局部性,并使用两级层次结构表示加速器局部性:
fabric.topograph.run/tier-0 # 最接近节点的交换机
fabric.topograph.run/tier-1 # 向外一层 fabric 层级
fabric.topograph.run/tier-<N> # 其他已发现的层级
accelerator.topograph.run/domain # 加速器域
accelerator.topograph.run/sub-domain # 可选的嵌套子域
Fabric 层级 0 是距离计算节点最近的叶交换机,层级编号向外递增。Topograph 仅写入所发现拓扑中存在的层级,没有固定的最大深度。运维人员可以设置 Kubernetes 引擎的 fabricLabels
数组和 acceleratorLabel
参数以使用自定义键;超出该数组的层级不会被标记。子域键是固定的。
要验证标签是否已应用,请运行:
kubectl get nodes --show-labels | grep -E 'fabric\.topograph\.run|accelerator\.topograph\.run'
如果缺少标签,请检查 Topograph 日志:
kubectl logs -n topograph -l app.kubernetes.io/name=topograph
注意: Topograph 反映的是已报告的拓扑,而非预期的拓扑。当生成过程运行时,标签会刷新,例如在被监视的节点或 Pod 发生变化之后。结构变化的可见性取决于提供程序及其触发事件。
暴露 API
该 API 默认是一个 ClusterIP 服务。使用上述 release 和命名空间,其地址为:topograph.topograph.svc.cluster.local:49021
。
用于本地调试:
kubectl -n topograph port-forward svc/topograph 49021:49021
curl http://localhost:49021/healthz
使用标准 Kubernetes 调度
拓扑标签可用作首选 Pod 亲和性中的 topologyKey
值:
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 90
podAffinityTerm:
labelSelector:
matchLabels:
app: myapp
topologyKey: fabric.topograph.run/tier-0
- weight: 70
podAffinityTerm:
labelSelector:
matchLabels:
app: myapp
topologyKey: fabric.topograph.run/tier-1
每个匹配的词项都会为候选节点的评分做出贡献,强烈倾向于现有 app=myapp Pod 所在的 tier-0 域,同时也奖励 tier-1 局部性。由于默认调度器逐个放置 Pod,这是一种偏好,而非全局最优的成组放置。
KAI Scheduler 和 Kueue 可以使用相同的节点标签来实现拓扑感知的成组放置。Kubernetes 1.36 还通过 KEP-5732 引入了 alpha 阶段的拓扑感知工作负载调度。上游的 beta 工作仍在进行中;请查阅增强跟踪器,而不要依赖某个特定的未来版本。
使用 KAI Scheduler 进行拓扑感知的成组调度
KAI Scheduler(由 NVIDIA 捐赠的 CNCF Sandbox 项目)将节点标签组织为一种层级结构:
apiVersion: kai.scheduler/v1alpha1
kind: Topology
metadata:
name: cluster-topology
spec:
levels:
- nodeLabel: topology.kubernetes.io/zone
- nodeLabel: fabric.topograph.run/tier-1
- nodeLabel: fabric.topograph.run/tier-0
- nodeLabel: kubernetes.io/hostname
使用 kubectl apply -f cluster-topology.yaml 应用它
,然后为一个多 Pod 的 Job 添加注解:
apiVersion: batch/v1
kind: Job
metadata:
name: topology-aware-workers
annotations:
kai.scheduler/topology: cluster-topology
kai.scheduler/topology-required-placement: fabric.topograph.run/tier-1
kai.scheduler/topology-preferred-placement: fabric.topograph.run/tier-0
spec:
parallelism: 4
completions: 4
template:
metadata:
labels:
app: inference-worker
spec:
schedulerName: kai-scheduler
restartPolicy: Never
containers:
- name: worker
image: nvcr.io/nvidia/nemo:latest
resources:
limits:
nvidia.com/gpu: 1
必需的注解会将 gang 限制在单个 tier-1 域内。首选的注解要求 KAI 在可行时将 Pod 集中到 tier-0 域中,但允许在必需边界内存在多个 tier-0 域。
有关更高级的拓扑感知调度示例,请参阅 Grove 和 NVIDIA Dynamo 的文档。
Grove 提供 Kubernetes API 和一个 operator,用于分层 gang 调度、拓扑感知放置和协调扩缩容。Dynamo 是一个开源分布式推理服务框架,与 Grove 集成以实现 Kubernetes 工作负载编排。
通过 NFD 发布拓扑(engine: nfd)
Topograph 也支持已在使用 Node Feature Discovery 的使用者。nfd
engine 会为每个选定的拓扑节点发布一个 NodeFeature,并为每个不同的 fabric-tier、XCLR-domain 和 XCLR-sub-domain 值发布一个 NodeFeatureGroup。NFD master 会评估这些规范,并拥有每个组的 status.nodes
成员关系。
首先安装 nfd
,并启用其 alpha NodeFeatureGroupAPI 特性门控;该特性门控默认关闭。然后选择 engine 以及 NFD master 运行的命名空间:
engine:
name: nfd
nfdNamespace: node-feature-discovery
当下游组件消费 NodeFeatureGroup 对象时使用此输出;它不能替代 Kubernetes 的 topologyKey
标签。对于原生 Pod 亲和性、KAI Scheduler 或 Kueue TAS,请继续使用 engine: k8s
。该 chart 将 NFD 权限限定在 nfd
命名空间。引擎会在协调后删除陈旧的 Topograph 管理对象,但如果某一代未生成任何拓扑,则会保留最后发布的拓扑。
在 Slurm 上解决(engine: slurm)
Topograph 以树形和块格式生成集群范围的配置,如下方图 2 的顶部中央和底部中央面板所示。Slurm 25.05 引入了 YAML 格式的按分区配置,Topograph 也支持该格式,如图所示。

图 2. 一个具有 Multi-Node NVLink 域的代表性三层集群拓扑,以及 Topograph 依赖配置的 Slurm 输出模式:集群范围 tree、集群范围 block,或按分区 topology YAML
安装 Topograph
Slurm 集群通常运行在 Linux 裸金属服务器或虚拟机上,其中 Topograph 通过原生包管理器安装。该仓库包含 Debian 和 RPM 构建目标:
make deb # Debian / Ubuntu
make rpm # RHEL / Rocky / SUSE
该软件包会安装服务但不会启动它,因此你可以查看并编辑配置文件 /etc/topograph/topograph-config.yaml
http:
port: 49021
provider: <provider>
engine: slurm
requestAggregationDelay: 15s
将 <provider>
替换为与你的环境匹配的值。
更新配置后,启动服务并验证其是否健康:
sudo systemctl enable --now topograph.service
curl http://localhost:49021/healthz
生成 Slurm 拓扑配置
要启动发现,请向 Topograph 的 /v1/generate
端点发送 POST 请求,该端点会重新生成 Slurm 拓扑配置。
提交请求并轮询其结果:
id=$(curl -s -X POST -H 'Content-Type: application/json' \
-d @payload.json http://localhost:49021/v1/generate)
curl -s "http://localhost:49021/v1/topology?uid=$id"
对于集群范围的树状输出,请使用绝对路径:
{
"engine": {
"name": "slurm",
"params": {
"plugin": "topology/tree",
"topologyConfigPath": "/etc/slurm/topology.conf",
"reconfigure": true
}
}
}
使用 topology/block
加上可选的 blockSizes
以进行块输出。
可选的 reconfigure
参数会在文件写入后运行 scontrol reconfigure
,默认值为 false。如果省略 topologyConfigPath
,Topograph 会从结果端点返回生成的内容,而不是写入文件。
{
"engine": {
"name": "slurm",
"params": {
"topologies": {
"gpu-block": {
"partition": "gpu",
"plugin": "topology/block",
"blockSizes": [8, 16]
},
"cpu-tree": {
"partition": "cpu",
"plugin": "topology/tree"
},
"default": {
"plugin": "topology/flat",
"clusterDefault": true
}
},
"topologyConfigPath": "/etc/slurm/topology.yaml",
"reconfigure": true
}
}
}
对于使用自动发现 Slurm 节点映射的提供程序进行节点状态驱动的刷新,请以 root 身份运行仓库中的脚本:
scripts/create-topology-update-script.sh -p <provider> -c /etc/slurm/topology.conf
它会注册一个永久的 strigger
用于节点上下线转换。它不会检测任意的交换机重新布线或每一次库存变更。
在 Slinky 上解决该问题(引擎:slinky)
Slinky 由 SchedMD 开发,在 Kubernetes 上运行 Slurm。NVIDIA 于 2025 年 12 月收购了 SchedMD。Topograph 的 Slinky 引擎将 Kubernetes 节点映射到 slurmd
Pod,并将 Slurm 拓扑数据写入 ConfigMap。
Slinky 引擎支持集群范围的 topology/tree
和 topology/block
输出,以及用于分区特定配置的多拓扑 YAML。
将 Topograph 作为 Helm chart 安装:
helm repo add topograph https://dsx-ai-factory.github.io/topograph
helm repo update
helm install topograph topograph/topograph \
--namespace topograph \
--create-namespace \
--values my-values.yaml
该仓库提供了可直接适配的 Helm 示例,用于 tree、block、per-partition 和 InfiniBand block 部署。
当所选的 slurmd
Pod 发生变化时,Topograph 会重新生成并更新 ConfigMap。
dra
provider 是面向 MNNVL 系统的一种更窄范围的 Slinky block 拓扑选项。它在重新生成拓扑配置时会读取现有的 nvidia.com/gpu.clique
标签。
对于动态 Slurm 节点,可选的 useDynamicNodes
模式还会用当前的 Slurm 拓扑规范为所选的 Kubernetes 节点添加注解。ConfigMap 更新与动态节点协调是两种不同的机制,因此请选择与所部署的 Slinky 配置相匹配的模式。
快速开始
放置问题会随着规模扩大而叠加,并表现为网络拥塞。Topograph 为调度器提供由 provider 报告的当前物理网络映射,使拓扑感知决策在云端和本地环境中保持一致,无需手动维护。
通过 KAI Scheduler、Kueue 和原生 Kubernetes,该映射可提升 AI 工厂效率、每瓦 token 数和成本效益。
从 dsx-ai-factory/topograph GitHub 仓库 部署 Topograph,或进一步了解 DSX OS 生态系统。
