云计算百科
云计算领域专业知识百科平台

【NPU】Ascend Docker Runtime v26.0.1 之三 runtime/dcmi/ — 超深度逐行分析

runtime/dcmi/ — 超深度逐行分析

三个文件:dcmi.go (360行) + dcmi_api.go (101行) + dcManager.go (294行) = 755行
核心职责:NPU设备管理接口封装,通过CGO调用libdcmi.so


一、模块定位

1.1 业务职责

runtime/dcmi/ 是设备管理抽象层,负责:

  • 驱动版本自适应 — 自动检测V1/V2驱动,选择匹配的Worker
  • 设备查询 — 获取卡列表、设备列表、芯片信息、产品类型
  • 虚拟设备管理 — 创建/销毁vNPU(虚拟NPU切分)
  • 物理ID↔逻辑ID转换 — 将用户指定的物理设备ID转换为驱动内部逻辑ID
  • CGO桥接 — 封装所有对libdcmi.so的C语言调用
  • 1.2 在系统中的位置

    #mermaid-svg-MA5V9njIHI1zHJ0f{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MA5V9njIHI1zHJ0f .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MA5V9njIHI1zHJ0f .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MA5V9njIHI1zHJ0f .error-icon{fill:#552222;}#mermaid-svg-MA5V9njIHI1zHJ0f .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MA5V9njIHI1zHJ0f .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MA5V9njIHI1zHJ0f .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MA5V9njIHI1zHJ0f .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MA5V9njIHI1zHJ0f .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MA5V9njIHI1zHJ0f .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MA5V9njIHI1zHJ0f .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MA5V9njIHI1zHJ0f .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MA5V9njIHI1zHJ0f .marker.cross{stroke:#333333;}#mermaid-svg-MA5V9njIHI1zHJ0f svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MA5V9njIHI1zHJ0f p{margin:0;}#mermaid-svg-MA5V9njIHI1zHJ0f .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-MA5V9njIHI1zHJ0f .cluster-label text{fill:#333;}#mermaid-svg-MA5V9njIHI1zHJ0f .cluster-label span{color:#333;}#mermaid-svg-MA5V9njIHI1zHJ0f .cluster-label span p{background-color:transparent;}#mermaid-svg-MA5V9njIHI1zHJ0f .label text,#mermaid-svg-MA5V9njIHI1zHJ0f span{fill:#333;color:#333;}#mermaid-svg-MA5V9njIHI1zHJ0f .node rect,#mermaid-svg-MA5V9njIHI1zHJ0f .node circle,#mermaid-svg-MA5V9njIHI1zHJ0f .node ellipse,#mermaid-svg-MA5V9njIHI1zHJ0f .node polygon,#mermaid-svg-MA5V9njIHI1zHJ0f .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-MA5V9njIHI1zHJ0f .rough-node .label text,#mermaid-svg-MA5V9njIHI1zHJ0f .node .label text,#mermaid-svg-MA5V9njIHI1zHJ0f .image-shape .label,#mermaid-svg-MA5V9njIHI1zHJ0f .icon-shape .label{text-anchor:middle;}#mermaid-svg-MA5V9njIHI1zHJ0f .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-MA5V9njIHI1zHJ0f .rough-node .label,#mermaid-svg-MA5V9njIHI1zHJ0f .node .label,#mermaid-svg-MA5V9njIHI1zHJ0f .image-shape .label,#mermaid-svg-MA5V9njIHI1zHJ0f .icon-shape .label{text-align:center;}#mermaid-svg-MA5V9njIHI1zHJ0f .node.clickable{cursor:pointer;}#mermaid-svg-MA5V9njIHI1zHJ0f .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-MA5V9njIHI1zHJ0f .arrowheadPath{fill:#333333;}#mermaid-svg-MA5V9njIHI1zHJ0f .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-MA5V9njIHI1zHJ0f .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-MA5V9njIHI1zHJ0f .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MA5V9njIHI1zHJ0f .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-MA5V9njIHI1zHJ0f .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MA5V9njIHI1zHJ0f .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-MA5V9njIHI1zHJ0f .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-MA5V9njIHI1zHJ0f .cluster text{fill:#333;}#mermaid-svg-MA5V9njIHI1zHJ0f .cluster span{color:#333;}#mermaid-svg-MA5V9njIHI1zHJ0f div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-MA5V9njIHI1zHJ0f .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-MA5V9njIHI1zHJ0f rect.text{fill:none;stroke-width:0;}#mermaid-svg-MA5V9njIHI1zHJ0f .icon-shape,#mermaid-svg-MA5V9njIHI1zHJ0f .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MA5V9njIHI1zHJ0f .icon-shape p,#mermaid-svg-MA5V9njIHI1zHJ0f .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-MA5V9njIHI1zHJ0f .icon-shape .label rect,#mermaid-svg-MA5V9njIHI1zHJ0f .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MA5V9njIHI1zHJ0f .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-MA5V9njIHI1zHJ0f .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-MA5V9njIHI1zHJ0f :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    外部

    dcmi模块

    调用方

    GetMatchingNpuWorker

    CreateVDevice

    GetChipName/GetProductType

    CGO C.DcmiXXX

    runtime/process/process.go

    dcmi_api.go顶层APICreateVDevice

    dcmi.goWorker接口+V1/V2实现设备查询/虚拟设备

    dcManager.goCGO封装直接调用libdcmi.so

    libdcmi.soNPU驱动C库

    NPU硬件


    二、dcmi_api.go 逐行解析(101行)

    2.1 数据结构

    type VDeviceInfo struct {
    CardID int32
    DeviceID int32
    VdeviceID int32
    }

    字段含义示例
    CardID NPU卡ID(物理插槽) 0
    DeviceID 卡内设备ID 1
    VdeviceID 虚拟设备ID(切分后生成) 42

    #mermaid-svg-Cxk2dFq8FtryuRbp{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Cxk2dFq8FtryuRbp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Cxk2dFq8FtryuRbp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Cxk2dFq8FtryuRbp .error-icon{fill:#552222;}#mermaid-svg-Cxk2dFq8FtryuRbp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Cxk2dFq8FtryuRbp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Cxk2dFq8FtryuRbp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Cxk2dFq8FtryuRbp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Cxk2dFq8FtryuRbp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Cxk2dFq8FtryuRbp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Cxk2dFq8FtryuRbp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Cxk2dFq8FtryuRbp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Cxk2dFq8FtryuRbp .marker.cross{stroke:#333333;}#mermaid-svg-Cxk2dFq8FtryuRbp svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Cxk2dFq8FtryuRbp p{margin:0;}#mermaid-svg-Cxk2dFq8FtryuRbp g.classGroup text{fill:#9370DB;stroke:none;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-Cxk2dFq8FtryuRbp g.classGroup text .title{font-weight:bolder;}#mermaid-svg-Cxk2dFq8FtryuRbp .cluster-label text{fill:#333;}#mermaid-svg-Cxk2dFq8FtryuRbp .cluster-label span{color:#333;}#mermaid-svg-Cxk2dFq8FtryuRbp .cluster-label span p{background-color:transparent;}#mermaid-svg-Cxk2dFq8FtryuRbp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Cxk2dFq8FtryuRbp .cluster text{fill:#333;}#mermaid-svg-Cxk2dFq8FtryuRbp .cluster span{color:#333;}#mermaid-svg-Cxk2dFq8FtryuRbp .nodeLabel,#mermaid-svg-Cxk2dFq8FtryuRbp .edgeLabel{color:#131300;}#mermaid-svg-Cxk2dFq8FtryuRbp .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-Cxk2dFq8FtryuRbp .label text{fill:#131300;}#mermaid-svg-Cxk2dFq8FtryuRbp .labelBkg{background:#ECECFF;}#mermaid-svg-Cxk2dFq8FtryuRbp .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-Cxk2dFq8FtryuRbp .classTitle{font-weight:bolder;}#mermaid-svg-Cxk2dFq8FtryuRbp .node rect,#mermaid-svg-Cxk2dFq8FtryuRbp .node circle,#mermaid-svg-Cxk2dFq8FtryuRbp .node ellipse,#mermaid-svg-Cxk2dFq8FtryuRbp .node polygon,#mermaid-svg-Cxk2dFq8FtryuRbp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Cxk2dFq8FtryuRbp .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-Cxk2dFq8FtryuRbp g.clickable{cursor:pointer;}#mermaid-svg-Cxk2dFq8FtryuRbp g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-Cxk2dFq8FtryuRbp g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-Cxk2dFq8FtryuRbp .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-Cxk2dFq8FtryuRbp .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-Cxk2dFq8FtryuRbp .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-Cxk2dFq8FtryuRbp .dashed-line{stroke-dasharray:3;}#mermaid-svg-Cxk2dFq8FtryuRbp .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-Cxk2dFq8FtryuRbp #compositionStart,#mermaid-svg-Cxk2dFq8FtryuRbp .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Cxk2dFq8FtryuRbp #compositionEnd,#mermaid-svg-Cxk2dFq8FtryuRbp .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Cxk2dFq8FtryuRbp #dependencyStart,#mermaid-svg-Cxk2dFq8FtryuRbp .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Cxk2dFq8FtryuRbp #dependencyStart,#mermaid-svg-Cxk2dFq8FtryuRbp .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Cxk2dFq8FtryuRbp #extensionStart,#mermaid-svg-Cxk2dFq8FtryuRbp .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Cxk2dFq8FtryuRbp #extensionEnd,#mermaid-svg-Cxk2dFq8FtryuRbp .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Cxk2dFq8FtryuRbp #aggregationStart,#mermaid-svg-Cxk2dFq8FtryuRbp .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Cxk2dFq8FtryuRbp #aggregationEnd,#mermaid-svg-Cxk2dFq8FtryuRbp .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Cxk2dFq8FtryuRbp #lollipopStart,#mermaid-svg-Cxk2dFq8FtryuRbp .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Cxk2dFq8FtryuRbp #lollipopEnd,#mermaid-svg-Cxk2dFq8FtryuRbp .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Cxk2dFq8FtryuRbp .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-Cxk2dFq8FtryuRbp .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Cxk2dFq8FtryuRbp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Cxk2dFq8FtryuRbp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Cxk2dFq8FtryuRbp :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    VDeviceInfo

    +int32 CardID

    +int32 DeviceID

    +int32 VdeviceID

    «interface»

    WorkerInterface

    +Initialize() : error

    +ShutDown()

    +CreateVDevice(uniqueID, coreNum)(VDeviceInfo, error)

    +DestroyVDevice(uniqueID, vDevID) : error

    +GetProductType()(string, error)

    +GetChipName()(string, error)

    2.2 WorkerInterface 接口

    type WorkerInterface interface {
    Initialize() error
    ShutDown()
    CreateVDevice(uniqueID int32, coreNum string) (VDeviceInfo, error)
    DestroyVDevice(uniqueID int32, vDevID int32) error
    GetProductType() (string, error)
    GetChipName() (string, error)
    }

    6个方法的职责:

    方法输入输出用途
    Initialize error 初始化dcmi库连接
    ShutDown 关闭dcmi库连接
    CreateVDevice uniqueID(物理设备ID), coreNum(切分模板) VDeviceInfo, error 创建虚拟NPU
    DestroyVDevice uniqueID, vDevID(虚拟设备ID) error 销毁虚拟NPU
    GetProductType string, error 获取产品型号
    GetChipName string, error 获取芯片名称

    设计意图:策略模式接口,V1和V2驱动各自实现此接口,调用方无需关心驱动版本。

    2.3 CreateVDevice 顶层API

    func CreateVDevice(w WorkerInterface, spec *specs.Spec, devices []int) (VDeviceInfo, error) {
    invalidVDevice := VDeviceInfo{CardID: 1, DeviceID: 1, VdeviceID: 1}
    if spec == nil {
    return invalidVDevice, fmt.Errorf("spec is nil")
    }
    splitDevice, err := extractVpuParam(spec)
    if err != nil {
    return invalidVDevice, err
    }
    if splitDevice == "" {
    return invalidVDevice, nil
    }
    if len(devices) != 1 || devices[0] < 0 || devices[0] >= hiAIMaxCardNum*hiAIMaxDeviceNum {
    hwlog.RunLog.Errorf("invalid devices: %v", devices)
    return invalidVDevice, fmt.Errorf("invalid devices: %v", devices)
    }

    if err := w.Initialize(); err != nil {
    return invalidVDevice, fmt.Errorf("cannot init dcmi : %v", err)
    }
    defer w.ShutDown()

    vDeviceInfo, err := w.CreateVDevice(int32(devices[0]), splitDevice)
    if err != nil || vDeviceInfo.VdeviceID < 0 {
    hwlog.RunLog.Errorf("cannot create vd or vdevice is wrong: %v %v", vDeviceInfo.VdeviceID, err)
    return invalidVDevice, err
    }
    return vDeviceInfo, nil
    }

    逐行解析:

  • 定义无效返回值 invalidVDevice(所有ID为-1)
  • nil检查保护
  • extractVpuParam — 从OCI Spec环境变量中提取vNPU切分模板
  • 如果splitDevice为空 → 不是虚拟模式,返回无效值但无错误
  • 设备数校验:vNPU切分只允许1个物理设备(len(devices) != 1),且ID在有效范围内
  • 初始化Worker → 创建虚拟设备 → defer关闭
  • 如果创建失败或VdeviceID<0 → 返回错误
  • 设计意图:此函数是对Worker.CreateVDevice的包装,增加了Spec解析和参数校验。

    2.4 extractVpuParam — vNPU切分模板解析

    func extractVpuParam(spec *specs.Spec) (string, error) {
    allowSplit := map[string]string{
    "vir01": "vir01", "vir02": "vir02", "vir04": "vir04", "vir08": "vir08", "vir16": "vir16",
    "vir02_1c": "vir02_1c", "vir03_1c_8g": "vir03_1c_8g", "vir04_3c": "vir04_3c",
    "vir04_4c_dvpp": "vir04_4c_dvpp", "vir04_3c_ndvpp": "vir04_3c_ndvpp",
    "vir05_1c_8g": "vir05_1c_8g", "vir05_1c_16g": "vir05_1c_16g",
    "vir06_1c_16g": "vir06_1c_16g", "vir10_3c_16g": "vir10_3c_16g",
    "vir10_3c_16g_nm": "vir10_3c_16g_nm", "vir10_3c_32g": "vir10_3c_32g",
    "vir10_4c_16g_m": "vir10_4c_16g_m", "vir12_3c_32g": "vir12_3c_32g",
    }

    for _, line := range spec.Process.Env {
    words := strings.Split(line, "=")
    const LENGTH int = 2
    if len(words) != LENGTH {
    continue
    }
    if strings.TrimSpace(words[0]) == api.AscendVnpuSpescEnv {
    if split, ok := allowSplit[words[1]]; ok && split != "" {
    return split, nil
    }
    return "", fmt.Errorf("cannot parse param : %v", words[1])
    }
    }
    return "", nil
    }

    vNPU切分模板说明:

    模板名含义
    vir01 1/16切分(最小)
    vir02 1/8切分
    vir04 1/4切分
    vir08 1/2切分
    vir16 不切分(全卡)
    vir02_1c 1/8切分+1核
    vir04_3c 1/4切分+3核
    vir04_4c_dvpp 1/4切分+4核+DVPP
    vir04_3c_ndvpp 1/4切分+3核+无DVPP
    vir05_1c_8g 1/3.2切分+1核+8GB
    vir10_3c_16g 1/1.6切分+3核+16GB
    vir10_4c_16g_m 1/1.6切分+4核+16GB+内存增强
    vir12_3c_32g 1/1.3切分+3核+32GB

    逐行解析:

  • 定义允许的切分模板白名单(map)
  • 遍历容器环境变量
  • 找到 ASCEND_VNPU_SPECS 环境变量
  • 如果值在白名单中 → 返回切分模板
  • 如果值不在白名单 → 返回错误(防止非法切分参数)
  • 如果环境变量不存在 → 返回空字符串(非虚拟模式)
  • 设计意图:严格的白名单校验,防止用户传入非法切分参数导致驱动异常。


    三、dcmi.go 逐行解析(360行)

    3.1 常量定义

    const (
    retError = 1
    hiAIMaxCardNum = 64 // 最大卡数
    hiAIMaxCardID = math.MaxInt32 // 卡ID上限
    hiAIMaxDeviceID = math.MaxInt32 // 设备ID上限
    hiAIMaxDeviceNum = 4 // 每卡最大设备数
    maxChipNameLen = 32 // 芯片名最大长度
    productTypeLen = 64 // 产品类型最大长度
    notSupportCode = 8255 // "不支持"错误码
    coreNumLen = 32 // 切分模板名最大长度
    vfgID = 4294967295 // 虚拟组ID默认值(0xFFFFFFFF)
    notSupportString = "[not support]"
    )

    常量值用途
    hiAIMaxCardNum 64 系统最多支持64张NPU卡
    hiAIMaxDeviceNum 4 每张卡最多4个芯片
    maxChipNameLen 32 C结构体中芯片名字段长度
    vfgID 0xFFFFFFFF 虚拟功能组ID,默认自动分配
    notSupportCode -8255 DCMI库返回的"不支持"错误码

    3.2 managerList — Worker注册表

    var managerList = []WorkerInterface{
    &NpuV1Worker{DcMgr: &DcV1Manager{}},
    &NpuV2Worker{DcMgr: &DcV2Manager{}},
    }

    设计意图:全局Worker列表,V1在前V2在后。GetMatchingNpuWorker 按顺序尝试初始化,第一个成功的即为匹配的驱动版本。

    3.3 ChipInfo 结构体

    type ChipInfo struct {
    Type string `json:"chip_type"`
    Name string `json:"chip_name"`
    Version string `json:"chip_version"`
    }

    • 从C结构体 DcmiChipInfo 转换而来
    • Name 用于判断芯片类型(如"Ascend910A"→Ascend910)

    3.4 驱动接口定义

    type DcDriverV1Interface interface {
    DcInitialize() error
    DcShutDown()
    DcGetCardList() (int32, []int32, error)
    DcGetDeviceNumInCard(cardID int32) (int32, error)
    DcGetDeviceLogicID(cardID, deviceID int32) (int32, error)
    DcGetProductType(cardID, deviceID int32) (string, error)
    DcCreateVDevice(cardID, deviceID int32, coreNum string) (int32, error)
    DcDestroyVDevice(cardID, deviceID int32, vDevID int32) error
    DcGetChipInfo(cardID, deviceID int32) (*ChipInfo, error)
    DcGetDeviceLogicidFromPhyid(phyID int32) (int32, error)
    }

    type DcDriverV2Interface interface {
    DcInitialize() error
    DcShutDown()
    DcCreateVDevice(deviceID int32, coreNum string) (int32, error)
    DcDestroyVDevice(deviceID int32, vDevID int32) error
    DcGetChipInfo(deviceID int32) (*ChipInfo, error)
    DcGetDeviceList() (int32, []int32, error)
    }

    V1 vs V2 接口差异:

    差异点V1V2
    设备寻址 cardID + deviceID 二级寻址 deviceID 一级寻址
    卡列表 DcGetCardList → 每卡DcGetDeviceNumInCard DcGetDeviceList 直接获取所有设备
    产品类型 支持 DcGetProductType 不支持(返回"[not support]")
    物理ID转换 DcGetDeviceLogicidFromPhyid 不需要(直接用deviceID)
    虚拟设备 支持 不支持(返回错误)

    3.5 GetMatchingNpuWorker — 工厂函数

    func GetMatchingNpuWorker() (WorkerInterface, error) {
    for _, manager := range managerList {
    err := manager.Initialize()
    if err == nil {
    manager.ShutDown()
    hwlog.RunLog.Infof("worker type: %T", manager)
    return manager, nil
    }
    }
    return nil, fmt.Errorf("failed to find a valid manager")
    }

    逐行解析:

  • 遍历managerList:先尝试V1,再尝试V2
  • 调用 Initialize() 尝试初始化dcmi库
  • 如果成功 → 立即 ShutDown()(因为只是探测,实际使用时会重新初始化)
  • 返回匹配的Worker
  • 如果都失败 → 返回错误
  • 设计意图:V1调用 DcmiInit(),V2调用 DcmiV2Init()。在新版硬件上调用V1初始化会失败,反之亦然。利用这个特性来自动检测驱动版本。

    #mermaid-svg-VYcE0T9MJNGyD0Jd{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VYcE0T9MJNGyD0Jd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VYcE0T9MJNGyD0Jd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VYcE0T9MJNGyD0Jd .error-icon{fill:#552222;}#mermaid-svg-VYcE0T9MJNGyD0Jd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VYcE0T9MJNGyD0Jd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VYcE0T9MJNGyD0Jd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VYcE0T9MJNGyD0Jd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VYcE0T9MJNGyD0Jd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VYcE0T9MJNGyD0Jd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VYcE0T9MJNGyD0Jd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VYcE0T9MJNGyD0Jd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VYcE0T9MJNGyD0Jd .marker.cross{stroke:#333333;}#mermaid-svg-VYcE0T9MJNGyD0Jd svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VYcE0T9MJNGyD0Jd p{margin:0;}#mermaid-svg-VYcE0T9MJNGyD0Jd .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-VYcE0T9MJNGyD0Jd .cluster-label text{fill:#333;}#mermaid-svg-VYcE0T9MJNGyD0Jd .cluster-label span{color:#333;}#mermaid-svg-VYcE0T9MJNGyD0Jd .cluster-label span p{background-color:transparent;}#mermaid-svg-VYcE0T9MJNGyD0Jd .label text,#mermaid-svg-VYcE0T9MJNGyD0Jd span{fill:#333;color:#333;}#mermaid-svg-VYcE0T9MJNGyD0Jd .node rect,#mermaid-svg-VYcE0T9MJNGyD0Jd .node circle,#mermaid-svg-VYcE0T9MJNGyD0Jd .node ellipse,#mermaid-svg-VYcE0T9MJNGyD0Jd .node polygon,#mermaid-svg-VYcE0T9MJNGyD0Jd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VYcE0T9MJNGyD0Jd .rough-node .label text,#mermaid-svg-VYcE0T9MJNGyD0Jd .node .label text,#mermaid-svg-VYcE0T9MJNGyD0Jd .image-shape .label,#mermaid-svg-VYcE0T9MJNGyD0Jd .icon-shape .label{text-anchor:middle;}#mermaid-svg-VYcE0T9MJNGyD0Jd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VYcE0T9MJNGyD0Jd .rough-node .label,#mermaid-svg-VYcE0T9MJNGyD0Jd .node .label,#mermaid-svg-VYcE0T9MJNGyD0Jd .image-shape .label,#mermaid-svg-VYcE0T9MJNGyD0Jd .icon-shape .label{text-align:center;}#mermaid-svg-VYcE0T9MJNGyD0Jd .node.clickable{cursor:pointer;}#mermaid-svg-VYcE0T9MJNGyD0Jd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VYcE0T9MJNGyD0Jd .arrowheadPath{fill:#333333;}#mermaid-svg-VYcE0T9MJNGyD0Jd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VYcE0T9MJNGyD0Jd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VYcE0T9MJNGyD0Jd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VYcE0T9MJNGyD0Jd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VYcE0T9MJNGyD0Jd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VYcE0T9MJNGyD0Jd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VYcE0T9MJNGyD0Jd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VYcE0T9MJNGyD0Jd .cluster text{fill:#333;}#mermaid-svg-VYcE0T9MJNGyD0Jd .cluster span{color:#333;}#mermaid-svg-VYcE0T9MJNGyD0Jd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VYcE0T9MJNGyD0Jd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VYcE0T9MJNGyD0Jd rect.text{fill:none;stroke-width:0;}#mermaid-svg-VYcE0T9MJNGyD0Jd .icon-shape,#mermaid-svg-VYcE0T9MJNGyD0Jd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VYcE0T9MJNGyD0Jd .icon-shape p,#mermaid-svg-VYcE0T9MJNGyD0Jd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VYcE0T9MJNGyD0Jd .icon-shape .label rect,#mermaid-svg-VYcE0T9MJNGyD0Jd .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VYcE0T9MJNGyD0Jd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VYcE0T9MJNGyD0Jd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VYcE0T9MJNGyD0Jd :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    GetMatchingNpuWorker

    尝试NpuV1Worker.Initialize

    DcmiInit成功?

    ShutDown关闭探测连接

    返回NpuV1Worker

    尝试NpuV2Worker.Initialize

    DcmiV2Init成功?

    ShutDown

    返回NpuV2Worker

    返回错误failed to find valid manager

    3.6 NpuV1Worker.FindDevice — 物理ID到卡/设备映射

    func (w *NpuV1Worker) FindDevice(visibleDevice int32) (int32, int32, error) {
    targetLogicID, err := w.DcMgr.DcGetDeviceLogicidFromPhyid(visibleDevice)
    if err != nil {
    return 0, 0, fmt.Errorf("cannot convert phy id to logic id, err: %v", err)
    }
    _, cardList, err := w.DcMgr.DcGetCardList()
    if err != nil {
    return 0, 0, fmt.Errorf("get card list err : %v", err)
    }
    targetDeviceID, targetCardID := int32(math.MaxInt32), int32(math.MaxInt32)
    for _, cardID := range cardList {
    deviceCount, err := w.DcMgr.DcGetDeviceNumInCard(cardID)
    if err != nil {
    return 0, 0, fmt.Errorf("cannot get device num in card : %v", err)
    }
    for deviceID := int32(0); deviceID < deviceCount; deviceID++ {
    logicID, err := w.DcMgr.DcGetDeviceLogicID(cardID, deviceID)
    if err != nil {
    return 0, 0, fmt.Errorf("cannot get logic id : %v", err)
    }
    if logicID == targetLogicID {
    targetCardID, targetDeviceID = cardID, deviceID
    }
    }
    }
    return targetDeviceID, targetCardID, nil
    }

    逐行解析:

  • 将物理ID(用户指定的visibleDevice)转换为逻辑ID
  • 获取所有卡的列表
  • 双层遍历:遍历每张卡,遍历卡内每个设备
  • 对每个设备获取其逻辑ID
  • 如果逻辑ID匹配目标 → 记录cardID和deviceID
  • 返回找到的deviceID和cardID
  • 设计意图:V1驱动使用"物理ID"作为用户接口(如ASCEND_VISIBLE_DEVICES=0),但内部操作需要cardID+deviceID二维坐标。此函数完成这个映射。

    #mermaid-svg-OFtCmAwrmgWmqUML{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-OFtCmAwrmgWmqUML .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-OFtCmAwrmgWmqUML .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-OFtCmAwrmgWmqUML .error-icon{fill:#552222;}#mermaid-svg-OFtCmAwrmgWmqUML .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-OFtCmAwrmgWmqUML .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-OFtCmAwrmgWmqUML .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-OFtCmAwrmgWmqUML .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-OFtCmAwrmgWmqUML .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-OFtCmAwrmgWmqUML .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-OFtCmAwrmgWmqUML .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-OFtCmAwrmgWmqUML .marker{fill:#333333;stroke:#333333;}#mermaid-svg-OFtCmAwrmgWmqUML .marker.cross{stroke:#333333;}#mermaid-svg-OFtCmAwrmgWmqUML svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-OFtCmAwrmgWmqUML p{margin:0;}#mermaid-svg-OFtCmAwrmgWmqUML .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-OFtCmAwrmgWmqUML .cluster-label text{fill:#333;}#mermaid-svg-OFtCmAwrmgWmqUML .cluster-label span{color:#333;}#mermaid-svg-OFtCmAwrmgWmqUML .cluster-label span p{background-color:transparent;}#mermaid-svg-OFtCmAwrmgWmqUML .label text,#mermaid-svg-OFtCmAwrmgWmqUML span{fill:#333;color:#333;}#mermaid-svg-OFtCmAwrmgWmqUML .node rect,#mermaid-svg-OFtCmAwrmgWmqUML .node circle,#mermaid-svg-OFtCmAwrmgWmqUML .node ellipse,#mermaid-svg-OFtCmAwrmgWmqUML .node polygon,#mermaid-svg-OFtCmAwrmgWmqUML .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-OFtCmAwrmgWmqUML .rough-node .label text,#mermaid-svg-OFtCmAwrmgWmqUML .node .label text,#mermaid-svg-OFtCmAwrmgWmqUML .image-shape .label,#mermaid-svg-OFtCmAwrmgWmqUML .icon-shape .label{text-anchor:middle;}#mermaid-svg-OFtCmAwrmgWmqUML .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-OFtCmAwrmgWmqUML .rough-node .label,#mermaid-svg-OFtCmAwrmgWmqUML .node .label,#mermaid-svg-OFtCmAwrmgWmqUML .image-shape .label,#mermaid-svg-OFtCmAwrmgWmqUML .icon-shape .label{text-align:center;}#mermaid-svg-OFtCmAwrmgWmqUML .node.clickable{cursor:pointer;}#mermaid-svg-OFtCmAwrmgWmqUML .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-OFtCmAwrmgWmqUML .arrowheadPath{fill:#333333;}#mermaid-svg-OFtCmAwrmgWmqUML .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-OFtCmAwrmgWmqUML .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-OFtCmAwrmgWmqUML .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OFtCmAwrmgWmqUML .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-OFtCmAwrmgWmqUML .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OFtCmAwrmgWmqUML .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-OFtCmAwrmgWmqUML .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-OFtCmAwrmgWmqUML .cluster text{fill:#333;}#mermaid-svg-OFtCmAwrmgWmqUML .cluster span{color:#333;}#mermaid-svg-OFtCmAwrmgWmqUML div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-OFtCmAwrmgWmqUML .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-OFtCmAwrmgWmqUML rect.text{fill:none;stroke-width:0;}#mermaid-svg-OFtCmAwrmgWmqUML .icon-shape,#mermaid-svg-OFtCmAwrmgWmqUML .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OFtCmAwrmgWmqUML .icon-shape p,#mermaid-svg-OFtCmAwrmgWmqUML .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-OFtCmAwrmgWmqUML .icon-shape .label rect,#mermaid-svg-OFtCmAwrmgWmqUML .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OFtCmAwrmgWmqUML .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-OFtCmAwrmgWmqUML .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-OFtCmAwrmgWmqUML :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    FindDevicevisibleDevice=0

    DcGetDeviceLogicidFromPhyid物理ID→逻辑ID

    DcGetCardList获取所有卡ID

    遍历每张卡

    DcGetDeviceNumInCard获取卡内设备数

    遍历卡内每个设备

    DcGetDeviceLogicID获取设备的逻辑ID

    逻辑ID == 目标?

    记录cardID和deviceID

    还有更多设备?

    还有更多卡?

    返回deviceID, cardID

    3.7 NpuV1Worker.GetChipName

    func (w *NpuV1Worker) GetChipName() (string, error) {
    invalidName := ""

    if err := w.Initialize(); err != nil {
    return invalidName, fmt.Errorf("cannot init dcmi : %v", err)
    }
    defer w.ShutDown()

    cardNum, cardList, err := w.DcMgr.DcGetCardList()
    if err != nil {
    return invalidName, err
    }
    if cardNum == 0 {
    return invalidName, fmt.Errorf("get chip info failed, no card found")
    }

    for _, cardID := range cardList {
    devNum, err := w.DcMgr.DcGetDeviceNumInCard(cardID)
    if err != nil || devNum == 0 {
    continue
    }
    for devID := int32(0); devID < devNum; devID++ {
    chipInfo, err := w.DcMgr.DcGetChipInfo(cardID, devID)
    if err != nil {
    continue
    }
    if !isValidChipInfo(chipInfo) {
    continue
    }
    return (*chipInfo).Name, nil
    }
    }

    return invalidName, fmt.Errorf("cannot get valid chip info")
    }

    执行流程:

  • 初始化dcmi → 获取卡列表 → 遍历卡 → 遍历设备 → 获取芯片信息 → 返回第一个有效芯片名
  • 容错策略:任何单步失败都continue跳过,继续尝试下一个设备
  • defer确保关闭dcmi连接
  • 设计意图:只需要获取任意一个有效芯片的名称即可确定整个系统的芯片类型(假设同一机器上芯片类型一致)。

    3.8 NpuV2Worker.GetChipName

    func (a *NpuV2Worker) GetChipName() (string, error) {
    invalidName := ""

    if err := a.Initialize(); err != nil {
    return invalidName, fmt.Errorf("cannot init dcmi : %v", err)
    }
    defer a.ShutDown()

    deviceNum, deviceList, err := a.DcMgr.DcGetDeviceList()
    // …
    for _, devID := range deviceList {
    chipInfo, err := a.DcMgr.DcGetChipInfo(devID)
    // …
    return (*chipInfo).Name, nil
    }
    return invalidName, fmt.Errorf("cannot get valid chip info")
    }

    与V1的区别:

    • V1:卡列表→每卡设备数→遍历cardID+deviceID
    • V2:直接获取设备列表→遍历deviceID

    3.9 NpuV1Worker.CreateVDevice

    func (w *NpuV1Worker) CreateVDevice(uniqueID int32, coreNum string) (VDeviceInfo, error) {
    deviceID, cardID, err := w.FindDevice(uniqueID)
    if err != nil {
    return VDeviceInfo{CardID: 1, DeviceID: 1, VdeviceID: 1}, err
    }
    vdevId, err := w.DcMgr.DcCreateVDevice(cardID, deviceID, coreNum)
    if err != nil {
    return VDeviceInfo{CardID: 1, DeviceID: 1, VdeviceID: math.MaxInt32}, err
    }
    if vdevId > math.MaxInt32 {
    return VDeviceInfo{CardID: cardID, DeviceID: deviceID, VdeviceID: math.MaxInt32},
    fmt.Errorf("create virtual device failed, vdeviceId too large")
    }
    return VDeviceInfo{CardID: cardID, DeviceID: deviceID, VdeviceID: int32(vdevId)}, nil
    }

    逐行解析:

  • FindDevice — 将物理ID转换为cardID+deviceID
  • DcCreateVDevice — 调用CGO创建虚拟设备
  • 溢出检查:vdevId > math.MaxInt32
  • 返回完整的VDeviceInfo
  • 3.10 NpuV2Worker.CreateVDevice

    func (a *NpuV2Worker) CreateVDevice(uniqueID int32, coreNum string) (VDeviceInfo, error) {
    vdevId, err := a.DcMgr.DcCreateVDevice(uniqueID, coreNum)
    if err != nil {
    return VDeviceInfo{
    CardID: 1,
    DeviceID: 1,
    VdeviceID: 1,
    }, err
    }
    return VDeviceInfo{VdeviceID: vdevId}, nil
    }

    注意:V2的 DcCreateVDevice 实际返回错误(“ascend 950 not support virtual device”),所以这段代码在当前版本实际上不会成功执行。


    四、dcManager.go 逐行解析(294行)

    4.1 CGO导入

    // #cgo LDFLAGS: -ldl
    // #include "dcmi_interface_api.h"
    import "C"

    • LDFLAGS: -ldl — 链接动态加载库(dlopen)
    • #include "dcmi_interface_api.h" — DCMI C接口头文件
    • import "C" — Go的CGO机制,允许调用C函数

    4.2 DcV1Manager.DcInitialize

    func (d *DcV1Manager) DcInitialize() error {
    cDlPath := C.CString(string(make([]byte, int32(C.PATH_MAX))))
    defer C.free(unsafe.Pointer(cDlPath))
    if err := C.DcmiInitDl(cDlPath); err != C.SUCCESS {
    errInfo := fmt.Errorf("dcmi lib load failed, error code: %d", int32(err))
    return errInfo
    }
    dlPath := C.GoString(cDlPath)
    if _, err := mindxcheckutils.RealFileChecker(dlPath, true, false, mindxcheckutils.DefaultSize); err != nil {
    return err
    }
    if err := C.DcmiInit(); err != C.SUCCESS {
    errInfo := fmt.Errorf("dcmi init failed, error code: %d", int32(err))
    return errInfo
    }
    return nil
    }

    逐行解析:

  • make([]byte, C.PATH_MAX) — 创建PATH_MAX长度的空字节切片
  • C.CString — 转换为C字符串(用于接收dcmi库路径输出)
  • C.DcmiInitDl(cDlPath) — 动态加载libdcmi.so(dlopen方式),路径通过cDlPath返回
  • defer C.free — 释放C字符串内存(防内存泄漏)
  • C.GoString(cDlPath) — 将C字符串转回Go字符串
  • RealFileChecker — 安全校验加载的dcmi库文件
  • C.DcmiInit() — 初始化dcmi设备管理连接
  • 设计意图:两步初始化——先加载动态库(dlopen),再初始化设备连接。安全校验确保加载的是合法dcmi库。

    #mermaid-svg-tu8zhbbKHxJoZJTO{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-tu8zhbbKHxJoZJTO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-tu8zhbbKHxJoZJTO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-tu8zhbbKHxJoZJTO .error-icon{fill:#552222;}#mermaid-svg-tu8zhbbKHxJoZJTO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tu8zhbbKHxJoZJTO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-tu8zhbbKHxJoZJTO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tu8zhbbKHxJoZJTO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tu8zhbbKHxJoZJTO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-tu8zhbbKHxJoZJTO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tu8zhbbKHxJoZJTO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tu8zhbbKHxJoZJTO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tu8zhbbKHxJoZJTO .marker.cross{stroke:#333333;}#mermaid-svg-tu8zhbbKHxJoZJTO svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tu8zhbbKHxJoZJTO p{margin:0;}#mermaid-svg-tu8zhbbKHxJoZJTO .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-tu8zhbbKHxJoZJTO .cluster-label text{fill:#333;}#mermaid-svg-tu8zhbbKHxJoZJTO .cluster-label span{color:#333;}#mermaid-svg-tu8zhbbKHxJoZJTO .cluster-label span p{background-color:transparent;}#mermaid-svg-tu8zhbbKHxJoZJTO .label text,#mermaid-svg-tu8zhbbKHxJoZJTO span{fill:#333;color:#333;}#mermaid-svg-tu8zhbbKHxJoZJTO .node rect,#mermaid-svg-tu8zhbbKHxJoZJTO .node circle,#mermaid-svg-tu8zhbbKHxJoZJTO .node ellipse,#mermaid-svg-tu8zhbbKHxJoZJTO .node polygon,#mermaid-svg-tu8zhbbKHxJoZJTO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-tu8zhbbKHxJoZJTO .rough-node .label text,#mermaid-svg-tu8zhbbKHxJoZJTO .node .label text,#mermaid-svg-tu8zhbbKHxJoZJTO .image-shape .label,#mermaid-svg-tu8zhbbKHxJoZJTO .icon-shape .label{text-anchor:middle;}#mermaid-svg-tu8zhbbKHxJoZJTO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-tu8zhbbKHxJoZJTO .rough-node .label,#mermaid-svg-tu8zhbbKHxJoZJTO .node .label,#mermaid-svg-tu8zhbbKHxJoZJTO .image-shape .label,#mermaid-svg-tu8zhbbKHxJoZJTO .icon-shape .label{text-align:center;}#mermaid-svg-tu8zhbbKHxJoZJTO .node.clickable{cursor:pointer;}#mermaid-svg-tu8zhbbKHxJoZJTO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-tu8zhbbKHxJoZJTO .arrowheadPath{fill:#333333;}#mermaid-svg-tu8zhbbKHxJoZJTO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-tu8zhbbKHxJoZJTO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-tu8zhbbKHxJoZJTO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tu8zhbbKHxJoZJTO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-tu8zhbbKHxJoZJTO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tu8zhbbKHxJoZJTO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-tu8zhbbKHxJoZJTO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-tu8zhbbKHxJoZJTO .cluster text{fill:#333;}#mermaid-svg-tu8zhbbKHxJoZJTO .cluster span{color:#333;}#mermaid-svg-tu8zhbbKHxJoZJTO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-tu8zhbbKHxJoZJTO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-tu8zhbbKHxJoZJTO rect.text{fill:none;stroke-width:0;}#mermaid-svg-tu8zhbbKHxJoZJTO .icon-shape,#mermaid-svg-tu8zhbbKHxJoZJTO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tu8zhbbKHxJoZJTO .icon-shape p,#mermaid-svg-tu8zhbbKHxJoZJTO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-tu8zhbbKHxJoZJTO .icon-shape .label rect,#mermaid-svg-tu8zhbbKHxJoZJTO .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tu8zhbbKHxJoZJTO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-tu8zhbbKHxJoZJTO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-tu8zhbbKHxJoZJTO :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    失败

    成功

    不通过

    通过

    失败

    成功

    DcInitialize

    分配C字符串bufferPATH_MAX长度

    DcmiInitDldlopen加载libdcmi.so

    返回错误dcmi lib load failed

    获取库路径C.GoString

    RealFileChecker安全校验库文件

    返回错误

    DcmiInit初始化设备连接

    返回错误dcmi init failed

    返回nil

    4.3 DcV1Manager.DcGetCardList

    func (d *DcV1Manager) DcGetCardList() (int32, []int32, error) {
    var ids [hiAIMaxCardNum]C.int
    var cNum C.int
    if err := C.DcmiGetCardNumList(&cNum, &ids[0], hiAIMaxCardNum); err != 0 {
    return retError, nil, fmt.Errorf("get card list failed, error code: %d", int32(err))
    }
    if cNum <= 0 || cNum > hiAIMaxCardNum {
    return retError, nil, fmt.Errorf("get error card quantity: %d", int32(cNum))
    }
    var cardNum = int32(cNum)
    var cardIDList []int32
    for i := int32(0); i < cardNum; i++ {
    cardID := int32(ids[i])
    if cardID < 0 {
    continue
    }
    cardIDList = append(cardIDList, cardID)
    }
    return cardNum, cardIDList, nil
    }

    逐行解析:

  • 声明C数组 ids[64] 和数量 cNum
  • C.DcmiGetCardNumList — C函数填充卡数量和卡ID列表
  • 校验数量:1 ≤ cNum ≤ 64
  • 遍历C数组,过滤负值,转为Go的[]int32
  • 4.4 DcV1Manager.DcCreateVDevice

    func (d *DcV1Manager) DcCreateVDevice(cardID, deviceID int32, coreNum string) (int32, error) {
    var createInfo C.struct_DcmiCreateVdevOut
    createInfo.vdevId = C.uint(math.MaxUint32)
    var deviceCreateStr C.struct_DcmiCreateVdevResStru
    deviceCreateStr = C.struct_DcmiCreateVdevResStru{
    vdevId: C.uint(vfgID),
    vfgId: C.uint(vfgID),
    }
    deviceCreateStrArr := [coreNumLen]C.char{0}
    for i := 0; i < len(coreNum); i++ {
    if i >= coreNumLen {
    return math.MaxInt32, fmt.Errorf("wrong template")
    }
    deviceCreateStrArr[i] = C.char(coreNum[i])
    }
    deviceCreateStr.templateName = deviceCreateStrArr
    ret := C.DcmiCreateVdevice(C.int(cardID), C.int(deviceID), &deviceCreateStr, &createInfo)
    if ret != 0 {
    return math.MaxInt32, fmt.Errorf("create virtual device failed, error code: %d", int32(ret))
    }
    return int32(createInfo.vdevId), nil
    }

    逐行解析:

  • 创建输出结构体 DcmiCreateVdevOut,初始vdevId设为MaxUint32(表示未创建)
  • 创建输入结构体 DcmiCreateVdevResStru,设置vdevId和vfgId为默认值(0xFFFFFFFF)
  • 将切分模板名(如"vir04")逐字节复制到C字符数组
  • 模板名长度校验(≤32)
  • 调用 C.DcmiCreateVdevice — CGO调用创建虚拟设备
  • 返回创建的vdevId
  • 关键数据结构:

    #mermaid-svg-Ls9qSzt4Ej6fTd78{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Ls9qSzt4Ej6fTd78 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .error-icon{fill:#552222;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .marker.cross{stroke:#333333;}#mermaid-svg-Ls9qSzt4Ej6fTd78 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Ls9qSzt4Ej6fTd78 p{margin:0;}#mermaid-svg-Ls9qSzt4Ej6fTd78 g.classGroup text{fill:#9370DB;stroke:none;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-Ls9qSzt4Ej6fTd78 g.classGroup text .title{font-weight:bolder;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .cluster-label text{fill:#333;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .cluster-label span{color:#333;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .cluster-label span p{background-color:transparent;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .cluster text{fill:#333;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .cluster span{color:#333;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .nodeLabel,#mermaid-svg-Ls9qSzt4Ej6fTd78 .edgeLabel{color:#131300;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .label text{fill:#131300;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .labelBkg{background:#ECECFF;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .classTitle{font-weight:bolder;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .node rect,#mermaid-svg-Ls9qSzt4Ej6fTd78 .node circle,#mermaid-svg-Ls9qSzt4Ej6fTd78 .node ellipse,#mermaid-svg-Ls9qSzt4Ej6fTd78 .node polygon,#mermaid-svg-Ls9qSzt4Ej6fTd78 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-Ls9qSzt4Ej6fTd78 g.clickable{cursor:pointer;}#mermaid-svg-Ls9qSzt4Ej6fTd78 g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-Ls9qSzt4Ej6fTd78 g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .dashed-line{stroke-dasharray:3;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-Ls9qSzt4Ej6fTd78 #compositionStart,#mermaid-svg-Ls9qSzt4Ej6fTd78 .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Ls9qSzt4Ej6fTd78 #compositionEnd,#mermaid-svg-Ls9qSzt4Ej6fTd78 .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Ls9qSzt4Ej6fTd78 #dependencyStart,#mermaid-svg-Ls9qSzt4Ej6fTd78 .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Ls9qSzt4Ej6fTd78 #dependencyStart,#mermaid-svg-Ls9qSzt4Ej6fTd78 .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Ls9qSzt4Ej6fTd78 #extensionStart,#mermaid-svg-Ls9qSzt4Ej6fTd78 .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Ls9qSzt4Ej6fTd78 #extensionEnd,#mermaid-svg-Ls9qSzt4Ej6fTd78 .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Ls9qSzt4Ej6fTd78 #aggregationStart,#mermaid-svg-Ls9qSzt4Ej6fTd78 .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Ls9qSzt4Ej6fTd78 #aggregationEnd,#mermaid-svg-Ls9qSzt4Ej6fTd78 .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Ls9qSzt4Ej6fTd78 #lollipopStart,#mermaid-svg-Ls9qSzt4Ej6fTd78 .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Ls9qSzt4Ej6fTd78 #lollipopEnd,#mermaid-svg-Ls9qSzt4Ej6fTd78 .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Ls9qSzt4Ej6fTd78 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Ls9qSzt4Ej6fTd78 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    输入→输出

    DcmiCreateVdevResStru

    +uint vdevId

    +uint vfgId

    +char[32] templateName "切分模板名如vir04"

    DcmiCreateVdevOut

    +uint vdevId "创建后的虚拟设备ID"

    4.5 DcV1Manager.DcGetChipInfo

    func (d *DcV1Manager) DcGetChipInfo(cardID, deviceID int32) (*ChipInfo, error) {
    if !isValidCardIDAndDeviceID(cardID, deviceID) {
    return nil, fmt.Errorf("cardID(%d) or deviceID(%d) is invalid", cardID, deviceID)
    }
    var chipInfo C.struct_DcmiChipInfo
    if rCode := C.DcmiGetDeviceChipInfo(C.int(cardID), C.int(deviceID), &chipInfo); int32(rCode) != 0 {
    return nil, fmt.Errorf("get device ChipInfo information failed, …")
    }

    name := convertUCharToCharArr(chipInfo.chipName)
    cType := convertUCharToCharArr(chipInfo.chipType)
    ver := convertUCharToCharArr(chipInfo.chipVer)

    chip := &ChipInfo{
    Name: string(name),
    Type: string(cType),
    Version: string(ver),
    }
    if !isValidChipInfo(chip) {
    return nil, fmt.Errorf("get device ChipInfo information failed, chip info is empty, …")
    }

    return chip, nil
    }

    逐行解析:

  • 参数校验(cardID和deviceID范围检查)
  • 声明C结构体 DcmiChipInfo
  • 调用 C.DcmiGetDeviceChipInfo 获取芯片信息
  • convertUCharToCharArr — 将C的uchar数组转为Go byte切片(遇0截断)
  • 构造Go的ChipInfo结构体
  • 有效性校验
  • 4.6 convertUCharToCharArr — C数组转Go

    func convertUCharToCharArr(cgoArr [maxChipNameLen]C.uchar) []byte {
    var charArr []byte
    for _, v := range cgoArr {
    if v == 0 {
    break
    }
    charArr = append(charArr, byte(v))
    }
    return charArr
    }

    • C字符串以null(0)结尾,遍历到0即停止
    • 将C的[32]uchar转为Go的[]byte,再转为string

    4.7 DcV2Manager — V2 CGO实现

    func (d *DcV2Manager) DcInitialize() error {
    // …同V1的DcmiInitDl…
    if err := C.DcmiV2Init(); err != C.SUCCESS {
    return fmt.Errorf("dcmi init failed, error code: %d", int32(err))
    }
    return nil
    }

    关键差异:V2调用 C.DcmiV2Init() 而非 C.DcmiInit()。

    func (d *DcV2Manager) DcCreateVDevice(deviceID int32, coreNum string) (int32, error) {
    return 1, fmt.Errorf("create error, ascend 950 not support virtual device")
    }

    func (d *DcV2Manager) DcDestroyVDevice(deviceID int32, vDevID int32) error {
    return fmt.Errorf("destroy error, ascend 950 not support virtual device")
    }

    V2不支持虚拟设备:Ascend 950(910A5)不支持vNPU切分,直接返回错误。

    func (d *DcV2Manager) DcGetDeviceList() (int32, []int32, error) {
    var ids [hiAIMaxCardNum]C.int
    var cNum C.int
    if err := C.DcmiV2GetDeviceList(&ids[0], &cNum, hiAIMaxCardNum); err != 0 {
    return retError, nil, fmt.Errorf("get device list failed, error code: %d", int32(err))
    }
    // …校验+转换…
    return deviceNum, deviceIDList, nil
    }

    V2直接获取设备列表,无需先获取卡列表再遍历卡内设备。


    五、V1 vs V2 完整对比

    #mermaid-svg-7FJDdB1jd6Ui6Vgt{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7FJDdB1jd6Ui6Vgt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .error-icon{fill:#552222;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .marker.cross{stroke:#333333;}#mermaid-svg-7FJDdB1jd6Ui6Vgt svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7FJDdB1jd6Ui6Vgt p{margin:0;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .cluster-label text{fill:#333;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .cluster-label span{color:#333;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .cluster-label span p{background-color:transparent;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .label text,#mermaid-svg-7FJDdB1jd6Ui6Vgt span{fill:#333;color:#333;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .node rect,#mermaid-svg-7FJDdB1jd6Ui6Vgt .node circle,#mermaid-svg-7FJDdB1jd6Ui6Vgt .node ellipse,#mermaid-svg-7FJDdB1jd6Ui6Vgt .node polygon,#mermaid-svg-7FJDdB1jd6Ui6Vgt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .rough-node .label text,#mermaid-svg-7FJDdB1jd6Ui6Vgt .node .label text,#mermaid-svg-7FJDdB1jd6Ui6Vgt .image-shape .label,#mermaid-svg-7FJDdB1jd6Ui6Vgt .icon-shape .label{text-anchor:middle;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .rough-node .label,#mermaid-svg-7FJDdB1jd6Ui6Vgt .node .label,#mermaid-svg-7FJDdB1jd6Ui6Vgt .image-shape .label,#mermaid-svg-7FJDdB1jd6Ui6Vgt .icon-shape .label{text-align:center;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .node.clickable{cursor:pointer;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .arrowheadPath{fill:#333333;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7FJDdB1jd6Ui6Vgt .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7FJDdB1jd6Ui6Vgt .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-7FJDdB1jd6Ui6Vgt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .cluster text{fill:#333;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .cluster span{color:#333;}#mermaid-svg-7FJDdB1jd6Ui6Vgt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7FJDdB1jd6Ui6Vgt rect.text{fill:none;stroke-width:0;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .icon-shape,#mermaid-svg-7FJDdB1jd6Ui6Vgt .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .icon-shape p,#mermaid-svg-7FJDdB1jd6Ui6Vgt .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .icon-shape .label rect,#mermaid-svg-7FJDdB1jd6Ui6Vgt .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7FJDdB1jd6Ui6Vgt .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-7FJDdB1jd6Ui6Vgt .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-7FJDdB1jd6Ui6Vgt :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    V2 新版驱动 Ascend 910B/A5

    DcmiV2Init

    DcmiV2GetDeviceList直接获取设备列表

    DcmiV2GetDeviceChipInfo仅deviceID

    不支持vNPU返回错误

    V1 旧版驱动 Ascend 910/310

    DcmiInit

    DcmiGetCardNumList获取卡列表

    DcmiGetDeviceNumInCard每卡设备数

    DcmiGetDeviceChipInfocardID+deviceID

    DcmiCreateVdevice支持vNPU切分

    DcmiSetDestroyVdevice销毁vNPU

    DcmiGetDeviceLogicidFromPhyid物理ID→逻辑ID

    对比维度V1 (DcV1Manager)V2 (DcV2Manager)
    初始化 DcmiInitDl + DcmiInit DcmiInitDl + DcmiV2Init
    设备寻址 cardID + deviceID 二级 deviceID 一级
    获取设备列表 DcmiGetCardNumList → 遍历卡 → DcmiGetDeviceNumInCard DcmiV2GetDeviceList 一步到位
    芯片信息 DcmiGetDeviceChipInfo(cardID, deviceID) DcmiV2GetDeviceChipInfo(deviceID)
    产品类型 支持 DcmiGetProductType 不支持(返回"[not support]")
    vNPU切分 支持 DcmiCreateVdevice 不支持(返回错误)
    物理ID转换 需要 DcmiGetDeviceLogicidFromPhyid 不需要
    适用芯片 Ascend 910, 310, 310P, 310B Ascend 910B, A5 (950)
    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 【NPU】Ascend Docker Runtime v26.0.1 之三 runtime/dcmi/ — 超深度逐行分析
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!