【NPU】Ascend Device Plugin 超深度源码分析 — Part 3 设备管理基类 + 910设备管理器 + 热重置容错引擎之二
·
3.2 ascend910.go — HwAscend910Manager 深度解析
3.2.1 结构体与构造函数
type HwAscend910Manager struct {
AscendTools // 嵌入基类
dpu common.DpuInfo // DPU信息(总线类型/DPU列表/NPU→DPU映射)
hotResetManager HotResetManager // 热重置管理器接口
}
func NewHwAscend910Manager() *HwAscend910Manager {
return &HwAscend910Manager{
AscendTools: AscendTools{
name: getAscend910Name(), // A5→"npu", 其他→"Ascend910"
unHealthyKey: common.GetAscend910Key(api.CmCardUnhealthySuffix),
devCount: common.MaxDevicesNum,
cardInResetMap: make(map[int32]bool, common.GeneralMapSize),
resetFailedTimesMap: make(map[int32]int, common.GeneralMapSize),
lastUsedChipsContainerMap: make(map[string]sets.String),
},
}
}
设计意图:
hotResetManager通过接口而非具体类型引用,便于测试mock和未来扩展dpu字段独立于AscendTools,因为DPU是910A5特有的概念- 构造函数只初始化基本字段,
hotResetManager在GraceTolerance首次调用时通过sync.Once延迟初始化
3.2.2 核心流程:GetNPUs — 设备发现
虚拟设备命名规则:
物理设备: Ascend910-{phyID} 例如: Ascend910-0
虚拟设备: {name}-{vDevType}-{vDevID}-{phyID} 例如: Ascend910-4c-1-0
共享设备: {name}-{phyID}-{index} 例如: Ascend910-0-0
3.2.3 核心流程:GraceTolerance — 优雅容错主入口
updateHotResetCache 逐行解析:
func (hnm *HwAscend910Manager) updateHotResetCache(classifyDevs map[string][]*common.NpuDevice) error {
deviceList, ok := classifyDevs[hnm.name]
if !ok {
return fmt.Errorf("ascend npu device list not found")
}
// 1. 更新已隔离设备列表
// 遍历isolateDevList,如果设备已恢复健康则从隔离列表中移除
if err := hnm.updateUpgradeErrorInfo(classifyDevs); err != nil {
return err
}
// 2. 更新全局设备故障信息缓存
// 为每个设备创建DevFaultInfo,设置Policy(隔离/正常/各故障级别)
if err := hnm.hotResetManager.UpdateGlobalDevFaultInfoCache(deviceList, isolateDevList); err != nil {
return err
}
// 3. 设置任务设备信息缓存
// 扫描所有活跃Pod,构建任务→设备列表/故障信息/Pod的映射
if err := hnm.setTaskDevInfoCache(); err != nil {
return err
}
return nil
}
3.2.4 核心流程:processAllTask — 任务级容错处理
3.2.5 核心流程:L2故障处理 (restartRequestProcess)
3.2.6 核心流程:L3故障处理 (restartProcess)
3.2.7 核心流程:L5故障处理 (resetProcess)
3.2.8 故障升级链
3.2.9 核心流程:设备重置执行 (execResetDevice)
3.2.10 设备重置详细流程
3.2.11 核心流程:DoWithVolcanoListAndWatch
3.2.12 核心流程:hotResetHandler — 无任务热重置
isFaultNeedRestart 逐行解析:
func (hnm *HwAscend910Manager) isFaultNeedRestart(devFaultInfo *common.DevFaultInfo) bool {
// 910B系列:FreeResetError或ResetError直接需要重启
if common.ParamOption.RealCardType == api.Ascend910B &&
(devFaultInfo.Policy == common.FreeResetError ||
devFaultInfo.Policy == common.ResetError) {
return true
}
// 其他系列:检查故障持续时间
resetTime := getResetTime(devFaultInfo.LogicId)
if resetTime == 0 {
// 首次检测到故障,记录开始时间,不立即重置
resetTimeMap.Store(devFaultInfo.LogicId, time.Now().Unix())
return false
}
// 故障存在超过 ResetFaultToleranceTimeInterval(60秒) → 需要重置
if time.Now().Unix()-resetTime > common.ResetFaultToleranceTimeInterval {
resetTimeMap.Delete(devFaultInfo.LogicId)
return true
}
return false
}
3.2.13 A3卡关联重置机制
设计意图:A3卡每张物理卡包含2个die(deviceID=0和1),两张物理卡组成一个Ring。重置时必须同时重置Ring上所有4个设备。GetAssociatedLogicIDs 计算出完整的关联设备列表。
3.2.14 核心流程:filterDevStatus — 重置中设备状态过滤
设计意图:当设备正在热重置时,其健康状态会被过滤为Healthy。这是因为:
- 设备正在重置过程中,故障可能已清除但尚未完全恢复
- 避免Volcano调度器将重置中的设备标记为不健康,导致任务被驱逐
- 重置完成后,设备状态由
setAllDevUnhealthyOnRing统一管理
3.2.15 核心流程:waitForAllFaultyDeviceProcessesToZero
func (hnm *HwAscend910Manager) waitForAllFaultyDeviceProcessesToZero(taskName string,
devFaultInfoList []*common.TaskDevInfo) error {
// 1. 获取需要重置的设备LogicID映射
faultDeviceLogicIdMap, err := hnm.getNeedResetDeviceLogicIdMap(devFaultInfoList)
// 2. 创建超时定时器
timer := time.NewTimer(common.WaitProcessesToZeroTime * time.Second)
defer timer.Stop()
timeCount := 0
for {
select {
case <-timer.C:\n // 超时:最后一次检查,如果仍非零→升级为隔离\n if hnm.canContinueGraceProcess(faultDeviceLogicIdMap, taskName, true) {\n return nil // 最后一次检查通过
}
// 超时且进程未归零→更新CM为隔离状态
hnm.updateResetCMStatusToIsolate(taskName, devFaultInfoList)
return fmt.Errorf("check processes timeout")
default:
// 非阻塞检查:每PollingInterval秒检查一次
if hnm.canContinueGraceProcess(faultDeviceLogicIdMap, taskName, false) {
return nil // 所有进程归零
}
time.Sleep(common.PollingInterval * time.Second)
timeCount++
}
}
}
canContinueGraceProcess 和 checkNumberOfAllProcessIsZero:
func (hnm *HwAscend910Manager) checkNumberOfAllProcessIsZero(
faultDeviceLogicIdMap map[int32]int32) (bool, error) {
if len(faultDeviceLogicIdMap) == 0 {
return true, nil
}
isNumberOfAllProcessZero := true
for faultDeviceLogicId, num := range faultDeviceLogicIdMap {
if num == 0 {
continue // 已知为0的设备跳过查询(优化:减少DCMI调用)
}
// 通过DCMI获取设备进程信息
devProcessInfo, err := hnm.dmgr.GetDevProcessInfo(faultDeviceLogicId)
if err != nil || devProcessInfo == nil {
return false, err
}
// 更新映射中的进程数(下次循环可跳过已为0的设备)
faultDeviceLogicIdMap[faultDeviceLogicId] = devProcessInfo.ProcNum
isNumberOfAllProcessZero = devProcessInfo.ProcNum == 0
if !isNumberOfAllProcessZero {
return false, nil // 只要有一个设备进程非0,就返回false
}
}
return isNumberOfAllProcessZero, nil
}
3.2.16 核心流程:updateDeviceInfo — 910设备信息CM更新
func (hnm *HwAscend910Manager) updateDeviceInfo(oldDevInfo, newDevInfo map[string]string,
devStatusSet common.DevStatusSet) error {
// 1. 获取健康设备和需要恢复的设备
nodeFmtDevRecover, nodeFmtDevNetRecover := sets.String{}, sets.String{}
newDevRecoverLabel, newAscend910 := hnm.getHealthAndRecoverDev(devStatusSet,
nodeFmtDevRecover,
common.ConvertDevListToSets(oldDevInfo[common.GetAscend910Key(api.CmCardUnhealthySuffix)],
common.CommaSepDev))
// 2. 获取网络恢复设备
newNetRecoverSets, newNetUHDevSets := hnm.getNewNetworkRecoverDev(
devStatusSet.NetUnHealthyDevice,
common.ConvertDevListToSets(oldDevInfo[common.GetAscend910Key(api.CmCardNetworkUnhealthySuffix)],
common.CommaSepDev),
nodeFmtDevNetRecover)
// 3. 写入各Key的设备列表
newDevInfo[common.GetAscend910Key("")] = newAscend910 // 健康设备
newDevInfo[common.GetAscend910Key(api.CmRecoveringSuffix)] =
common.ToString(devStatusSet.RecoveringDevices, common.CommaSepDev) // 重置中设备
// 4. 推理场景:A800IA2 with HCCS且有故障→阻塞所有设备调度
if common.ParamOption.HotReset == common.HotResetInfer &&
hnm.GetResetFailedTimes(common.FirstDevice) <= common.MaxResetTimes &&
hnm.isNeedBlockAllDevice(devStatusSet.DeviceFault) {
newDevInfo[common.GetAscend910Key("")] = "" // 清空健康设备
newDevInfo[common.GetAscend910Key(api.CmRecoveringSuffix)] =
common.ToString(devStatusSet.AllDevices, common.CommaSepDev) // 所有设备标记为Recovering
}
// 5. 写入不健康/网络不健康/DPU不健康设备列表
newDevInfo[common.GetAscend910Key(api.CmCardUnhealthySuffix)] =
common.ToString(devStatusSet.UnHealthyDevice, common.CommaSepDev)
newDevInfo[common.GetAscend910Key(api.CmCardNetworkUnhealthySuffix)] =
common.ToString(newNetUHDevSets, common.CommaSepDev)
newDevInfo[common.GetAscend910Key(api.CmCardDPUUnhealthySuffix)] =
common.ToString(devStatusSet.DpuUnHealthyDevice, common.CommaSepDev)
// 6. 写入故障详情JSON
data := common.MarshalData(devStatusSet.DeviceFault)
newDevInfo[common.GetAscend910Key(api.CmFaultListSuffix)] = string(data)
// 7. 非自动收纳模式:更新Node Label
if !common.ParamOption.AutoStowingDevs {
curNode, err := hnm.getRecoverLabelFromNodeSets(&nodeFmtDevRecover, &nodeFmtDevNetRecover)
if err != nil { return err }
if err := hnm.update910NodeLabel(curNode, newDevRecoverLabel,
hnm.getPatchLabel(newNetRecoverSets)); err != nil {
return err
}
lastTimeNetworkRecoverDevices = newNetRecoverSets
}
return nil
}
3.3 ascendtolerance.go — HotResetTools 深度解析
3.3.1 结构体定义
type HotResetTools struct {
resetDevNumOnce int // 单次重置设备数(=Ring大小)
allTaskDevList map[string][]int32 // 任务名→设备逻辑ID列表
allTaskDevFaultInfo map[string][]*common.TaskDevInfo // 任务名→设备故障信息列表
globalDevFaultInfo map[int32]*common.DevFaultInfo // 逻辑ID→全局设备故障信息
taskPod map[string]v1.Pod // 任务名→Pod
faultDev2PodMap map[int32]v1.Pod // 故障设备逻辑ID→Pod
resetTask map[string]struct{} // 重置中的任务集合
resetDev map[int32]struct{} // 重置中的设备集合
queue workqueue.RateLimitingInterface // K8s工作队列
podIndexer cache.Indexer // Pod缓存索引器
cmIndexer cache.Indexer // CM缓存索引器
jobs map[string]string // PodKey→JobName映射
noResetCmPodKeys map[string]struct{} // 无Reset CM的Pod Key集合
}
设计意图:
resetDevNumOnce在构造时确定,不同卡类型/用途有不同的Ring大小globalDevFaultInfo是全局设备故障的单一数据源,每次ListAndWatch周期更新allTaskDevFaultInfo从globalDevFaultInfo派生,加入了Rank信息queue+podIndexer+cmIndexer构成了K8s Informer事件驱动架构resetTask和resetDev是两个独立的状态集合,分别跟踪任务级和设备级重置状态
3.3.2 构造函数与Ring大小决策
func NewHotResetManager(devUsage string, deviceNum int, boardId uint32) HotResetManager {
resetDevNumOnce := getResetDevNumOnce(devUsage, deviceNum, boardId)
if resetDevNumOnce == 0 {
return nil // 不支持的设备类型返回nil
}
return &HotResetTools{
resetDevNumOnce: resetDevNumOnce,
resetTask: map[string]struct{}{},
resetDev: map[int32]struct{}{},
faultDev2PodMap: map[int32]v1.Pod{},
jobs: map[string]string{},
noResetCmPodKeys: map[string]struct{}{},
}
}
func getResetDevNumOnce(devUsage string, deviceNum int, boardId uint32) int {
switch common.ParamOption.RealCardType {
case api.Ascend910A:
// 910A: 8卡一个Ring
return common.Ascend910RingsNum
case api.Ascend910B:
if devUsage == common.Infer {
// 推理卡: A800IA2无HCCS→1卡Ring, 其他→训练Ring
if boardId == common.A300IA2BoardId || ... {
return common.Ascend910BRingsNumInfer
}
return common.Ascend910BRingsNumTrain
}
if devUsage == common.Train {
// 训练卡: 8卡Ring, 超过8卡→A200T A2 Ring
resetDevNumOnce = common.Ascend910BRingsNumTrain
if deviceNum > common.Ascend910BRingsNumTrain {
return common.A200TA2RingsNum
}
}
case api.Ascend910A3:
// A3: 全节点关联重置, 设备数=Ring大小
return deviceNum
case api.Ascend910A5:
// A5: 固定Ring大小
return common.Ascend910A5RingsNum
}
return 0 // 不支持的类型
}
3.3.3 核心流程:SyncResetCM — CM/Pod Informer同步
3.3.4 核心流程:handlePodAddEvent — Pod添加处理
设计意图:Pod添加时,为该Pod的Job创建本地目录,并将相关的CM(DataTrace和ResetInfo)写入本地文件。这些文件供设备插件的其他组件(如弹性Agent)读取,实现CM到文件的同步。
3.3.5 核心流程:handleCMUpdateEvent — CM更新处理
func (hrt *HotResetTools) handleCMUpdateEvent(obj interface{}) {
event := obj.(kubeclient.Event)
cm, err := hrt.GetCMFromCache(event.Key)
if err != nil {
hrt.queue.Forget(obj)
return
}
// DataTrace CM: 更新profiling开关文件
if strings.HasPrefix(cm.Name, common.DataTraceCmPrefix) {
dir := fmt.Sprintf("%s/%s", common.DataTraceConfigDir, cm.Namespace+"."+cm.Name)
fileFullName := filepath.Join(dir, common.DataTraceCmProfilingSwitchKey)
// 只在目录已存在时更新(目录由Pod添加事件创建)
if _, checkErr := os.Stat(dir); checkErr != nil {
hrt.queue.Forget(obj)
return
}
hrt.writeCmToFileSystem(cm, common.DataTraceCmProfilingSwitchKey, fileFullName, obj)
return
}
// ResetInfo CM: 更新reset信息文件
if strings.HasPrefix(cm.Name, common.ResetInfoCMNamePrefix) {
dir := common.GenResetDirName(cm.Namespace, cm.Name)
if _, checkErr := os.Stat(dir); checkErr != nil {
hrt.queue.Forget(obj)
return
}
if err = hrt.writeCMToFile(cm); err != nil {
hrt.queue.AddRateLimited(obj) // 写入失败→限速重试
return
}
}
hrt.queue.Forget(obj)
}
3.3.6 核心流程:writeCMToFile — CM数据写入文件
3.3.7 核心流程:GetTaskProcessPolicy — 任务策略决策
func (hrt *HotResetTools) GetTaskProcessPolicy(taskName string) (string, int, error) {
devFaultInfoList, ok := hrt.allTaskDevFaultInfo[taskName]
if !ok {
return "", -1, fmt.Errorf("this task is not in the cache")
}
var processPolicy string
var processPolicyLevel int
// 遍历任务下所有设备的故障信息,取最高级别策略
for _, devFaultInfo := range devFaultInfoList {
devPolicyLevel, ok := processPolicyTable[devFaultInfo.Policy]
if !ok {
return "", -1, fmt.Errorf("invalid policy of device fault info in task %s", taskName)
}
// 取最高级别(最严重)的策略
if devPolicyLevel > processPolicyLevel {
processPolicy = devFaultInfo.Policy
processPolicyLevel = devPolicyLevel
}
}
return processPolicy, processPolicyLevel, nil
}
设计意图:一个任务可能跨多个设备,每个设备有不同的故障级别。任务级策略采用最严重优先原则——以最高级别的设备故障策略作为整个任务的处理策略。
3.3.8 核心流程:UpdateGlobalDevFaultInfoCache — 全局故障缓存更新
func (hrt *HotResetTools) UpdateGlobalDevFaultInfoCache(devDeviceList []*common.NpuDevice,
isoDevList []int32) error {
if len(devDeviceList) == 0 {
return fmt.Errorf("npu device list is nil")
}
// 每次全量重建全局故障缓存
hrt.globalDevFaultInfo = make(map[int32]*common.DevFaultInfo, len(devDeviceList))
for _, device := range devDeviceList {
hrt.globalDevFaultInfo[device.LogicID] = &common.DevFaultInfo{}
hrt.globalDevFaultInfo[device.LogicID].LogicId = device.LogicID
hrt.globalDevFaultInfo[device.LogicID].ErrorCode = device.FaultCodes
if common.IntInList(device.LogicID, isoDevList) {
// 已隔离设备直接设为IsolateError
hrt.globalDevFaultInfo[device.LogicID].Policy = common.IsolateError
} else {
// 根据故障类型获取处理策略
hrt.globalDevFaultInfo[device.LogicID].Policy =
hrt.GetDevProcessPolicy(common.GetFaultType(device.FaultCodes, device.LogicID))
}
}
return nil
}
3.3.9 GetDevProcessPolicy — 设备故障策略映射
func (hrt *HotResetTools) GetDevProcessPolicy(faultType string) string {
switch faultType {
case common.NormalNPU, common.NotHandleFault, common.SubHealthFault:
return common.EmptyError // Level 0: 无需处理
case common.RestartRequest:
return common.RestartRequestError // Level 2: L2请求重启
case common.RestartBusiness:
return common.RestartError // Level 3: L3设备重启
case common.FreeRestartNPU:
return common.FreeResetError // Level 4: L4空闲重置
case common.RestartNPU:
return common.ResetError // Level 5: L5强制重置
default:
return common.IsolateError // Level 6: 隔离
}
}
3.3.10 核心流程:GenerateTaskDevFaultInfoList — 生成任务设备故障列表
func (hrt *HotResetTools) GenerateTaskDevFaultInfoList(devIdList []int32,
rankIndex string) ([]*common.TaskDevInfo, error) {
// 1. 按LogicID排序,确保Rank分配一致性
sort.Slice(devIdList, func(i, j int) bool {
return devIdList[i] < devIdList[j]
})
// 2. 解析Rank起始索引
rankStart, err := strconv.Atoi(rankIndex)
devNum := len(devIdList)
taskDevInfoList := make([]*common.TaskDevInfo, 0, len(devIdList))
for _, devId := range devIdList {
var rankId int
switch rankIndex {
case common.InferRankIndex:
// 推理场景:所有设备使用相同的Rank
rankId = rankStart
default:
// 训练场景:Rank = rankStart * devNum + 当前序号
// 例如:rankStart=0, devNum=8 → 0,1,2,3,4,5,6,7
// rankStart=1, devNum=8 → 8,9,10,11,12,13,14,15
rankId = rankStart*devNum + len(taskDevInfoList)
}
// 从全局缓存获取设备故障信息
faultInfo, ok := hrt.globalDevFaultInfo[devId]
if !ok {
return nil, fmt.Errorf("device %d is not in global cache", devId)
}
taskDevInfo := &common.TaskDevInfo{
RankId: rankId,
DevFaultInfo: *faultInfo, // 值拷贝,避免后续修改影响全局缓存
}
taskDevInfoList = append(taskDevInfoList, taskDevInfo)
}
return taskDevInfoList, nil
}
3.3.11 核心流程:UpdateFaultDev2PodMap — 故障设备-Pod映射更新
func (hrt *HotResetTools) UpdateFaultDev2PodMap(devList []int32, pod v1.Pod) error {
for _, device := range devList {
// 设备有故障→记录映射
if hrt.globalDevFaultInfo[device].Policy != common.EmptyError &&
hrt.globalDevFaultInfo[device].Policy != common.IgnoreError {
hrt.faultDev2PodMap[device] = pod
continue
}
// 设备健康但在重置中→不删除映射(重置期间保持关联)
if _, ok := hrt.resetDev[device]; ok {
continue
}
// 设备健康且不在重置中→删除映射
if _, ok := hrt.faultDev2PodMap[device]; ok {
delete(hrt.faultDev2PodMap, device)
}
}
return nil
}
3.3.12 核心流程:GetTaskResetInfo — 构建任务重置信息
设计意图:两阶段处理:
- 第一阶段:识别哪些Ring有需要重置的设备(故障级别≥L3)
- 第二阶段:将这些Ring上的所有设备(包括非故障设备)都加入重置列表
这是因为Ring级别的重置会影响Ring上所有设备,因此需要将整个Ring的设备状态都更新到CM中。
3.3.13 核心流程:UpdateFreeTask — 清理已结束任务
func (hrt *HotResetTools) UpdateFreeTask(taskListUsedDevice map[string]struct{},
newTaskDevList map[string][]int32) {
for taskName := range hrt.resetTask {
// 条件1: 任务不在当前活跃列表中 → 清理
// 条件2: 任务的设备列表发生变化 → 清理(任务可能被重新调度到其他节点)
if _, ok := taskListUsedDevice[taskName]; !ok ||
hrt.isTaskDevListChange(taskName, newTaskDevList) {
delete(hrt.resetTask, taskName)
}
}
}
func (hrt *HotResetTools) isTaskDevListChange(taskName string,
newTaskDevList map[string][]int32) bool {
// 比较旧设备列表和新设备列表是否一致(通过下划线连接后字符串比较)
return common.Int32Join(hrt.allTaskDevList[taskName], common.UnderLine) !=
common.Int32Join(newTaskDevList[taskName], common.UnderLine)
}
3.4 ascendcommon_v2.go — A5超节点扩展
3.4.1 文件全貌
// Package device a series of device function
package device
// SetSuperPodType setting the type of super pod
func (tool *AscendTools) SetSuperPodType(superPodType int8) {
tool.superPodType = superPodType
}
// GetSuperPodType getting the type of super pod
func (tool *AscendTools) GetSuperPodType() int8 {
return tool.superPodType
}
// SetSuperPodSize setting the type of super pod
func (tool *AscendTools) SetSuperPodSize(superPodSize int32) {
tool.superPodSize = superPodSize
}
// GetSuperPodSize getting the type of super pod
func (tool *AscendTools) GetSuperPodSize() int32 {
return tool.superPodSize
}
// SetNodeInternalIPInK8s setting the ip of the node server in k8s
func (tool *AscendTools) SetNodeInternalIPInK8s(nodeIp string) {
tool.nodeInternalIP = nodeIp
}
// GetNodeInternalIPInK8s getting the ip of the node server in k8s
func (tool *AscendTools) GetNodeInternalIPInK8s() string {
return tool.nodeInternalIP
}
// SetRackID setting the rank id
func (tool *AscendTools) SetRackID(rackID int32) {
tool.rackID = rackID
}
// GetRackID getting the rack id
func (tool *AscendTools) GetRackID() int32 {
return tool.rackID
}
设计意图:
- 这是一个纯getter/setter扩展文件,为AscendTools添加A5超节点相关的属性访问方法
- 独立成文件的原因:这些属性是A5特有的,与ascendcommon.go中的通用方法逻辑不同,分开便于维护和版本管理
- 6个方法对应3组属性:
superPodType/superPodSize(超Pod规格)、nodeInternalIP(节点IP)、rackID(机架ID) - 这些属性在
getConfigAnno中被用于构建Pod配置注解的ServerInfo结构
3.4.2 A5属性使用关系
四、跨模块协作全景
4.1 ListAndWatch完整周期
4.2 故障处理完整链路
4.3 Ring级重置拓扑
4.4 CM数据模型
分析总结
这四个文件构成了Ascend Device Plugin的核心设备管理层,实现了以下关键能力:
- 设备发现:支持物理设备、虚拟设备(vNPU)、共享设备的统一发现与命名
- 健康监测:多维度健康判定(芯片/网络/DPU),支持IPv4/IPv6双栈设备IP获取
- 故障容错:六级故障分级(L0-L6),三级升级链(L2→L3→L5→隔离),支持在线/离线两种容错模式
- 热重置:Ring级设备重置,A3卡关联重置,带内/带外双重重置路径,第三方设备扫描恢复
- CM同步:通过Informer机制实时同步Pod/CM变更,本地文件系统镜像
- 调度集成:Volcano调度ListAndWatch,DeviceInfo CM驱动调度决策,Node Label/Annotation管理
- A5超Pod:SuperPod/Rack/ServerIndex感知,支持大规模集群拓扑
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐


所有评论(0)