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注解控制工作负载的部署范围,实现在单一网络域内的拓扑感知组调度,从而提升通信效率。

NVIDIA