Ascend Device Plugin — 入口层 + 工厂层 超深度源码分析

分析范围:main.gopkg/next/devicefactory/entry.gopkg/next/devicefactory/driver_init.gopkg/next/devicefactory/customname/public_name_config.gopkg/topology/topo.gopkg/topology/rack_topology.go


目录


一、全局架构总览

本组文件构成了 Ascend Device Plugin 的启动入口 → 工厂初始化 → 设备命名定制 → 拓扑写入 四层链路。

外部组件

服务层(外部)

拓扑层

工厂层

入口层

setParameters()

devicefactory.InitFunction()

initDevManager()

customname.InitPublicNameConfig()

devmanager.AutoInit()

NewSwitchDevManager()

server.NewHwDevManager()

topology.RasTopoWriteTask()

ToFile()

slownet API

duplicatedetector.CheckDuplicateDevices()

main.go
程序入口、参数解析、参数校验

devicefactory/entry.go
InitFunction() 工厂入口

devicefactory/driver_init.go
initDevManager() 驱动初始化

devicefactory/customname/
public_name_config.go
设备自定义命名

topology/topo.go
拓扑文件读写

topology/rack_topology.go
Rack拓扑写入后台任务

server/HwDevManager
设备管理器

deviceswitch/
SwitchDevManager

devmanager.AutoInit
底层驱动管理

duplicatedetector
重复设备检测

slownet
慢网路径

启动时序图

duplicatedetector topology HwDevManager devmanager devicefactory hwlog main.go Kubernetes duplicatedetector topology HwDevManager devmanager devicefactory hwlog main.go Kubernetes par [并发启动] 启动 Pod flag.Parse() 解析命令行参数 initLogModule(ctx) 初始化日志 checkParam() 参数校验(13项检查) setParameters() 写入全局 Option InitFunction() customname.InitPublicNameConfig() AutoInit("", resetTimeout) devM (DeviceInterface) NewSwitchDevManager() (非A5时) NewHwDevManager(devM) hdm hdm hdm.DoSetMultiDiePolicyForA3() setUseAscendDocker() go hdm.ListenDevice(ctx) go hdm.ListenDpu(ctx) go topology.RasTopoWriteTask(ctx, hdm) CheckDuplicateDevices(ctx, config) hdm.SignCatch(cancel) 运行中

二、main.go — 程序入口与参数校验

2.1 模块定位

维度 说明
业务职责 Ascend Device Plugin 的唯一入口点(package main)。负责命令行参数解析、日志初始化、全局参数校验、全局配置注入、驱动工厂调用、并发生命周期管理(设备监听 / DPU监听 / 拓扑写入 / 重复检测 / 信号捕获)
功能定位 Bootstrap + Orchestrator:不包含具体设备管理逻辑,仅做"编排"——组装各组件并启动后台 goroutine
在系统中的位置 Kubernetes Device Plugin 进程入口。运行在节点上,向 kubelet 注册设备资源

Kubernetes Node

Device Plugin Pod

后台goroutine

ListAndWatch

ListenDevice
设备状态监听

main.go
(本文件)

ListenDpu
DPU监听

RasTopoWriteTask
拓扑写入

CheckDuplicateDevices
重复检测

kubelet
gRPC接口

2.2 模块整体结构

2.2.1 常量定义
const (
    defaultLogPath        = "/var/log/mindx-dl/devicePlugin/devicePlugin.log"  // 默认日志路径(中心场景)
    defaultListWatchPeriod = 5                                                  // 默认设备状态监听周期(秒)
    maxListWatchPeriod     = 1800                                               // 最大监听周期
    minListWatchPeriod     = 3                                                  // 最小监听周期
    maxLogLineLength       = 1024                                               // 单行日志最大长度
    defaultLinkdownTimeout = 30                                                 // 默认链路断开超时(秒)
    maxLinkdownTimeout     = 30                                                 // 最大链路断开超时
    minLinkdownTimeout     = 1                                                  // 最小链路断开超时
)
2.2.2 命令行 Flag 定义

Flag 分类

版本信息

version
输出版本信息

高级功能

dealWatchHandler
Pod缓存watch错误处理

checkCachedPods
周期性检查Pod缓存

enableSlowNode
慢节点通知

thirdPartyScanDelay
三方复位扫描延迟(秒)

deviceResetTimeout
设备复位超时(10~600s)

softShareDevConfigDir
软共享设备配置目录

日志与诊断

logLevel
日志级别(-1~3)

logFile
日志文件路径

edgeLogFile
边缘场景日志路径

logMaxAge
日志保留天数(7~700)

logMaxBackups
日志备份数(0~30]

设备管理

listWatchPeriod
设备监听周期(3~1800s)

autoStowing
自动收纳故障设备

presetVirtualDevice
预置虚拟设备(算力切分)

shareDevCount
共享设备数(1~100)

hotReset
热复位模式(-1~2)

linkdownTimeout
链路断开超时(1~30s)

运行模式控制

fdFlag
是否使用FD系统管理设备

useAscendDocker
是否使用NPU Docker

volcanoType
是否使用Volcano调度

use310PMixedInsert
310P混合插卡模式

useSingleDieMode
A3单Die模式

2.2.3 全局变量与构建期注入
var (
    // 通过 -ldflags 在构建时注入
    BuildName    string  // 应用名称
    BuildVersion string  // 应用版本
    BuildScene   string  // 启动场景: "center" 或 "edge"
)

设计目的:构建时通过 -ldflags "-X main.BuildVersion=xxx" 注入版本信息,运行时通过 --version 输出。BuildScene 决定日志路径和边缘/中心场景行为。

2.2.4 核心方法清单
方法 签名 作用
initLogModule func(ctx) error 根据 fdFlag 选择日志路径,初始化 hwlog 运行时日志
checkParam func() bool 编排13项参数校验,任一失败即终止
checkListWatchPeriod func() bool 校验监听周期范围 [3, 1800]
checkPresetAndVolcanoRelation func() bool preset=false 时 volcano 必须为 true
checkUse310PMixedInsertWithVolcano func() bool 310P混合插卡与Volcano互斥
checkUse310PMixedInsertWithShareDevCount func() bool 310P混合插卡时 shareDevCount 必须为1
checkPresetWithShareDevCount func() bool preset=false 时 shareDevCount 必须为1
checkSoftShareDevConfigDir func() bool 软共享配置目录校验(绝对路径、shareDevCount=100、目录存在)
checkHotResetMode func() bool 热复位模式枚举值校验
checkBuildScene func() bool 构建场景必须为 edge 或 center
checkLinkdownTimeout func() bool 链路断开超时范围校验 [1, 30]
checkThirdPartyScanDelay func() bool 三方扫描延迟非负校验
checkDeviceResetTimeout func() bool 设备复位超时范围校验 [10, 600]
checkShareDevCount func() bool 共享设备数范围校验 [1, 100]
main func() 程序入口:解析→日志→校验→配置→工厂→启动
setParameters func() 将所有 Flag 值写入 common.ParamOption 全局结构体
setUseAscendDocker func() 根据环境变量和运行模式调整 useAscendDocker

2.3 核心业务逻辑深度解析

2.3.1 main() 函数完整执行流程

Yes

No

No

Yes

No

Yes

No

Yes

main() 开始

flag.Parse()
解析命令行参数

version flag?

输出 BuildName:BuildVersion
return 退出

ctx, cancel := context.WithCancel()
创建可取消上下文

initLogModule(ctx)
初始化日志系统

日志初始化成功?

return 退出

checkParam()
执行13项参数校验

全部通过?

return 退出

hwlog: 启动日志
version + scene

setParameters()
写入 common.ParamOption

devicefactory.InitFunction()
初始化设备工厂

初始化成功?

return 退出

获得 hdm (HwDevManager)

hdm.DoSetMultiDiePolicyForA3()
设置A3多Die策略

setUseAscendDocker()
调整Docker运行时配置

par 并发启动4个后台任务

go hdm.ListenDevice(ctx)

go hdm.ListenDpu(ctx)

go topology.RasTopoWriteTask(ctx, hdm)

duplicatedetector.CheckDuplicateDevices(ctx, ...)

hdm.SignCatch(cancel)
信号捕获与优雅退出

进程结束

2.3.2 initLogModule() 逐行解析
func initLogModule(ctx context.Context) error {
    var loggerPath string
    loggerPath = *logFile                    // 默认使用中心场景日志路径
    if *fdFlag {
        loggerPath = *edgeLogFile            // FD系统模式下使用边缘场景日志路径
    }
    // 检查日志文件用户与进程用户是否一致(安全检查)
    if !common.CheckFileUserSameWithProcess(loggerPath) {
        return fmt.Errorf("check log file failed")
    }
    // 构建hwlog配置结构体
    hwLogConfig := hwlog.LogConfig{
        LogFileName:   loggerPath,           // 日志文件名
        LogLevel:      *logLevel,            // 日志级别: -1(debug)~3(critical)
        MaxBackups:    *logMaxBackups,       // 最大备份文件数
        MaxAge:        *logMaxAge,           // 日志保留天数
        MaxLineLength: maxLogLineLength,     // 单行最大1024字符
    }
    // 初始化运行时日志器
    if err := hwlog.InitRunLogger(&hwLogConfig, ctx); err != nil {
        fmt.Printf("log init failed, error is %v\n", err)  // 日志未就绪,用fmt输出
        return err
    }
    return nil
}

设计意图

  • 双场景日志路径切换:中心场景 /var/log/mindx-dl/devicePlugin/devicePlugin.log,边缘场景 /var/alog/AtlasEdge_log/devicePlugin.log
  • 文件用户一致性检查防止权限泄漏
  • ctx 传入日志模块,支持随进程退出优雅关闭日志
2.3.3 checkParam() 参数校验链

checkParam()

checkListWatchPeriod
范围[3,1800]

checkPresetAndVolcanoRelation
preset=false→volcano必为true

checkUse310PMixedInsertWithVolcano
混合插卡与volcano互斥

checkUse310PMixedInsertWithShareDevCount
混合插卡时shareDevCount=1

checkPresetWithShareDevCount
preset=false→shareDevCount=1

checkHotResetMode
枚举值: -1,0,1,2

checkBuildScene
必须为edge或center

checkLinkdownTimeout
范围[1,30]

checkThirdPartyScanDelay
非负

checkDeviceResetTimeout
范围[10,600]

checkShareDevCount
范围[1,100]

checkSoftShareDevConfigDir
绝对路径+shareDevCount=100

返回 true

逐个校验函数详解

func checkListWatchPeriod() bool {
    // listWatchPeriod 控制 ListAndWatch gRPC 流的轮询间隔
    // 过小浪费CPU,过大延迟感知设备状态变化
    if *listWatchPeriod < minListWatchPeriod || *listWatchPeriod > maxListWatchPeriod {
        hwlog.RunLog.Errorf("list and watch period %d out of range", *listWatchPeriod)
        return false
    }
    return true
}
func checkPresetAndVolcanoRelation() bool {
    // presetVirtualDevice=false 表示关闭算力切分预置
    // 此时必须使用 volcano 调度器来处理虚拟设备调度
    if !(*presetVirtualDevice) && !(*volcanoType) {
        hwlog.RunLog.Error("presetVirtualDevice is false, volcanoType should be true")
        return false
    }
    return true
}
func checkUse310PMixedInsertWithVolcano() bool {
    // 310P混合插卡模式 与 volcano调度 互斥
    // 混合插卡需要特殊的设备分配逻辑,volcano的调度策略不兼容
    if *use310PMixedInsert && *volcanoType {
        hwlog.RunLog.Errorf("%s is true, volcanoType should be false", api.Use310PMixedInsert)
        return false
    }
    return true
}
func checkSoftShareDevConfigDir() bool {
    if *softShareDevConfigDir == "" {
        return true  // 未配置软共享目录,跳过检查
    }
    // 软共享必须配合最大共享数100
    if *shareDevCount != common.MaxShareDevCount {
        hwlog.RunLog.Errorf("shareDevCount should be %d when softShareDevConfigDir is set",
            common.MaxShareDevCount)
        return false
    }
    // 必须是绝对路径(防止相对路径导致配置文件定位错误)
    if !filepath.IsAbs(*softShareDevConfigDir) {
        hwlog.RunLog.Errorf("softShareDevConfigDir: %s is not absolute path", *softShareDevConfigDir)
        return false
    }
    // 父目录必须存在且可读
    _, err := utils.RealDirChecker(filepath.Dir(*softShareDevConfigDir), true, false)
    if err != nil {
        hwlog.RunLog.Errorf("check softShareDevConfigDir: %s failed, error is %v", *softShareDevConfigDir, err)
        return false
    }
    return true
}
func checkHotResetMode() bool {
    // 热复位模式枚举:
    // -1: 关闭热复位
    //  0: 推理芯片热复位
    //  1: 训练在线热复位
    //  2: 训练离线热复位
    switch *hotReset {
    case common.HotResetClose, common.HotResetInfer,
         common.HotResetTrainOnLine, common.HotResetTrainOffLine:
        return true
    default:
        hwlog.RunLog.Error("hot reset mode param invalid")
        return false
    }
}
2.3.4 setParameters() 全局配置注入
func setParameters() {
    // 将所有命令行 Flag 值一次性写入 common.ParamOption 全局结构体
    // 后续所有模块通过 common.ParamOption 读取配置,无需逐个传参
    common.ParamOption = common.Option{
        GetFdFlag:             *fdFlag,                    // FD系统管理模式
        UseAscendDocker:       *useAscendDocker,            // NPU Docker运行时
        UseVolcanoType:        *volcanoType,                // Volcano调度
        AutoStowingDevs:       *autoStowing,                // 自动收纳
        ListAndWatchPeriod:    *listWatchPeriod,            // 监听周期
        PresetVDevice:         *presetVirtualDevice,        // 算力切分
        Use310PMixedInsert:    *use310PMixedInsert,          // 310P混合插卡
        HotReset:              *hotReset,                   // 热复位模式
        BuildScene:            BuildScene,                   // 构建场景
        ShareCount:            *shareDevCount,               // 共享数
        LinkdownTimeout:       *linkdownTimeout,             // 链路断开超时
        DealWatchHandler:      *dealWatchHandler,            // watch错误处理
        CheckCachedPods:       *checkCachedPods,             // Pod缓存检查
        EnableSlowNode:        *enableSlowNode,              // 慢节点通知
        ThirdPartyScanDelay:   *thirdPartyScanDelay,         // 三方扫描延迟
        DeviceResetTimeout:    *deviceResetTimeout,          // 设备复位超时
        SoftShareDevConfigDir: *softShareDevConfigDir,       // 软共享配置目录
        UseSingleDieMode:      *useSingleDieMode,            // A3单Die模式
    }
}

设计模式:全局 Option 模式(单例配置)。简化参数传递,但所有模块共享同一配置结构体,非线程安全(仅在启动时写入一次)。

2.3.5 setUseAscendDocker() Docker运行时调整

No

Yes

Yes

No

Yes

No

setUseAscendDocker()

*useAscendDocker = true
默认启用

读取环境变量
AscendDockerRuntimeEnv

env == 'True'?

*useAscendDocker = false
非Ascend Docker环境

保持 true

Use310PMixedInsert?

*useAscendDocker = false
混合插卡不用NPU Docker

仅Atlas200ISoc单一产品?

*useAscendDocker = false
SoC模式不用NPU Docker

common.ParamOption.UseAscendDocker = *useAscendDocker
回写全局配置

hwlog: 输出最终Docker设置

完成

func setUseAscendDocker() {
    *useAscendDocker = true  // 默认值:启用Ascend Docker运行时

    // 检查环境变量 ASCEND_DOCKER_RUNTIME 是否为 "True"
    ascendDocker := os.Getenv(api.AscendDockerRuntimeEnv)
    if ascendDocker != "True" {
        *useAscendDocker = false
        hwlog.RunLog.Debugf("get docker runtime from env is: %#v", ascendDocker)
    }

    // 310P混合插卡模式下不使用 NPU Docker(使用原生设备映射)
    if common.ParamOption.Use310PMixedInsert {
        *useAscendDocker = false
        hwlog.RunLog.Debugf("mixed insert mode do not use npu docker")
    }

    // Atlas 200I SoC 是单芯片SoC产品,不需要Docker运行时
    if len(common.ParamOption.ProductTypes) == 1 &&
       common.ParamOption.ProductTypes[0] == common.Atlas200ISoc {
        *useAscendDocker = false
    }

    // 回写全局配置(注意:setParameters已写入一次,这里可能覆盖)
    common.ParamOption.UseAscendDocker = *useAscendDocker
    hwlog.RunLog.Infof("device-plugin set npu docker as: %v", *useAscendDocker)
}

关键设计点setUseAscendDocker()InitFunction() 之后调用,因为需要读取 common.ParamOption.ProductTypes(由 NewHwDevManager→setAscendManager→GetAllProductType 填充)。这说明配置注入分两个阶段:Flag→Option(setParameters)→ 实际初始化 → Option修正(setUseAscendDocker)

2.3.6 main() 函数后半段逐行解析
func main() {
    flag.Parse()                        // 解析命令行参数到各 flag 变量

    if *version {                        // --version flag: 输出版本信息后退出
        fmt.Printf("%s version: %s\n", BuildName, BuildVersion)
        return
    }

    // 创建带取消的上下文,cancel 用于优雅退出
    ctx, cancel := context.WithCancel(context.Background())

    if err := initLogModule(ctx); err != nil {   // 初始化日志系统
        return                                    // 日志初始化失败,无法继续
    }

    if !checkParam() {                           // 13项参数校验
        return                                    // 任一校验失败即退出
    }

    hwlog.RunLog.Infof("device plugin starting and the version is %s", BuildVersion)
    hwlog.RunLog.Infof("device plugin starting scene is %s", BuildScene)

    setParameters()                               // 将 Flag 值写入 common.ParamOption

    hdm, err := devicefactory.InitFunction()      // ★ 工厂初始化(核心调用)
    if err != nil {
        return                                    // 工厂初始化失败,无法继续
    }

    hdm.DoSetMultiDiePolicyForA3()                // 设置 A3 芯片多 Die 策略
    setUseAscendDocker()                          // 根据实际环境修正 Docker 运行时配置

    // ★ 启动4个并发任务
    go hdm.ListenDevice(ctx)                      // goroutine 1: 设备状态监听 + ListAndWatch
    go hdm.ListenDpu(ctx)                         // goroutine 2: DPU(数据处理单元)监听
    go topology.RasTopoWriteTask(ctx, hdm)        // goroutine 3: RAS拓扑文件写入(仅A5)

    duplicatedetector.CheckDuplicateDevices(ctx, &types.DetectorConfig{   // 同步调用:重复设备检测
        CriEndpoint: "",                          // 使用默认 CRI endpoint
        RuntimeType: hdm.ContainerRuntime,        // 从 HwDevManager 获取容器运行时
    })

    hwlog.RunLog.Infof("device plugin started.")

    hdm.SignCatch(cancel)                         // ★ 信号捕获(阻塞):等待 SIGINT/SIGTERM
    // SignCatch 收到信号后调用 cancel(),取消 ctx,
    // 各 goroutine 通过 ctx.Done() 感知并退出
}

生命周期管理设计

  • ctx + cancel 模式:主 goroutine 在 SignCatch 阻塞等待信号
  • 收到信号后调用 cancel(),ctx 被取消
  • 各后台 goroutine 通过 select { case <-ctx.Done(): } 感知并优雅退出
  • duplicatedetector.CheckDuplicateDevices 是同步调用,在 SignCatch 之前完成

三、devicefactory/entry.go — 设备工厂入口

3.1 模块定位

维度 说明
业务职责 设备工厂的入口函数,协调自定义命名初始化、底层驱动管理器初始化、交换设备管理器初始化,最终组装出 HwDevManager
功能定位 Factory Facade:对外暴露唯一的 InitFunction(),内部编排三个子初始化
在系统中的位置 main.go 直接调用,是 main 与 server 层之间的工厂层

deviceswitch(外部依赖)

devmanager(外部依赖)

server/

devicefactory/customname/

devicefactory/driver_init.go

devicefactory/entry.go

main.go

调用

1. 调用

2. 调用

2a

2b(非A5时)

3. 调用

返回 hdm

返回 hdm

main()

InitFunction()

initDevManager()

InitPublicNameConfig()

NewHwDevManager()

AutoInit()

NewSwitchDevManager()

3.2 模块整体结构

3.2.1 类/结构体与依赖关系

创建

通过 initDevManager 获取

通过 initDevManager 获取

通过 customname 初始化

持有

«file: entry.go»

EntryGo

HwDevManager

+SwitchDevManager *SwitchDevManager

+groupDevice map[string][]*NpuDevice

+ServerMap map[string]InterfaceServer

+allInfo NpuAllInfo

+manager DeviceManager

+RunMode string

+WorkMode string

+baseNPUInfo map[string]*NpuBaseInfo

+dpuManager *DpuFilter

+ManagerLock sync.Mutex

+ContainerRuntime string

«外部: deviceswitch»

SwitchDevManager

«接口: devmanager»

DeviceInterface

+GetDevType() : string

+GetNpuWorkMode() : string

DevName

+ResourceType string

+DevicePublicType string

+OldDevicePublicType string

+DevicePublicNamePre string

+OldDevicePublicNamePre string

+PodConfigurationName string

+OldPodConfigurationName string

3.2.2 核心方法清单
方法 签名 作用
InitFunction func() (*server.HwDevManager, error) 工厂入口:初始化命名→初始化驱动→创建管理器→配置交换设备

3.3 核心业务逻辑深度解析

3.3.1 InitFunction() 逐行解析

Error

Success

Yes

No

Yes

No

InitFunction()

1. customname.InitPublicNameConfig()
加载设备自定义命名配置

2. initDevManager()
初始化底层驱动

驱动初始化成功?

hwlog: init dev manager failed
return nil, err

获得 devM, switchDevM

3. server.NewHwDevManager(devM)
创建设备管理器

hdm == nil?

hwlog: init device manager failed
return nil, error

hwlog: init device manager success

common.ParamOption.EnableSwitchFault = false
默认关闭交换设备故障

switchDevM != nil?

hdm.SwitchDevManager = switchDevM
挂载交换设备管理器

common.ParamOption.EnableSwitchFault = true
启用交换设备故障检测

return hdm, nil

返回给 main.go

// InitFunction init function — 工厂入口函数
func InitFunction() (*server.HwDevManager, error) {
    // 步骤1: 初始化设备自定义命名配置
    // 从 /usr/local/deviceNameCustomization.json 加载自定义设备名称映射
    // 失败时不报错,仅记录 info 日志,使用默认命名
    customname.InitPublicNameConfig()

    // 步骤2: 初始化底层驱动管理器和交换设备管理器
    // devM: 通过 devmanager.AutoInit 自动探测设备类型并初始化
    // switchDevM: 交换设备管理器(仅非A5芯片时初始化)
    devM, switchDevM, err := initDevManager()
    if err != nil {
        hwlog.RunLog.Errorf("init dev manager failed, err: %v", err)
        return nil, err
    }

    // 步骤3: 创建上层设备管理器 HwDevManager
    // NewHwDevManager 内部会: 设置设备类型→设置所有设备和类型→检查产品类型→
    // 设置SuperPod信息→更新节点标签→初始化插件服务器→获取容器运行时
    hdm := server.NewHwDevManager(devM)
    if hdm == nil {
        hwlog.RunLog.Error("init device manager failed")
        return nil, fmt.Errorf("init device manager failed")
    }
    hwlog.RunLog.Info("init device manager success")

    // 步骤4: 配置交换设备管理器
    // 默认关闭交换设备故障检测
    common.ParamOption.EnableSwitchFault = false
    if switchDevM != nil {
        // 有交换设备管理器时挂载到 hdm 并启用故障检测
        hdm.SwitchDevManager = switchDevM
        common.ParamOption.EnableSwitchFault = true
    }

    return hdm, nil
}

设计意图

  1. 命名初始化优先:自定义命名必须在设备管理器创建之前完成,因为 NewHwDevManager 内部会使用命名映射来设置资源名称
  2. 交换设备可选:A5芯片不支持交换设备,switchDevM 为 nil 时不报错,仅不启用相关功能
  3. EnableSwitchFault 全局开关:通过 common.ParamOption 全局传递,其他模块据此决定是否处理交换设备故障

四、devicefactory/driver_init.go — 驱动初始化

4.1 模块定位

维度 说明
业务职责 初始化底层设备驱动管理器(devmanager.DeviceInterface)和交换设备管理器(SwitchDevManager),处理 A5 芯片的特殊逻辑
功能定位 Driver Bootstrap:自动探测 NPU 设备类型,根据设备类型决定是否初始化交换设备
在系统中的位置 entry.goInitFunction() 调用,连接底层 devmanager 和上层 server

deviceswitch

devmanager

driver_init.go

entry.go

1

返回 devM

2

Yes

No

Yes

No

InitFunction()

initDevManager()

AutoInit('', resetTimeout)
自动探测设备类型

NewSwitchDevManager()

InitSwitchDev()

devM.GetDevType()
== Ascend910A5?

不初始化交换设备
return devM, nil, nil

InitSwitchDev
成功?

return devM, switchDevMgr, nil

Warn: 仅警告
return devM, nil, nil

return devM, nil, nil

4.2 模块整体结构

4.2.1 核心方法清单
方法 签名 作用
initDevManager func() (devmanager.DeviceInterface, *deviceswitch.SwitchDevManager, error) 自动初始化底层驱动,按设备类型决定是否初始化交换设备管理器
4.2.2 依赖关系

"通过 AutoInit 获取"

"创建并初始化"

«file: driver_init.go»

DriverInitGo

«interface: devmanager»

DeviceInterface

+GetDevType() : string

+GetNpuWorkMode() : string

«struct: deviceswitch»

SwitchDevManager

+InitSwitchDev() : error

AutoInit 会自动探测:\n- Ascend310\n- Ascend310P\n- Ascend310B\n- Ascend910A\n- Ascend910B\n- Ascend910A3\n- Ascend910A5

4.3 核心业务逻辑深度解析

4.3.1 initDevManager() 逐行解析
func initDevManager() (devmanager.DeviceInterface, *deviceswitch.SwitchDevManager, error) {
    // 步骤1: 自动初始化底层驱动管理器
    // 传入空字符串 "" 表示自动探测设备路径
    // common.ParamOption.DeviceResetTimeout 是等待驱动上报所有芯片的最大超时时间
    devM, err := devmanager.AutoInit("", common.ParamOption.DeviceResetTimeout)
    if err != nil {
        hwlog.RunLog.Errorf("init devmanager failed, err: %v", err)
        return devM, nil, err  // 注意:返回 devM(可能为nil)便于上层调试
    }

    // 步骤2: A5芯片特殊处理 — 不支持交换设备
    if devM.GetDevType() == api.Ascend910A5 {
        hwlog.RunLog.Infof("current devType is %s, switch device manager not supported.",
            api.HuaweiNPU)
        return devM, nil, nil  // A5直接返回,switchDevM为nil
    }

    // 步骤3: 非A5芯片,创建并初始化交换设备管理器
    switchDevMgr := deviceswitch.NewSwitchDevManager()
    if err := switchDevMgr.InitSwitchDev(); err != nil {
        // 交换设备初始化失败不致命,仅警告
        // 系统仍可正常运行,只是不处理交换设备故障
        hwlog.RunLog.Warnf("failed to init switch device manager, "+
            "will not deal with switch fault, err: %s", err.Error())
        return devM, nil, nil  // 交换设备为nil,但驱动管理器有效
    }

    return devM, switchDevMgr, nil
}

执行流程图

Yes

No

Yes

No

Yes

No

initDevManager()

devmanager.AutoInit('', resetTimeout)
自动探测NPU设备类型并初始化

err != nil?

return devM, nil, err
驱动初始化失败

devM.GetDevType()
获取设备类型

== Ascend910A5?

return devM, nil, nil
A5不支持交换设备
日志: HuaweiNPU

deviceswitch.NewSwitchDevManager()
创建交换设备管理器

switchDevMgr.InitSwitchDev()
初始化交换设备

err != nil?

Warn: 交换设备初始化失败
不影响主流程
return devM, nil, nil

return devM, switchDevMgr, nil
全部成功

返回

关键设计决策

  1. A5芯片不初始化交换设备:A5(Ascend910A5)是新一代训练芯片,架构上不需要交换设备管理
  2. 交换设备初始化失败不影响主流程InitSwitchDev() 失败仅 Warn 不 Error,系统降级运行(不处理交换设备故障)
  3. 降级模式安全switchDevM 为 nil 时,entry.goEnableSwitchFault 保持 false,其他模块不会访问交换设备

Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐