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、Node Feature Discovery(NFD)资源,或面向实例的拓扑JSON。
已与Topograph实现可用集成的云提供商包括谷歌云、Lambda、Nebius、Nscale和OCI,更多云及托管服务提供商的集成正在开发中。
在本地部署时,可使用配合ibnetdiscover的InfiniBand提供程序,或用于Spectrum-X或多节点NVLink(MNNVL)域的NetQ。
提供程序接口是开放的,运维人员可以为自己的环境添加相应实现,并将其贡献至上游项目。
环境与引擎支持情况
范围与说明。该矩阵反映的是截至2026年9月16日上游主分支的情况。它展示了受支持的提供程序到引擎输出的组合;具体要求可能因Topograph版本、环境及提供程序配置而有所不同。
Crusoe提供程序从Crusoe托管Kubernetes节点读取网络结构和加速器域标签;因此该提供程序需要Topograph运行在Kubernetes中。
Slurm引擎可以在Kubernetes中运行,但需要为其配置的topology.conf输出路径提供可写卷。
NFD引擎需要启用alpha版NodeFeatureGroupAPI功能开关。Kubernetes引擎则改为发布节点标签。
保持视图随集群变化实时更新
五个组件共同维持该视图的实时性:
API服务器:验证请求、聚合重复项并调度发现流程
节点观察器:监控配置的Kubernetes节点或Pod变化以及API就绪状态,并通过重试机制请求重新生成
节点数据代理:收集各节点属性并将其存储为节点注解
提供程序:将云端或网络结构数据转换为规范表示形式
引擎:以调度器可理解的格式写入该表示形式
客户端如何查询拓扑
API服务器提供五个服务端点:
POST /v1/generate — 提交异步请求,并以HTTP 202返回请求ID。
GET /v1/topology?uid=<请求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为可选项。
使用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.topograph.run/tier-<N> # 其他被发现的层级
accelerator.topograph.run/domain # 加速器域
accelerator.topograph.run/sub-domain # 可选的嵌套子域
网络结构第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所在的第0层域,同时也会为第1层局部性给予奖励。由于默认调度器逐个部署Pod,这只是一种偏好,而非全局最优的组部署。
KAI Scheduler和Kueue可以使用相同的节点标签实现拓扑感知的组部署。Kubernetes 1.36也通过KEP-5732引入了alpha版拓扑感知工作负载调度。上游的beta版工作正在进行中,请参考增强功能跟踪器,而非依赖某个具体的未来版本。
使用KAI Scheduler实现拓扑感知组调度
KAI Scheduler(一个由NVIDIA捐赠的CNCF沙箱项目)将节点标签组织为层次结构:
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作业添加注解:
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
required注解确保整个组保持在单一第1层域内。preferred注解则要求KAI在可行的情况下将Pod集中到某个第0层域,但允许在该必需边界内存在多个第0层域。
有关更高级的拓扑感知调度示例,请参阅Grove和NVIDIA Dynamo的相关文档。
Grove提供了用于分层组调度、拓扑感知部署和协调扩缩容的Kubernetes API及操作器。Dynamo是一个开源分布式推理服务框架,与Grove集成以实现Kubernetes工作负载编排。
通过NFD发布拓扑(引擎:nfd)
Topograph还支持已经在使用Node Feature Discovery的用户。nfd引擎为每个选定的拓扑节点发布一个NodeFeature,并为每个不同的网络结构层级、XCLR域和XCLR子域值发布一个NodeFeatureGroup。NFD master会评估这些规范,并管理每个组的status.nodes成员关系。
首先安装nfd,并启用其alpha版NodeFeatureGroupAPI功能开关;该功能默认关闭。然后选择引擎和NFD master运行所在的命名空间:
engine:
name: nfd
nfdNamespace: node-feature-discovery
当下游组件消费NodeFeatureGroup对象时使用此输出;它并非Kubernetes topologyKey标签的替代方案。对于原生Pod亲和性、KAI Scheduler或Kueue TAS,请继续使用engine: k8s。该chart将NFD权限限定在nfd命名空间内。该引擎在协调完成后会删除过时的Topograph管理对象,但如果某次生成未产生结果,则会保留上一次发布的拓扑结构。
在Slurm上解决该问题(引擎:slurm)
Topograph以tree和block格式生成集群范围的配置,如下图2中上中和下中面板所示。Slurm 25.05引入了YAML格式的按分区配置,Topograph同样支持,如图所示。
安装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"
对于集群范围的tree输出,使用绝对路径:
{
"engine": {
"name": "slurm",
"params": {
"plugin": "topology/tree",
"topologyConfigPath": "/etc/slurm/topology.conf",
"reconfigure": true
}
}
}
使用topology/block加上可选的blockSizes可获得block输出。
可选的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。
以Helm chart形式安装Topograph:
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、按分区以及InfiniBand block部署。
当选定的slurmd Pod发生变化时,Topograph会重新生成并更新ConfigMap。
对于MNNVL系统,dra提供程序是一个范围更窄的Slinky block拓扑选项。它在重新生成拓扑配置时会读取现有的nvidia.com/gpu.clique标签。
对于动态Slurm节点,可选的useDynamicNodes模式还会为选定的Kubernetes节点添加当前Slurm拓扑规范的注解。ConfigMap更新和动态节点协调是两种不同的机制,因此需要根据所部署的Slinky配置选择合适的模式。
开始使用
部署问题会随着规模扩大而累积,并表现为网络拥塞。Topograph为调度器提供了一份实时、由提供程序上报的物理网络地图,使拓扑感知决策在云端和本地环境中都能保持一致,且无需人工维护。
通过KAI Scheduler、Kueue以及原生Kubernetes,该地图能够提升AI工厂的效率、每瓦特Token产出以及成本效益。
可从dsx-ai-factory/topograph的GitHub仓库部署Topograph,或进一步了解DSX OS生态系统。
Q&A
Q1:NVIDIA Topograph是什么?主要用来解决什么问题?
A:NVIDIA Topograph是一款开源工具包,用于发现和映射集群的网络拓扑结构,帮助工作负载管理器实现拓扑感知的调度决策。它主要解决GPU工作负载部署不合理导致拓扑域碎片化、流量拥堵、吞吐量下降和作业成本上升的问题。
Q2:Topograph支持哪些调度平台?
A:Topograph支持Kubernetes、Slurm和Slinky三种主流调度平台,可以将拓扑信息以对应格式发布,包括Kubernetes节点标签、Slurm拓扑配置文件,以及Slinky的ConfigMap。
Q3:Topograph如何与KAI Scheduler配合实现组调度?
A:Topograph将拓扑信息发布为节点标签后,KAI Scheduler可以基于这些标签构建层次化拓扑结构,并通过required和preferred注解控制工作负载的部署范围,实现在单一网络域内的拓扑感知组调度,从而提升通信效率。
