核心观点 - HAMi v2.7.0版本正式推出针对NVIDIA GPU的拓扑感知调度功能,旨在解决高性能计算和AI大模型训练场景下的多卡通信瓶颈问题 [2] - 该功能通过智能调度,将计算任务精确部署到物理连接最紧密、通信速度最快的GPU组合上,以最大化加速计算任务并提升集群整体的算力效能 [2] - 其设计哲学是用动态发现代替静态配置,用远见决策代替短视分配,构成了一套成熟、高效的GPU调度方案 [27] 核心特性总览 - 核心设计思想是先在节点本地将复杂的物理拓扑精确量化为设备间的“通信分数”,然后调度器基于这些分数做出最优选择 [5] - 具备动态计算拓扑分数特性,Device Plugin能够通过NVML动态探测节点上GPU间的物理连接拓扑(如NVLink、PCIe),并将其量化为通信分数 [6] - 采用双策略防碎片调度,Fit函数内置寻优算法,针对多卡任务和单卡任务自动采用“最佳匹配”与“最小破坏”策略 [6] 实现原理:拓扑注册与调度决策 - 拓扑注册阶段的目标是将GPU物理连接转化为调度逻辑可理解的标准化的数字分数 [9] - 信息探测环节通过NVIDIA的NVML获取所有GPU两两之间的物理连接类型(NVLink或PCIe) [11] - 数据建模与量化环节首先在内存中构建完整的GPU拓扑图,然后根据预设规则将连接关系计算转换为具体的通信分数 [11] - 最终产物是一个记录了每个GPU的UUID以及它与其他所有GPU之间通信分数的“设备分数表”,并被注册到节点的Annotation中 [11] - 调度决策阶段,Fit函数会先过滤掉不满足基本资源需求的GPU,然后基于设备分数表执行考虑了最佳匹配和最小破坏原则的寻优算法 [11] 代码深度解析:拓扑发现与分数计算 - 拓扑信息的发现与量化在Device Plugin本地完成,并最终生成可供上报的分数表 [13] - 构建拓扑图逻辑由build()函数完成,它初始化设备列表后,通过双重循环遍历所有GPU对,聚合连接信息,构建包含丰富连接信息的完整拓扑图 [15] - 量化为分数由calculateGPUScore函数完成,它会检查两个GPU之间的所有连接并根据详细的switch语句进行评分,最终分数是所有连接分数的总和 [15] 代码深度解析:设备端调度决策 - 调度决策核心逻辑位于设备端的Fit()函数中,该函数会根据请求的GPU数量自动切换寻优策略 [14] - 对于多卡任务(请求多于1个GPU),采用“最佳匹配”原则,目标是寻找内部通信总分最高的GPU组合 [19] - 具体实现是找出所有满足资源需求的空闲GPU,生成所有可能组合,计算每个组合内部所有设备对的分数总和,并选择分数总和最高的组合 [20][23] - 对于单卡任务(只请求1个GPU),采用“最小破坏”原则,目标是选择与其他可用GPU连接最“疏远”的卡 [22] - 具体实现是遍历所有可用单个GPU,计算每个GPU与其他所有可用GPU的分数总和,并选择总分最低的GPU,以保护拓扑完整性 [22] 使用方式 - 用户只需一个Annotation即可启用拓扑感知调度,调度器会根据任务请求的GPU数量自动应用相应的策略 [25] - 启用方式为在Pod的metadata annotations中添加hami.io/gpu-scheduler-policy: "topology-aware" [26]
HAMi × NVIDIA:GPU 拓扑感知调度实现详解