【NVIDIA】NVIDIA k8s-device-plugin v0.19.3 资源管理器模块深度分析之三

NVIDIA k8s-device-plugin v0.19.3 资源管理器模块深度分析

模块路径: internal/rm

分析版本: v0.19.3

文件数: 11


一、模块定位

1.1 业务职责

internal/rm 是 NVIDIA k8s-device-plugin 的资源管理核心模块,负责:

  1. 设备发现:通过 NVML / Tegra / WSL 三种后端发现 GPU 及 MIG 设备
  2. 设备映射:将物理设备映射到 Kubernetes 可识别的 ResourceName
  3. 设备共享:支持时间分片(TimeSlicing)和 MPS 两种共享策略下的设备副本(replica)管理
  4. 设备分配:提供 PreferredAllocation 算法,支持对齐分配(AlignedAlloc)和分布式分配(DistributedAlloc)
  5. 健康检查:基于 NVML Xid 事件 + ECC 错误的实时设备健康监控
  6. 请求校验:校验kubelet分配请求中的设备ID合法性与共享策略约束

1.2 系统位置

复制代码
┌─────────────────────────────────────────────────────────────┐
│                  k8s-device-plugin (main.go)                 │
│                         │                                    │
│          ┌──────────────┴──────────────┐                     │
│          │    internal/plugin          │                     │
│          │   (Plugin gRPC Server)      │                     │
│          └──────────────┬──────────────┘                     │
│                         │                                    │
│          ┌──────────────┴──────────────┐                     │
│          │      internal/rm ★          │ ← 本模块             │
│          │   (Resource Manager)        │                     │
│          └──────┬────────┬────────┬────┘                     │
│                 │        │        │                          │
│     ┌───────────┘        │        └───────────┐              │
│     ▼                    ▼                    ▼              │
│  NVML后端            Tegra后端           WSL后端              │
│  (nvml_manager)     (tegra_manager)    (wsl_devices)         │
│     │                    │                    │              │
│     ▼                    ▼                    ▼              │
│  go-nvml库           硬编码设备          /dev/dxg             │
│  go-gpuallocator    (Jetson平台)        (WSL2平台)           │
└─────────────────────────────────────────────────────────────┘

二、模块整体结构

2.1 文件清单与职责

文件 行数 核心职责
rm.go ~170 定义 ResourceManager 接口和基础 resourceManager 结构体
devices.go ~210 定义 Device/Devices/AnnotatedID 等核心数据类型
device_map.go ~260 DeviceMap 构建器,设备到资源名的映射逻辑
health.go ~280 基于 Xid 事件的设备健康检查
allocate.go ~75 分布式副本分配算法
helper.go ~20 uint8Slice 辅助类型
nvml_devices.go ~200 NVML 后端的 deviceInfo 实现 (GPU + MIG)
nvml_manager.go ~130 NVML 后端的 ResourceManager 构建
tegra_devices.go ~60 Tegra 后端的 deviceInfo 实现
tegra_manager.go ~40 Tegra 后端的 ResourceManager 构建
wsl_devices.go ~45 WSL 后端的 deviceInfo 实现

2.2 核心类型关系图

#mermaid-svg-JbhdalVOfN9EQi9q{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-JbhdalVOfN9EQi9q .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-JbhdalVOfN9EQi9q .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-JbhdalVOfN9EQi9q .error-icon{fill:#552222;}#mermaid-svg-JbhdalVOfN9EQi9q .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-JbhdalVOfN9EQi9q .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-JbhdalVOfN9EQi9q .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-JbhdalVOfN9EQi9q .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-JbhdalVOfN9EQi9q .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-JbhdalVOfN9EQi9q .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-JbhdalVOfN9EQi9q .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-JbhdalVOfN9EQi9q .marker{fill:#333333;stroke:#333333;}#mermaid-svg-JbhdalVOfN9EQi9q .marker.cross{stroke:#333333;}#mermaid-svg-JbhdalVOfN9EQi9q svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-JbhdalVOfN9EQi9q p{margin:0;}#mermaid-svg-JbhdalVOfN9EQi9q g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-JbhdalVOfN9EQi9q g.classGroup text .title{font-weight:bolder;}#mermaid-svg-JbhdalVOfN9EQi9q .cluster-label text{fill:#333;}#mermaid-svg-JbhdalVOfN9EQi9q .cluster-label span{color:#333;}#mermaid-svg-JbhdalVOfN9EQi9q .cluster-label span p{background-color:transparent;}#mermaid-svg-JbhdalVOfN9EQi9q .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-JbhdalVOfN9EQi9q .cluster text{fill:#333;}#mermaid-svg-JbhdalVOfN9EQi9q .cluster span{color:#333;}#mermaid-svg-JbhdalVOfN9EQi9q .nodeLabel,#mermaid-svg-JbhdalVOfN9EQi9q .edgeLabel{color:#131300;}#mermaid-svg-JbhdalVOfN9EQi9q .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-JbhdalVOfN9EQi9q .label text{fill:#131300;}#mermaid-svg-JbhdalVOfN9EQi9q .labelBkg{background:#ECECFF;}#mermaid-svg-JbhdalVOfN9EQi9q .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-JbhdalVOfN9EQi9q .classTitle{font-weight:bolder;}#mermaid-svg-JbhdalVOfN9EQi9q .node rect,#mermaid-svg-JbhdalVOfN9EQi9q .node circle,#mermaid-svg-JbhdalVOfN9EQi9q .node ellipse,#mermaid-svg-JbhdalVOfN9EQi9q .node polygon,#mermaid-svg-JbhdalVOfN9EQi9q .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-JbhdalVOfN9EQi9q .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-JbhdalVOfN9EQi9q g.clickable{cursor:pointer;}#mermaid-svg-JbhdalVOfN9EQi9q g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-JbhdalVOfN9EQi9q g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-JbhdalVOfN9EQi9q .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-JbhdalVOfN9EQi9q .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-JbhdalVOfN9EQi9q .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-JbhdalVOfN9EQi9q .dashed-line{stroke-dasharray:3;}#mermaid-svg-JbhdalVOfN9EQi9q .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-JbhdalVOfN9EQi9q #compositionStart,#mermaid-svg-JbhdalVOfN9EQi9q .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JbhdalVOfN9EQi9q #compositionEnd,#mermaid-svg-JbhdalVOfN9EQi9q .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JbhdalVOfN9EQi9q #dependencyStart,#mermaid-svg-JbhdalVOfN9EQi9q .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JbhdalVOfN9EQi9q #dependencyStart,#mermaid-svg-JbhdalVOfN9EQi9q .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JbhdalVOfN9EQi9q #extensionStart,#mermaid-svg-JbhdalVOfN9EQi9q .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JbhdalVOfN9EQi9q #extensionEnd,#mermaid-svg-JbhdalVOfN9EQi9q .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JbhdalVOfN9EQi9q #aggregationStart,#mermaid-svg-JbhdalVOfN9EQi9q .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JbhdalVOfN9EQi9q #aggregationEnd,#mermaid-svg-JbhdalVOfN9EQi9q .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JbhdalVOfN9EQi9q #lollipopStart,#mermaid-svg-JbhdalVOfN9EQi9q .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JbhdalVOfN9EQi9q #lollipopEnd,#mermaid-svg-JbhdalVOfN9EQi9q .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JbhdalVOfN9EQi9q .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-JbhdalVOfN9EQi9q .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-JbhdalVOfN9EQi9q .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-JbhdalVOfN9EQi9q .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-JbhdalVOfN9EQi9q :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} devices
<<interface>>
ResourceManager
+Resource() : spec.ResourceName
+Devices() : Devices
+GetDevicePaths(\[\]string) : \[\]string
+GetPreferredAllocation(available, required, size)(\[\]string, error)
+CheckHealth(stop, unhealthy) : error
+ValidateRequest(AnnotatedIDs) : error
resourceManager
+config *spec.Config
+resource spec.ResourceName
+devices Devices
+Resource() : spec.ResourceName
+Devices() : Devices
+GetDevicePaths(\[\]string) : \[\]string
+GetPreferredAllocation(available, required, size)(\[\]string, error)
+CheckHealth(stop, unhealthy) : error
+ValidateRequest(AnnotatedIDs) : error
+distributedAlloc(available, required, size)(\[\]string, error)
nvmlResourceManager
+nvml nvml.Interface
+GetPreferredAllocation(available, required, size)(\[\]string, error)
+GetDevicePaths(ids) : \[\]string
+CheckHealth(stop, unhealthy) : error
-getPreferredAllocation(available, required, size)(\[\]string, error)
-alignedAlloc(available, required, size)(\[\]string, error)
-checkHealth(stop, devices, unhealthy) : error
-getDevicePlacement(d)(string, uint32, uint32, error)
-getMigDeviceParts(d)(string, uint32, uint32, error)
Device
+ID string
+Health string
+Topology *TopologyInfo
+Paths \[\]string
+Index string
+TotalMemory uint64
+ComputeCapability string
+Replicas int
+IsMigDevice() : bool
+GetUUID() : string
+AlignedAllocationSupported() : bool
<<mapstring*Device>>
Devices
+Contains(ids) : bool
+GetByID(id) : *Device
+GetByIndex(index) : *Device
+Subset(ids) : Devices
+Difference(ods) : Devices
+GetIDs() : \[\]string
+GetUUIDs() : \[\]string
+GetPluginDevices() : \[\]*pluginapi.Device
+GetIndices() : \[\]string
+GetPaths() : \[\]string
+AlignedAllocationSupported() : bool
<<mapResourceNameDevices>>
DeviceMap
+setEntry(name, index, device) : error
+insert(name, dev)
+merge(o DeviceMap)
+isEmpty() : bool
+getIDsOfDevicesToReplicate(r)(\[\]string, error)

2.3 deviceInfo 接口与实现

#mermaid-svg-bQbyZyX5RMjYWI8H{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-bQbyZyX5RMjYWI8H .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bQbyZyX5RMjYWI8H .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bQbyZyX5RMjYWI8H .error-icon{fill:#552222;}#mermaid-svg-bQbyZyX5RMjYWI8H .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bQbyZyX5RMjYWI8H .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bQbyZyX5RMjYWI8H .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bQbyZyX5RMjYWI8H .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bQbyZyX5RMjYWI8H .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bQbyZyX5RMjYWI8H .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bQbyZyX5RMjYWI8H .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bQbyZyX5RMjYWI8H .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bQbyZyX5RMjYWI8H .marker.cross{stroke:#333333;}#mermaid-svg-bQbyZyX5RMjYWI8H svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bQbyZyX5RMjYWI8H p{margin:0;}#mermaid-svg-bQbyZyX5RMjYWI8H g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-bQbyZyX5RMjYWI8H g.classGroup text .title{font-weight:bolder;}#mermaid-svg-bQbyZyX5RMjYWI8H .cluster-label text{fill:#333;}#mermaid-svg-bQbyZyX5RMjYWI8H .cluster-label span{color:#333;}#mermaid-svg-bQbyZyX5RMjYWI8H .cluster-label span p{background-color:transparent;}#mermaid-svg-bQbyZyX5RMjYWI8H .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-bQbyZyX5RMjYWI8H .cluster text{fill:#333;}#mermaid-svg-bQbyZyX5RMjYWI8H .cluster span{color:#333;}#mermaid-svg-bQbyZyX5RMjYWI8H .nodeLabel,#mermaid-svg-bQbyZyX5RMjYWI8H .edgeLabel{color:#131300;}#mermaid-svg-bQbyZyX5RMjYWI8H .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-bQbyZyX5RMjYWI8H .label text{fill:#131300;}#mermaid-svg-bQbyZyX5RMjYWI8H .labelBkg{background:#ECECFF;}#mermaid-svg-bQbyZyX5RMjYWI8H .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-bQbyZyX5RMjYWI8H .classTitle{font-weight:bolder;}#mermaid-svg-bQbyZyX5RMjYWI8H .node rect,#mermaid-svg-bQbyZyX5RMjYWI8H .node circle,#mermaid-svg-bQbyZyX5RMjYWI8H .node ellipse,#mermaid-svg-bQbyZyX5RMjYWI8H .node polygon,#mermaid-svg-bQbyZyX5RMjYWI8H .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bQbyZyX5RMjYWI8H .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-bQbyZyX5RMjYWI8H g.clickable{cursor:pointer;}#mermaid-svg-bQbyZyX5RMjYWI8H g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-bQbyZyX5RMjYWI8H g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-bQbyZyX5RMjYWI8H .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-bQbyZyX5RMjYWI8H .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-bQbyZyX5RMjYWI8H .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-bQbyZyX5RMjYWI8H .dashed-line{stroke-dasharray:3;}#mermaid-svg-bQbyZyX5RMjYWI8H .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-bQbyZyX5RMjYWI8H #compositionStart,#mermaid-svg-bQbyZyX5RMjYWI8H .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bQbyZyX5RMjYWI8H #compositionEnd,#mermaid-svg-bQbyZyX5RMjYWI8H .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bQbyZyX5RMjYWI8H #dependencyStart,#mermaid-svg-bQbyZyX5RMjYWI8H .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bQbyZyX5RMjYWI8H #dependencyStart,#mermaid-svg-bQbyZyX5RMjYWI8H .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bQbyZyX5RMjYWI8H #extensionStart,#mermaid-svg-bQbyZyX5RMjYWI8H .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bQbyZyX5RMjYWI8H #extensionEnd,#mermaid-svg-bQbyZyX5RMjYWI8H .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bQbyZyX5RMjYWI8H #aggregationStart,#mermaid-svg-bQbyZyX5RMjYWI8H .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bQbyZyX5RMjYWI8H #aggregationEnd,#mermaid-svg-bQbyZyX5RMjYWI8H .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bQbyZyX5RMjYWI8H #lollipopStart,#mermaid-svg-bQbyZyX5RMjYWI8H .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bQbyZyX5RMjYWI8H #lollipopEnd,#mermaid-svg-bQbyZyX5RMjYWI8H .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bQbyZyX5RMjYWI8H .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-bQbyZyX5RMjYWI8H .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-bQbyZyX5RMjYWI8H .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-bQbyZyX5RMjYWI8H .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-bQbyZyX5RMjYWI8H :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} <<interface>>
deviceInfo
+GetUUID()(string, error)
+GetPaths()(\[\]string, error)
+GetNumaNode()(bool, int, error)
+GetTotalMemory()(uint64, error)
+GetComputeCapability()(string, error)
nvmlDevice
+nvml.Device
+GetUUID()(string, error)
+GetPaths()(\[\]string, error)
+GetNumaNode()(bool, int, error)
+GetTotalMemory()(uint64, error)
+GetComputeCapability()(string, error)
nvmlMigDevice
+GetUUID()(string, error)
+GetPaths()(\[\]string, error)
+GetNumaNode()(bool, int, error)
+GetTotalMemory()(uint64, error)
+GetComputeCapability()(string, error)
tegraDevice
+GetUUID()(string, error)
+GetPaths()(\[\]string, error)
+GetNumaNode()(bool, int, error)
+GetTotalMemory()(uint64, error)
+GetComputeCapability()(string, error)
wslAllGPUsDevice
+GetUUID()(string, error)
+GetPaths()(\[\]string, error)
+GetNumaNode()(bool, int, error)
+GetTotalMemory()(uint64, error)
+GetComputeCapability()(string, error)

2.4 Manager 创建入口与平台分支

#mermaid-svg-yEPaIMw8lg4puFzH{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-yEPaIMw8lg4puFzH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yEPaIMw8lg4puFzH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yEPaIMw8lg4puFzH .error-icon{fill:#552222;}#mermaid-svg-yEPaIMw8lg4puFzH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yEPaIMw8lg4puFzH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yEPaIMw8lg4puFzH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yEPaIMw8lg4puFzH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yEPaIMw8lg4puFzH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yEPaIMw8lg4puFzH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yEPaIMw8lg4puFzH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yEPaIMw8lg4puFzH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yEPaIMw8lg4puFzH .marker.cross{stroke:#333333;}#mermaid-svg-yEPaIMw8lg4puFzH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yEPaIMw8lg4puFzH p{margin:0;}#mermaid-svg-yEPaIMw8lg4puFzH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yEPaIMw8lg4puFzH .cluster-label text{fill:#333;}#mermaid-svg-yEPaIMw8lg4puFzH .cluster-label span{color:#333;}#mermaid-svg-yEPaIMw8lg4puFzH .cluster-label span p{background-color:transparent;}#mermaid-svg-yEPaIMw8lg4puFzH .label text,#mermaid-svg-yEPaIMw8lg4puFzH span{fill:#333;color:#333;}#mermaid-svg-yEPaIMw8lg4puFzH .node rect,#mermaid-svg-yEPaIMw8lg4puFzH .node circle,#mermaid-svg-yEPaIMw8lg4puFzH .node ellipse,#mermaid-svg-yEPaIMw8lg4puFzH .node polygon,#mermaid-svg-yEPaIMw8lg4puFzH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yEPaIMw8lg4puFzH .rough-node .label text,#mermaid-svg-yEPaIMw8lg4puFzH .node .label text,#mermaid-svg-yEPaIMw8lg4puFzH .image-shape .label,#mermaid-svg-yEPaIMw8lg4puFzH .icon-shape .label{text-anchor:middle;}#mermaid-svg-yEPaIMw8lg4puFzH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yEPaIMw8lg4puFzH .rough-node .label,#mermaid-svg-yEPaIMw8lg4puFzH .node .label,#mermaid-svg-yEPaIMw8lg4puFzH .image-shape .label,#mermaid-svg-yEPaIMw8lg4puFzH .icon-shape .label{text-align:center;}#mermaid-svg-yEPaIMw8lg4puFzH .node.clickable{cursor:pointer;}#mermaid-svg-yEPaIMw8lg4puFzH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yEPaIMw8lg4puFzH .arrowheadPath{fill:#333333;}#mermaid-svg-yEPaIMw8lg4puFzH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yEPaIMw8lg4puFzH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yEPaIMw8lg4puFzH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yEPaIMw8lg4puFzH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yEPaIMw8lg4puFzH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yEPaIMw8lg4puFzH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yEPaIMw8lg4puFzH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yEPaIMw8lg4puFzH .cluster text{fill:#333;}#mermaid-svg-yEPaIMw8lg4puFzH .cluster span{color:#333;}#mermaid-svg-yEPaIMw8lg4puFzH 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-yEPaIMw8lg4puFzH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yEPaIMw8lg4puFzH rect.text{fill:none;stroke-width:0;}#mermaid-svg-yEPaIMw8lg4puFzH .icon-shape,#mermaid-svg-yEPaIMw8lg4puFzH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yEPaIMw8lg4puFzH .icon-shape p,#mermaid-svg-yEPaIMw8lg4puFzH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yEPaIMw8lg4puFzH .icon-shape .label rect,#mermaid-svg-yEPaIMw8lg4puFzH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yEPaIMw8lg4puFzH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yEPaIMw8lg4puFzH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yEPaIMw8lg4puFzH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} NVML
Tegra
WSL


main.go / plugin.go
选择后端平台
NewNVMLResourceManagers
NewTegraResourceManagers
NewNVMLResourceManagers

WSL分支
nvml.Init
ResolvePlatform
NewDeviceMap

devicelib, config, platform
遍历 DeviceMap
platform == WSL?
nvmlResourceManager
基础 resourceManager
\[\]ResourceManager
buildTegraDeviceMap
updateDeviceMapWithReplicas
遍历 DeviceMap
基础 resourceManager
\[\]ResourceManager


三、核心数据类型深度解析

3.1 Device 结构体 (devices.go)

go 复制代码
type Device struct {
    pluginapi.Device          // 嵌入kubelet设备插件API的Device
    Paths             []string // 设备文件路径 (如 /dev/nvidia0)
    Index             string   // 设备索引 (GPU: "0", MIG: "0:1")
    TotalMemory       uint64   // 设备总显存(字节)
    ComputeCapability string   // CUDA算力版本 (如 "8.6")
    Replicas          int      // 副本数 (0或1=非共享, >1=共享)
}

设计意图

  • pluginapi.Device 嵌入提供了 IDHealthTopology 三个字段,这是 kubelet device plugin gRPC 协议必需的
  • Paths 是实际挂载到容器中的设备文件路径列表
  • Index 对 GPU 是数字字符串 "0",对 MIG 设备是 "GPU索引:MIG索引" 格式如 "0:1"
  • Replicas 用于时间分片/MPS共享,表示该设备被复制了多少份
  • ComputeCapability 用于判断是否支持对齐分配

3.2 AnnotatedID 机制 (devices.go)

go 复制代码
type AnnotatedID string  // 格式: "UUID::replica编号"

AnnotatedID 是共享设备的核心机制

  • 原始设备 UUID: GPU-12345678-abcd-...
  • 副本0的 AnnotatedID: GPU-12345678-abcd-...::0
  • 副本1的 AnnotatedID: GPU-12345678-abcd-...::1
go 复制代码
// NewAnnotatedID 创建带副本编号的ID
func NewAnnotatedID(id string, replica int) AnnotatedID {
    return AnnotatedID(fmt.Sprintf("%s::%d", id, replica))
}

// Split 分离出原始ID和副本号
func (r AnnotatedID) Split() (string, int) {
    split := strings.SplitN(string(r), "::", 2)
    if len(split) != 2 {
        return string(r), 0  // 无annotation则返回原始ID和0
    }
    replica, _ := strconv.ParseInt(split[1], 10, 0)
    return split[0], int(replica)
}

关键方法

  • HasAnnotations() --- 判断是否为副本ID(含 :: 分隔符)
  • GetID() --- 提取原始UUID部分
  • AnyHasAnnotations() --- 批量检查中是否有副本

3.3 Devices 集合操作 (devices.go)

Devicesmap[string]*Device,以 Device.ID 为 key。提供集合运算:
#mermaid-svg-PICBmr3t3D2t86EQ{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-PICBmr3t3D2t86EQ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PICBmr3t3D2t86EQ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PICBmr3t3D2t86EQ .error-icon{fill:#552222;}#mermaid-svg-PICBmr3t3D2t86EQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PICBmr3t3D2t86EQ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PICBmr3t3D2t86EQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PICBmr3t3D2t86EQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PICBmr3t3D2t86EQ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PICBmr3t3D2t86EQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PICBmr3t3D2t86EQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PICBmr3t3D2t86EQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PICBmr3t3D2t86EQ .marker.cross{stroke:#333333;}#mermaid-svg-PICBmr3t3D2t86EQ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PICBmr3t3D2t86EQ p{margin:0;}#mermaid-svg-PICBmr3t3D2t86EQ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-PICBmr3t3D2t86EQ .cluster-label text{fill:#333;}#mermaid-svg-PICBmr3t3D2t86EQ .cluster-label span{color:#333;}#mermaid-svg-PICBmr3t3D2t86EQ .cluster-label span p{background-color:transparent;}#mermaid-svg-PICBmr3t3D2t86EQ .label text,#mermaid-svg-PICBmr3t3D2t86EQ span{fill:#333;color:#333;}#mermaid-svg-PICBmr3t3D2t86EQ .node rect,#mermaid-svg-PICBmr3t3D2t86EQ .node circle,#mermaid-svg-PICBmr3t3D2t86EQ .node ellipse,#mermaid-svg-PICBmr3t3D2t86EQ .node polygon,#mermaid-svg-PICBmr3t3D2t86EQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-PICBmr3t3D2t86EQ .rough-node .label text,#mermaid-svg-PICBmr3t3D2t86EQ .node .label text,#mermaid-svg-PICBmr3t3D2t86EQ .image-shape .label,#mermaid-svg-PICBmr3t3D2t86EQ .icon-shape .label{text-anchor:middle;}#mermaid-svg-PICBmr3t3D2t86EQ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-PICBmr3t3D2t86EQ .rough-node .label,#mermaid-svg-PICBmr3t3D2t86EQ .node .label,#mermaid-svg-PICBmr3t3D2t86EQ .image-shape .label,#mermaid-svg-PICBmr3t3D2t86EQ .icon-shape .label{text-align:center;}#mermaid-svg-PICBmr3t3D2t86EQ .node.clickable{cursor:pointer;}#mermaid-svg-PICBmr3t3D2t86EQ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-PICBmr3t3D2t86EQ .arrowheadPath{fill:#333333;}#mermaid-svg-PICBmr3t3D2t86EQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-PICBmr3t3D2t86EQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-PICBmr3t3D2t86EQ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PICBmr3t3D2t86EQ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-PICBmr3t3D2t86EQ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PICBmr3t3D2t86EQ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-PICBmr3t3D2t86EQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-PICBmr3t3D2t86EQ .cluster text{fill:#333;}#mermaid-svg-PICBmr3t3D2t86EQ .cluster span{color:#333;}#mermaid-svg-PICBmr3t3D2t86EQ 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-PICBmr3t3D2t86EQ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-PICBmr3t3D2t86EQ rect.text{fill:none;stroke-width:0;}#mermaid-svg-PICBmr3t3D2t86EQ .icon-shape,#mermaid-svg-PICBmr3t3D2t86EQ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PICBmr3t3D2t86EQ .icon-shape p,#mermaid-svg-PICBmr3t3D2t86EQ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-PICBmr3t3D2t86EQ .icon-shape .label rect,#mermaid-svg-PICBmr3t3D2t86EQ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PICBmr3t3D2t86EQ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-PICBmr3t3D2t86EQ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-PICBmr3t3D2t86EQ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Devices集合操作
判断包含
子集提取
差集
按ID查找
按Index查找
Contains
所有id都存在→true
Subset
按id列表筛选
Difference
在ds但不在ods
GetByID
map直查 O(1)
GetByIndex
遍历 O(n)

3.4 DeviceMap (device_map.go)

go 复制代码
type DeviceMap map[spec.ResourceName]Devices

将设备按 Kubernetes 资源名(如 nvidia.com/gpunvidia.com/mig-1g.10gb)分组存储。


四、核心业务逻辑深度解析

4.1 设备发现与映射流程

4.1.1 NVML 后端入口: NewNVMLResourceManagers (nvml_manager.go)

#mermaid-svg-uBajKPAQF8kIBvpd{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-uBajKPAQF8kIBvpd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uBajKPAQF8kIBvpd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uBajKPAQF8kIBvpd .error-icon{fill:#552222;}#mermaid-svg-uBajKPAQF8kIBvpd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uBajKPAQF8kIBvpd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uBajKPAQF8kIBvpd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uBajKPAQF8kIBvpd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uBajKPAQF8kIBvpd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uBajKPAQF8kIBvpd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uBajKPAQF8kIBvpd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uBajKPAQF8kIBvpd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uBajKPAQF8kIBvpd .marker.cross{stroke:#333333;}#mermaid-svg-uBajKPAQF8kIBvpd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uBajKPAQF8kIBvpd p{margin:0;}#mermaid-svg-uBajKPAQF8kIBvpd .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uBajKPAQF8kIBvpd .cluster-label text{fill:#333;}#mermaid-svg-uBajKPAQF8kIBvpd .cluster-label span{color:#333;}#mermaid-svg-uBajKPAQF8kIBvpd .cluster-label span p{background-color:transparent;}#mermaid-svg-uBajKPAQF8kIBvpd .label text,#mermaid-svg-uBajKPAQF8kIBvpd span{fill:#333;color:#333;}#mermaid-svg-uBajKPAQF8kIBvpd .node rect,#mermaid-svg-uBajKPAQF8kIBvpd .node circle,#mermaid-svg-uBajKPAQF8kIBvpd .node ellipse,#mermaid-svg-uBajKPAQF8kIBvpd .node polygon,#mermaid-svg-uBajKPAQF8kIBvpd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uBajKPAQF8kIBvpd .rough-node .label text,#mermaid-svg-uBajKPAQF8kIBvpd .node .label text,#mermaid-svg-uBajKPAQF8kIBvpd .image-shape .label,#mermaid-svg-uBajKPAQF8kIBvpd .icon-shape .label{text-anchor:middle;}#mermaid-svg-uBajKPAQF8kIBvpd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uBajKPAQF8kIBvpd .rough-node .label,#mermaid-svg-uBajKPAQF8kIBvpd .node .label,#mermaid-svg-uBajKPAQF8kIBvpd .image-shape .label,#mermaid-svg-uBajKPAQF8kIBvpd .icon-shape .label{text-align:center;}#mermaid-svg-uBajKPAQF8kIBvpd .node.clickable{cursor:pointer;}#mermaid-svg-uBajKPAQF8kIBvpd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uBajKPAQF8kIBvpd .arrowheadPath{fill:#333333;}#mermaid-svg-uBajKPAQF8kIBvpd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uBajKPAQF8kIBvpd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uBajKPAQF8kIBvpd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uBajKPAQF8kIBvpd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uBajKPAQF8kIBvpd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uBajKPAQF8kIBvpd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uBajKPAQF8kIBvpd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uBajKPAQF8kIBvpd .cluster text{fill:#333;}#mermaid-svg-uBajKPAQF8kIBvpd .cluster span{color:#333;}#mermaid-svg-uBajKPAQF8kIBvpd 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-uBajKPAQF8kIBvpd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uBajKPAQF8kIBvpd rect.text{fill:none;stroke-width:0;}#mermaid-svg-uBajKPAQF8kIBvpd .icon-shape,#mermaid-svg-uBajKPAQF8kIBvpd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uBajKPAQF8kIBvpd .icon-shape p,#mermaid-svg-uBajKPAQF8kIBvpd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uBajKPAQF8kIBvpd .icon-shape .label rect,#mermaid-svg-uBajKPAQF8kIBvpd .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uBajKPAQF8kIBvpd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uBajKPAQF8kIBvpd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uBajKPAQF8kIBvpd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 失败
成功




遍历完成
NewNVMLResourceManagers(infolib, nvmllib, devicelib, config)
nvmllib.Init()
return error
defer nvmllib.Shutdown()
infolib.ResolvePlatform()
NewDeviceMap(devicelib, config, platform)
遍历 deviceMap
len(devices)==0?
创建 resourceManager{config, resource, devices}
platform == WSL?
包装为 nvmlResourceManager{resourceManager, nvml}
使用基础 resourceManager
append到\[\]ResourceManager
return \[\]ResourceManager

逐行解析

go 复制代码
func NewNVMLResourceManagers(infolib info.Interface, nvmllib nvml.Interface,
    devicelib device.Interface, config *spec.Config) ([]ResourceManager, error) {
    // 初始化NVML库------这是与NVIDIA驱动通信的入口
    ret := nvmllib.Init()
    if ret != nvml.SUCCESS {
        return nil, fmt.Errorf("failed to initialize NVML: %v", ret)
    }
    // defer确保函数退出前关闭NVML连接
    defer func() {
        ret := nvmllib.Shutdown()
        if ret != nvml.SUCCESS {
            klog.Infof("Error shutting down NVML: %v", ret)
        }
    }()

    // 解析平台类型: NVML / WSL / Tegra
    platform := infolib.ResolvePlatform()

    // 构建设备映射表------核心步骤
    deviceMap, err := NewDeviceMap(devicelib, config, platform)
    if err != nil {
        return nil, fmt.Errorf("error building device map: %v", err)
    }

    // 为每个资源名创建一个ResourceManager实例
    var rms []ResourceManager
    for resourceName, devices := range deviceMap {
        if len(devices) == 0 {
            continue  // 跳过空资源
        }
        resources := resourceManager{
            config:   config,
            resource: resourceName,
            devices:  devices,
        }

        var rm ResourceManager
        switch platform {
        case info.PlatformWSL:
            // WSL平台使用基础resourceManager(无健康检查、无对齐分配)
            rm = &resources
        default:
            // NVML平台使用nvmlResourceManager(有健康检查、对齐分配)
            rm = &nvmlResourceManager{
                resourceManager: resources,
                nvml:            nvmllib,
            }
        }
        rms = append(rms, rm)
    }
    return rms, nil
}
4.1.2 DeviceMap 构建: NewDeviceMap (device_map.go)

#mermaid-svg-4AFr0onQSuhpcnV2{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-4AFr0onQSuhpcnV2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4AFr0onQSuhpcnV2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4AFr0onQSuhpcnV2 .error-icon{fill:#552222;}#mermaid-svg-4AFr0onQSuhpcnV2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4AFr0onQSuhpcnV2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4AFr0onQSuhpcnV2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4AFr0onQSuhpcnV2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4AFr0onQSuhpcnV2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4AFr0onQSuhpcnV2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4AFr0onQSuhpcnV2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4AFr0onQSuhpcnV2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4AFr0onQSuhpcnV2 .marker.cross{stroke:#333333;}#mermaid-svg-4AFr0onQSuhpcnV2 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4AFr0onQSuhpcnV2 p{margin:0;}#mermaid-svg-4AFr0onQSuhpcnV2 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-4AFr0onQSuhpcnV2 .cluster-label text{fill:#333;}#mermaid-svg-4AFr0onQSuhpcnV2 .cluster-label span{color:#333;}#mermaid-svg-4AFr0onQSuhpcnV2 .cluster-label span p{background-color:transparent;}#mermaid-svg-4AFr0onQSuhpcnV2 .label text,#mermaid-svg-4AFr0onQSuhpcnV2 span{fill:#333;color:#333;}#mermaid-svg-4AFr0onQSuhpcnV2 .node rect,#mermaid-svg-4AFr0onQSuhpcnV2 .node circle,#mermaid-svg-4AFr0onQSuhpcnV2 .node ellipse,#mermaid-svg-4AFr0onQSuhpcnV2 .node polygon,#mermaid-svg-4AFr0onQSuhpcnV2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4AFr0onQSuhpcnV2 .rough-node .label text,#mermaid-svg-4AFr0onQSuhpcnV2 .node .label text,#mermaid-svg-4AFr0onQSuhpcnV2 .image-shape .label,#mermaid-svg-4AFr0onQSuhpcnV2 .icon-shape .label{text-anchor:middle;}#mermaid-svg-4AFr0onQSuhpcnV2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-4AFr0onQSuhpcnV2 .rough-node .label,#mermaid-svg-4AFr0onQSuhpcnV2 .node .label,#mermaid-svg-4AFr0onQSuhpcnV2 .image-shape .label,#mermaid-svg-4AFr0onQSuhpcnV2 .icon-shape .label{text-align:center;}#mermaid-svg-4AFr0onQSuhpcnV2 .node.clickable{cursor:pointer;}#mermaid-svg-4AFr0onQSuhpcnV2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-4AFr0onQSuhpcnV2 .arrowheadPath{fill:#333333;}#mermaid-svg-4AFr0onQSuhpcnV2 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-4AFr0onQSuhpcnV2 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-4AFr0onQSuhpcnV2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4AFr0onQSuhpcnV2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-4AFr0onQSuhpcnV2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4AFr0onQSuhpcnV2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-4AFr0onQSuhpcnV2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-4AFr0onQSuhpcnV2 .cluster text{fill:#333;}#mermaid-svg-4AFr0onQSuhpcnV2 .cluster span{color:#333;}#mermaid-svg-4AFr0onQSuhpcnV2 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-4AFr0onQSuhpcnV2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-4AFr0onQSuhpcnV2 rect.text{fill:none;stroke-width:0;}#mermaid-svg-4AFr0onQSuhpcnV2 .icon-shape,#mermaid-svg-4AFr0onQSuhpcnV2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4AFr0onQSuhpcnV2 .icon-shape p,#mermaid-svg-4AFr0onQSuhpcnV2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-4AFr0onQSuhpcnV2 .icon-shape .label rect,#mermaid-svg-4AFr0onQSuhpcnV2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4AFr0onQSuhpcnV2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-4AFr0onQSuhpcnV2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-4AFr0onQSuhpcnV2 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

NewDeviceMap(devicelib, config, platform)
platform == WSL?
newGPUDevice = newWslAllGPUsDevice
newGPUDevice = newNvmlGPUDevice
创建 deviceMapBuilder
b.build()
buildDeviceMapFromConfigResources()
updateDeviceMapWithReplicas()
return DeviceMap

deviceMapBuilder 结构

go 复制代码
type deviceMapBuilder struct {
    device.Interface                    // go-nvlib设备操作接口
    migStrategy         *string         // MIG策略: none/single/mixed
    resources           *spec.Resources // 资源匹配规则
    replicatedResources *spec.ReplicatedResources // 共享副本配置
    newGPUDevice func(i int, gpu nvml.Device) (string, deviceInfo) // GPU设备工厂函数
}

build() 核心流程

go 复制代码
func (b *deviceMapBuilder) build() (DeviceMap, error) {
    // 第一步:从config.Resources构建基础设备映射
    devices, err := b.buildDeviceMapFromConfigResources()
    // 第二步:根据共享配置添加副本
    devices, err = updateDeviceMapWithReplicas(b.replicatedResources, devices)
    return devices, nil
}
4.1.3 GPU 设备映射构建: buildGPUDeviceMap

#mermaid-svg-GNOq9YHtN2PuP5yd{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-GNOq9YHtN2PuP5yd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GNOq9YHtN2PuP5yd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GNOq9YHtN2PuP5yd .error-icon{fill:#552222;}#mermaid-svg-GNOq9YHtN2PuP5yd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GNOq9YHtN2PuP5yd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GNOq9YHtN2PuP5yd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GNOq9YHtN2PuP5yd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GNOq9YHtN2PuP5yd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GNOq9YHtN2PuP5yd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GNOq9YHtN2PuP5yd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GNOq9YHtN2PuP5yd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GNOq9YHtN2PuP5yd .marker.cross{stroke:#333333;}#mermaid-svg-GNOq9YHtN2PuP5yd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GNOq9YHtN2PuP5yd p{margin:0;}#mermaid-svg-GNOq9YHtN2PuP5yd .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-GNOq9YHtN2PuP5yd .cluster-label text{fill:#333;}#mermaid-svg-GNOq9YHtN2PuP5yd .cluster-label span{color:#333;}#mermaid-svg-GNOq9YHtN2PuP5yd .cluster-label span p{background-color:transparent;}#mermaid-svg-GNOq9YHtN2PuP5yd .label text,#mermaid-svg-GNOq9YHtN2PuP5yd span{fill:#333;color:#333;}#mermaid-svg-GNOq9YHtN2PuP5yd .node rect,#mermaid-svg-GNOq9YHtN2PuP5yd .node circle,#mermaid-svg-GNOq9YHtN2PuP5yd .node ellipse,#mermaid-svg-GNOq9YHtN2PuP5yd .node polygon,#mermaid-svg-GNOq9YHtN2PuP5yd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GNOq9YHtN2PuP5yd .rough-node .label text,#mermaid-svg-GNOq9YHtN2PuP5yd .node .label text,#mermaid-svg-GNOq9YHtN2PuP5yd .image-shape .label,#mermaid-svg-GNOq9YHtN2PuP5yd .icon-shape .label{text-anchor:middle;}#mermaid-svg-GNOq9YHtN2PuP5yd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GNOq9YHtN2PuP5yd .rough-node .label,#mermaid-svg-GNOq9YHtN2PuP5yd .node .label,#mermaid-svg-GNOq9YHtN2PuP5yd .image-shape .label,#mermaid-svg-GNOq9YHtN2PuP5yd .icon-shape .label{text-align:center;}#mermaid-svg-GNOq9YHtN2PuP5yd .node.clickable{cursor:pointer;}#mermaid-svg-GNOq9YHtN2PuP5yd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GNOq9YHtN2PuP5yd .arrowheadPath{fill:#333333;}#mermaid-svg-GNOq9YHtN2PuP5yd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GNOq9YHtN2PuP5yd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GNOq9YHtN2PuP5yd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GNOq9YHtN2PuP5yd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GNOq9YHtN2PuP5yd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GNOq9YHtN2PuP5yd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GNOq9YHtN2PuP5yd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GNOq9YHtN2PuP5yd .cluster text{fill:#333;}#mermaid-svg-GNOq9YHtN2PuP5yd .cluster span{color:#333;}#mermaid-svg-GNOq9YHtN2PuP5yd 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-GNOq9YHtN2PuP5yd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GNOq9YHtN2PuP5yd rect.text{fill:none;stroke-width:0;}#mermaid-svg-GNOq9YHtN2PuP5yd .icon-shape,#mermaid-svg-GNOq9YHtN2PuP5yd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GNOq9YHtN2PuP5yd .icon-shape p,#mermaid-svg-GNOq9YHtN2PuP5yd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GNOq9YHtN2PuP5yd .icon-shape .label rect,#mermaid-svg-GNOq9YHtN2PuP5yd .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GNOq9YHtN2PuP5yd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GNOq9YHtN2PuP5yd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GNOq9YHtN2PuP5yd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是



buildGPUDeviceMap()
VisitDevices回调
gpu.GetName() 获取GPU名称
gpu.IsMigEnabled() 检查MIG状态
MIG已启用且策略≠none?
跳过该GPU(return nil)
遍历 resources.GPUs 匹配规则
resource.Pattern.Matches(name)?
newGPUDevice(i, gpu) 创建deviceInfo
devices.setEntry(resourceName, index, info)
return error: 不匹配任何模式
继续下一个GPU

逐行解析

go 复制代码
func (b *deviceMapBuilder) buildGPUDeviceMap() (DeviceMap, error) {
    devices := make(DeviceMap)

    err := b.VisitDevices(func(i int, gpu device.Device) error {
        // 获取GPU产品名称用于模式匹配
        name, ret := gpu.GetName()
        if ret != nvml.SUCCESS {
            return fmt.Errorf("error getting product name for GPU: %v", ret)
        }
        // 检查MIG是否启用------如果启用了MIG且策略不是none,
        // 则该GPU在MIG设备映射中处理,这里跳过
        migEnabled, err := gpu.IsMigEnabled()
        if err != nil {
            return fmt.Errorf("error checking if MIG is enabled on GPU: %v", err)
        }
        if migEnabled && *b.migStrategy != spec.MigStrategyNone {
            return nil  // 跳过,由buildMigDeviceMap处理
        }
        // 遍历配置中的GPU资源规则,按名称模式匹配
        for _, resource := range b.resources.GPUs {
            if resource.Pattern.Matches(name) {
                index, info := b.newGPUDevice(i, gpu)
                return devices.setEntry(resource.Name, index, info)
            }
        }
        return fmt.Errorf("GPU name '%v' does not match any resource patterns", name)
    })
    return devices, err
}
4.1.4 MIG 设备映射构建: buildMigDeviceMap

#mermaid-svg-xdfIARjOTEzLGCj0{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-xdfIARjOTEzLGCj0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xdfIARjOTEzLGCj0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xdfIARjOTEzLGCj0 .error-icon{fill:#552222;}#mermaid-svg-xdfIARjOTEzLGCj0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xdfIARjOTEzLGCj0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xdfIARjOTEzLGCj0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xdfIARjOTEzLGCj0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xdfIARjOTEzLGCj0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xdfIARjOTEzLGCj0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xdfIARjOTEzLGCj0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xdfIARjOTEzLGCj0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xdfIARjOTEzLGCj0 .marker.cross{stroke:#333333;}#mermaid-svg-xdfIARjOTEzLGCj0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xdfIARjOTEzLGCj0 p{margin:0;}#mermaid-svg-xdfIARjOTEzLGCj0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xdfIARjOTEzLGCj0 .cluster-label text{fill:#333;}#mermaid-svg-xdfIARjOTEzLGCj0 .cluster-label span{color:#333;}#mermaid-svg-xdfIARjOTEzLGCj0 .cluster-label span p{background-color:transparent;}#mermaid-svg-xdfIARjOTEzLGCj0 .label text,#mermaid-svg-xdfIARjOTEzLGCj0 span{fill:#333;color:#333;}#mermaid-svg-xdfIARjOTEzLGCj0 .node rect,#mermaid-svg-xdfIARjOTEzLGCj0 .node circle,#mermaid-svg-xdfIARjOTEzLGCj0 .node ellipse,#mermaid-svg-xdfIARjOTEzLGCj0 .node polygon,#mermaid-svg-xdfIARjOTEzLGCj0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xdfIARjOTEzLGCj0 .rough-node .label text,#mermaid-svg-xdfIARjOTEzLGCj0 .node .label text,#mermaid-svg-xdfIARjOTEzLGCj0 .image-shape .label,#mermaid-svg-xdfIARjOTEzLGCj0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-xdfIARjOTEzLGCj0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xdfIARjOTEzLGCj0 .rough-node .label,#mermaid-svg-xdfIARjOTEzLGCj0 .node .label,#mermaid-svg-xdfIARjOTEzLGCj0 .image-shape .label,#mermaid-svg-xdfIARjOTEzLGCj0 .icon-shape .label{text-align:center;}#mermaid-svg-xdfIARjOTEzLGCj0 .node.clickable{cursor:pointer;}#mermaid-svg-xdfIARjOTEzLGCj0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xdfIARjOTEzLGCj0 .arrowheadPath{fill:#333333;}#mermaid-svg-xdfIARjOTEzLGCj0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xdfIARjOTEzLGCj0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xdfIARjOTEzLGCj0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xdfIARjOTEzLGCj0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xdfIARjOTEzLGCj0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xdfIARjOTEzLGCj0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xdfIARjOTEzLGCj0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xdfIARjOTEzLGCj0 .cluster text{fill:#333;}#mermaid-svg-xdfIARjOTEzLGCj0 .cluster span{color:#333;}#mermaid-svg-xdfIARjOTEzLGCj0 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-xdfIARjOTEzLGCj0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xdfIARjOTEzLGCj0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-xdfIARjOTEzLGCj0 .icon-shape,#mermaid-svg-xdfIARjOTEzLGCj0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xdfIARjOTEzLGCj0 .icon-shape p,#mermaid-svg-xdfIARjOTEzLGCj0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xdfIARjOTEzLGCj0 .icon-shape .label rect,#mermaid-svg-xdfIARjOTEzLGCj0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xdfIARjOTEzLGCj0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xdfIARjOTEzLGCj0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xdfIARjOTEzLGCj0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

buildMigDeviceMap()
VisitMigDevices回调

(i=GPU索引, j=MIG索引)
mig.GetProfile() 获取MIG配置文件
遍历 resources.MIGs 匹配规则
resource.Pattern.Matches(profile)?
newMigDevice(i, j, mig)

index = 'i:j'
devices.setEntry(resourceName, index, info)
return error: 不匹配
继续下一个MIG设备

4.1.5 MIG 校验: assertAllMigDevicesAreValid

#mermaid-svg-G6SLUAMm1ouktjRP{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-G6SLUAMm1ouktjRP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-G6SLUAMm1ouktjRP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-G6SLUAMm1ouktjRP .error-icon{fill:#552222;}#mermaid-svg-G6SLUAMm1ouktjRP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-G6SLUAMm1ouktjRP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-G6SLUAMm1ouktjRP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-G6SLUAMm1ouktjRP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-G6SLUAMm1ouktjRP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-G6SLUAMm1ouktjRP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-G6SLUAMm1ouktjRP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-G6SLUAMm1ouktjRP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-G6SLUAMm1ouktjRP .marker.cross{stroke:#333333;}#mermaid-svg-G6SLUAMm1ouktjRP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-G6SLUAMm1ouktjRP p{margin:0;}#mermaid-svg-G6SLUAMm1ouktjRP .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-G6SLUAMm1ouktjRP .cluster-label text{fill:#333;}#mermaid-svg-G6SLUAMm1ouktjRP .cluster-label span{color:#333;}#mermaid-svg-G6SLUAMm1ouktjRP .cluster-label span p{background-color:transparent;}#mermaid-svg-G6SLUAMm1ouktjRP .label text,#mermaid-svg-G6SLUAMm1ouktjRP span{fill:#333;color:#333;}#mermaid-svg-G6SLUAMm1ouktjRP .node rect,#mermaid-svg-G6SLUAMm1ouktjRP .node circle,#mermaid-svg-G6SLUAMm1ouktjRP .node ellipse,#mermaid-svg-G6SLUAMm1ouktjRP .node polygon,#mermaid-svg-G6SLUAMm1ouktjRP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-G6SLUAMm1ouktjRP .rough-node .label text,#mermaid-svg-G6SLUAMm1ouktjRP .node .label text,#mermaid-svg-G6SLUAMm1ouktjRP .image-shape .label,#mermaid-svg-G6SLUAMm1ouktjRP .icon-shape .label{text-anchor:middle;}#mermaid-svg-G6SLUAMm1ouktjRP .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-G6SLUAMm1ouktjRP .rough-node .label,#mermaid-svg-G6SLUAMm1ouktjRP .node .label,#mermaid-svg-G6SLUAMm1ouktjRP .image-shape .label,#mermaid-svg-G6SLUAMm1ouktjRP .icon-shape .label{text-align:center;}#mermaid-svg-G6SLUAMm1ouktjRP .node.clickable{cursor:pointer;}#mermaid-svg-G6SLUAMm1ouktjRP .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-G6SLUAMm1ouktjRP .arrowheadPath{fill:#333333;}#mermaid-svg-G6SLUAMm1ouktjRP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-G6SLUAMm1ouktjRP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-G6SLUAMm1ouktjRP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-G6SLUAMm1ouktjRP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-G6SLUAMm1ouktjRP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-G6SLUAMm1ouktjRP .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-G6SLUAMm1ouktjRP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-G6SLUAMm1ouktjRP .cluster text{fill:#333;}#mermaid-svg-G6SLUAMm1ouktjRP .cluster span{color:#333;}#mermaid-svg-G6SLUAMm1ouktjRP 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-G6SLUAMm1ouktjRP .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-G6SLUAMm1ouktjRP rect.text{fill:none;stroke-width:0;}#mermaid-svg-G6SLUAMm1ouktjRP .icon-shape,#mermaid-svg-G6SLUAMm1ouktjRP .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-G6SLUAMm1ouktjRP .icon-shape p,#mermaid-svg-G6SLUAMm1ouktjRP .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-G6SLUAMm1ouktjRP .icon-shape .label rect,#mermaid-svg-G6SLUAMm1ouktjRP .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-G6SLUAMm1ouktjRP .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-G6SLUAMm1ouktjRP .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-G6SLUAMm1ouktjRP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否









assertAllMigDevicesAreValid(uniform)
VisitDevices回调
d.IsMigEnabled()
MIG已启用?
d.GetMigDevices()
len(migDevices)==0?
uniform?
return error: 未配置MIG设备
klog.Warning 警告
uniform?
return nil
VisitMigDevices: 检查所有MIG设备属性一致
attrs != previousAttributes?
return error: 多种MIG设备类型

设计意图

  • uniform=true(MigStrategySingle)要求所有MIG设备类型完全一致
  • uniform=false(MigStrategyMixed)允许不同类型的MIG设备共存
4.1.6 副本管理: updateDeviceMapWithReplicas

#mermaid-svg-a4M87wPwCZinECl3{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-a4M87wPwCZinECl3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-a4M87wPwCZinECl3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-a4M87wPwCZinECl3 .error-icon{fill:#552222;}#mermaid-svg-a4M87wPwCZinECl3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-a4M87wPwCZinECl3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-a4M87wPwCZinECl3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-a4M87wPwCZinECl3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-a4M87wPwCZinECl3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-a4M87wPwCZinECl3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-a4M87wPwCZinECl3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-a4M87wPwCZinECl3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-a4M87wPwCZinECl3 .marker.cross{stroke:#333333;}#mermaid-svg-a4M87wPwCZinECl3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-a4M87wPwCZinECl3 p{margin:0;}#mermaid-svg-a4M87wPwCZinECl3 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-a4M87wPwCZinECl3 .cluster-label text{fill:#333;}#mermaid-svg-a4M87wPwCZinECl3 .cluster-label span{color:#333;}#mermaid-svg-a4M87wPwCZinECl3 .cluster-label span p{background-color:transparent;}#mermaid-svg-a4M87wPwCZinECl3 .label text,#mermaid-svg-a4M87wPwCZinECl3 span{fill:#333;color:#333;}#mermaid-svg-a4M87wPwCZinECl3 .node rect,#mermaid-svg-a4M87wPwCZinECl3 .node circle,#mermaid-svg-a4M87wPwCZinECl3 .node ellipse,#mermaid-svg-a4M87wPwCZinECl3 .node polygon,#mermaid-svg-a4M87wPwCZinECl3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-a4M87wPwCZinECl3 .rough-node .label text,#mermaid-svg-a4M87wPwCZinECl3 .node .label text,#mermaid-svg-a4M87wPwCZinECl3 .image-shape .label,#mermaid-svg-a4M87wPwCZinECl3 .icon-shape .label{text-anchor:middle;}#mermaid-svg-a4M87wPwCZinECl3 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-a4M87wPwCZinECl3 .rough-node .label,#mermaid-svg-a4M87wPwCZinECl3 .node .label,#mermaid-svg-a4M87wPwCZinECl3 .image-shape .label,#mermaid-svg-a4M87wPwCZinECl3 .icon-shape .label{text-align:center;}#mermaid-svg-a4M87wPwCZinECl3 .node.clickable{cursor:pointer;}#mermaid-svg-a4M87wPwCZinECl3 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-a4M87wPwCZinECl3 .arrowheadPath{fill:#333333;}#mermaid-svg-a4M87wPwCZinECl3 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-a4M87wPwCZinECl3 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-a4M87wPwCZinECl3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-a4M87wPwCZinECl3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-a4M87wPwCZinECl3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-a4M87wPwCZinECl3 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-a4M87wPwCZinECl3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-a4M87wPwCZinECl3 .cluster text{fill:#333;}#mermaid-svg-a4M87wPwCZinECl3 .cluster span{color:#333;}#mermaid-svg-a4M87wPwCZinECl3 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-a4M87wPwCZinECl3 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-a4M87wPwCZinECl3 rect.text{fill:none;stroke-width:0;}#mermaid-svg-a4M87wPwCZinECl3 .icon-shape,#mermaid-svg-a4M87wPwCZinECl3 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-a4M87wPwCZinECl3 .icon-shape p,#mermaid-svg-a4M87wPwCZinECl3 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-a4M87wPwCZinECl3 .icon-shape .label rect,#mermaid-svg-a4M87wPwCZinECl3 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-a4M87wPwCZinECl3 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-a4M87wPwCZinECl3 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-a4M87wPwCZinECl3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否



完成
完成
updateDeviceMapWithReplicas

(replicatedResources, oDevices)
构建replicated资源名集合
复制非副本资源设备
遍历 replicatedResources.Resources
getIDsOfDevicesToReplicate(r)
有设备要复制?
添加非副本设备到devices
r.Rename非空?
name = r.Rename
name = r.Name
为每个设备创建r.Replicas个副本
annotatedID = NewAnnotatedID(id, i)
创建replicatedDevice

复用原设备的Paths/Index/Memory等
devices.insert(name, replicatedDevice)
return devices

副本设备创建详解

go 复制代码
for _, id := range ids {
    for i := 0; i < r.Replicas; i++ {
        annotatedID := string(NewAnnotatedID(id, i))
        original := oDevices[r.Name][id]
        replicatedDevice := Device{
            Device: pluginapi.Device{
                ID:       annotatedID,  // 带副本编号的ID
                Health:   original.Health,
                Topology: original.Topology,  // 继承NUMA拓扑
            },
            Paths:             original.Paths,             // 共享相同的设备路径
            Index:             original.Index,             // 相同的GPU索引
            TotalMemory:       original.TotalMemory,       // 相同显存
            ComputeCapability: original.ComputeCapability, // 相同算力
            Replicas:          r.Replicas,                 // 记录总副本数
        }
        devices.insert(name, &replicatedDevice)
    }
}

关键设计 :副本设备共享同一物理设备的路径和属性,仅ID不同(带::replica后缀)。这使得kubelet认为有多个设备可用,实现时间分片共享。

4.1.7 getIDsOfDevicesToReplicate 选择复制设备

#mermaid-svg-j0TtREiIlxKuy97i{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-j0TtREiIlxKuy97i .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-j0TtREiIlxKuy97i .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-j0TtREiIlxKuy97i .error-icon{fill:#552222;}#mermaid-svg-j0TtREiIlxKuy97i .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-j0TtREiIlxKuy97i .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-j0TtREiIlxKuy97i .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-j0TtREiIlxKuy97i .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-j0TtREiIlxKuy97i .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-j0TtREiIlxKuy97i .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-j0TtREiIlxKuy97i .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-j0TtREiIlxKuy97i .marker{fill:#333333;stroke:#333333;}#mermaid-svg-j0TtREiIlxKuy97i .marker.cross{stroke:#333333;}#mermaid-svg-j0TtREiIlxKuy97i svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-j0TtREiIlxKuy97i p{margin:0;}#mermaid-svg-j0TtREiIlxKuy97i .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-j0TtREiIlxKuy97i .cluster-label text{fill:#333;}#mermaid-svg-j0TtREiIlxKuy97i .cluster-label span{color:#333;}#mermaid-svg-j0TtREiIlxKuy97i .cluster-label span p{background-color:transparent;}#mermaid-svg-j0TtREiIlxKuy97i .label text,#mermaid-svg-j0TtREiIlxKuy97i span{fill:#333;color:#333;}#mermaid-svg-j0TtREiIlxKuy97i .node rect,#mermaid-svg-j0TtREiIlxKuy97i .node circle,#mermaid-svg-j0TtREiIlxKuy97i .node ellipse,#mermaid-svg-j0TtREiIlxKuy97i .node polygon,#mermaid-svg-j0TtREiIlxKuy97i .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-j0TtREiIlxKuy97i .rough-node .label text,#mermaid-svg-j0TtREiIlxKuy97i .node .label text,#mermaid-svg-j0TtREiIlxKuy97i .image-shape .label,#mermaid-svg-j0TtREiIlxKuy97i .icon-shape .label{text-anchor:middle;}#mermaid-svg-j0TtREiIlxKuy97i .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-j0TtREiIlxKuy97i .rough-node .label,#mermaid-svg-j0TtREiIlxKuy97i .node .label,#mermaid-svg-j0TtREiIlxKuy97i .image-shape .label,#mermaid-svg-j0TtREiIlxKuy97i .icon-shape .label{text-align:center;}#mermaid-svg-j0TtREiIlxKuy97i .node.clickable{cursor:pointer;}#mermaid-svg-j0TtREiIlxKuy97i .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-j0TtREiIlxKuy97i .arrowheadPath{fill:#333333;}#mermaid-svg-j0TtREiIlxKuy97i .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-j0TtREiIlxKuy97i .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-j0TtREiIlxKuy97i .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-j0TtREiIlxKuy97i .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-j0TtREiIlxKuy97i .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-j0TtREiIlxKuy97i .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-j0TtREiIlxKuy97i .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-j0TtREiIlxKuy97i .cluster text{fill:#333;}#mermaid-svg-j0TtREiIlxKuy97i .cluster span{color:#333;}#mermaid-svg-j0TtREiIlxKuy97i 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-j0TtREiIlxKuy97i .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-j0TtREiIlxKuy97i rect.text{fill:none;stroke-width:0;}#mermaid-svg-j0TtREiIlxKuy97i .icon-shape,#mermaid-svg-j0TtREiIlxKuy97i .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-j0TtREiIlxKuy97i .icon-shape p,#mermaid-svg-j0TtREiIlxKuy97i .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-j0TtREiIlxKuy97i .icon-shape .label rect,#mermaid-svg-j0TtREiIlxKuy97i .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-j0TtREiIlxKuy97i .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-j0TtREiIlxKuy97i .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-j0TtREiIlxKuy97i :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是


失败
成功



未找到


未找到

getIDsOfDevicesToReplicate(r)
r.Devices.All?
return 所有设备ID
r.Devices.Count > 0?
检查Count≤总设备数
return error
return 前Count个设备ID
r.Devices.List非空?
遍历List
ref.IsUUID()?
GetByID查找
return error
ref.IsGPUIndex()或IsMigIndex()?
GetByIndex查找
return error: unexpected

4.2 NVML 设备信息实现 (nvml_devices.go)

4.2.1 nvmlDevice (GPU设备)
go 复制代码
type nvmlDevice struct {
    nvml.Device  // 嵌入go-nvml的Device接口
}

GetPaths --- 获取设备文件路径

go 复制代码
func (d nvmlDevice) GetPaths() ([]string, error) {
    minor, ret := d.GetMinorNumber()  // 获取GPU次设备号
    if ret != nvml.SUCCESS {
        return nil, fmt.Errorf("error getting GPU device minor number: %v", ret)
    }
    path := fmt.Sprintf("/dev/nvidia%d", minor)  // 如 /dev/nvidia0
    return []string{path}, nil
}

GetNumaNode --- 获取NUMA拓扑信息

go 复制代码
func (d nvmlDevice) GetNumaNode() (bool, int, error) {
    info, ret := d.GetPciInfo()  // 获取PCI总线信息
    // 从PCI BusId提取总线地址,去除前导零
    busID := strings.ToLower(strings.TrimPrefix(
        uint8Slice(info.BusId[:]).String(), "0000"))
    // 读取sysfs中的NUMA节点信息
    b, err := os.ReadFile(
        fmt.Sprintf("/sys/bus/pci/devices/%s/numa_node", busID))
    if err != nil {
        return false, 0, nil  // 读失败视为无NUMA支持
    }
    node, err := strconv.Atoi(string(bytes.TrimSpace(b)))
    if node < 0 {
        return false, 0, nil  // 负值表示无NUMA关联
    }
    return true, node, nil
}

GetComputeCapability --- 获取CUDA算力版本

go 复制代码
func (d nvmlDevice) GetComputeCapability() (string, error) {
    major, minor, ret := d.GetCudaComputeCapability()
    if ret != nvml.SUCCESS {
        return "", ret
    }
    return fmt.Sprintf("%d.%d", major, minor), nil  // 如 "8.6"
}
4.2.2 nvmlMigDevice (MIG设备)

MIG设备继承自nvmlDevice但重写了多个方法:

GetPaths --- MIG设备路径更复杂

go 复制代码
func (d nvmlMigDevice) GetPaths() ([]string, error) {
    // 从/proc/driver/nvidia/capabilities读取MIG能力路径
    capDevicePaths, err := mig.GetMigCapabilityDevicePaths()
    
    gi, _ := d.GetGpuInstanceId()    // GPU实例ID
    ci, _ := d.GetComputeInstanceId() // 计算实例ID
    parent, _ := d.GetDeviceHandleFromMigDeviceHandle()
    minor, _ := parent.GetMinorNumber()
    
    parentPath := fmt.Sprintf("/dev/nvidia%d", minor)
    
    // GI能力路径: /proc/driver/nvidia/capabilities/gpu0/mig/gi1/access
    giCapPath := fmt.Sprintf(nvidiaCapabilitiesPath+
        "/gpu%d/mig/gi%d/access", minor, gi)
    // CI能力路径: /proc/driver/nvidia/capabilities/gpu0/mig/gi1/ci0/access
    ciCapPath := fmt.Sprintf(nvidiaCapabilitiesPath+
        "/gpu%d/mig/gi%d/ci%d/access", minor, gi, ci)
    
    // MIG设备需要3个路径:父设备 + GI access + CI access
    return []string{parentPath, 
        capDevicePaths[giCapPath], 
        capDevicePaths[ciCapPath]}, nil
}

GetComputeCapability --- 从父设备获取

go 复制代码
func (d nvmlMigDevice) GetComputeCapability() (string, error) {
    parent, ret := d.GetDeviceHandleFromMigDeviceHandle()
    if ret != nvml.SUCCESS {
        return "", fmt.Errorf("failed to get parent device: %w", ret)
    }
    return nvmlDevice{parent}.GetComputeCapability()
}

GetNumaNode --- 从父设备获取

go 复制代码
func (d nvmlMigDevice) GetNumaNode() (bool, int, error) {
    parent, ret := d.GetDeviceHandleFromMigDeviceHandle()
    return nvmlDevice{parent}.GetNumaNode()
}

4.3 Tegra 后端 (tegra_devices.go + tegra_manager.go)

#mermaid-svg-2esdLIEoLUDeStLT{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-2esdLIEoLUDeStLT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2esdLIEoLUDeStLT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2esdLIEoLUDeStLT .error-icon{fill:#552222;}#mermaid-svg-2esdLIEoLUDeStLT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2esdLIEoLUDeStLT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2esdLIEoLUDeStLT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2esdLIEoLUDeStLT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2esdLIEoLUDeStLT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2esdLIEoLUDeStLT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2esdLIEoLUDeStLT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2esdLIEoLUDeStLT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2esdLIEoLUDeStLT .marker.cross{stroke:#333333;}#mermaid-svg-2esdLIEoLUDeStLT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2esdLIEoLUDeStLT p{margin:0;}#mermaid-svg-2esdLIEoLUDeStLT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-2esdLIEoLUDeStLT .cluster-label text{fill:#333;}#mermaid-svg-2esdLIEoLUDeStLT .cluster-label span{color:#333;}#mermaid-svg-2esdLIEoLUDeStLT .cluster-label span p{background-color:transparent;}#mermaid-svg-2esdLIEoLUDeStLT .label text,#mermaid-svg-2esdLIEoLUDeStLT span{fill:#333;color:#333;}#mermaid-svg-2esdLIEoLUDeStLT .node rect,#mermaid-svg-2esdLIEoLUDeStLT .node circle,#mermaid-svg-2esdLIEoLUDeStLT .node ellipse,#mermaid-svg-2esdLIEoLUDeStLT .node polygon,#mermaid-svg-2esdLIEoLUDeStLT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2esdLIEoLUDeStLT .rough-node .label text,#mermaid-svg-2esdLIEoLUDeStLT .node .label text,#mermaid-svg-2esdLIEoLUDeStLT .image-shape .label,#mermaid-svg-2esdLIEoLUDeStLT .icon-shape .label{text-anchor:middle;}#mermaid-svg-2esdLIEoLUDeStLT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-2esdLIEoLUDeStLT .rough-node .label,#mermaid-svg-2esdLIEoLUDeStLT .node .label,#mermaid-svg-2esdLIEoLUDeStLT .image-shape .label,#mermaid-svg-2esdLIEoLUDeStLT .icon-shape .label{text-align:center;}#mermaid-svg-2esdLIEoLUDeStLT .node.clickable{cursor:pointer;}#mermaid-svg-2esdLIEoLUDeStLT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-2esdLIEoLUDeStLT .arrowheadPath{fill:#333333;}#mermaid-svg-2esdLIEoLUDeStLT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2esdLIEoLUDeStLT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2esdLIEoLUDeStLT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2esdLIEoLUDeStLT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-2esdLIEoLUDeStLT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2esdLIEoLUDeStLT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-2esdLIEoLUDeStLT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2esdLIEoLUDeStLT .cluster text{fill:#333;}#mermaid-svg-2esdLIEoLUDeStLT .cluster span{color:#333;}#mermaid-svg-2esdLIEoLUDeStLT 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-2esdLIEoLUDeStLT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2esdLIEoLUDeStLT rect.text{fill:none;stroke-width:0;}#mermaid-svg-2esdLIEoLUDeStLT .icon-shape,#mermaid-svg-2esdLIEoLUDeStLT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2esdLIEoLUDeStLT .icon-shape p,#mermaid-svg-2esdLIEoLUDeStLT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-2esdLIEoLUDeStLT .icon-shape .label rect,#mermaid-svg-2esdLIEoLUDeStLT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2esdLIEoLUDeStLT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2esdLIEoLUDeStLT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2esdLIEoLUDeStLT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

完成
NewTegraResourceManagers(config)
buildTegraDeviceMap(config)
创建空DeviceMap
name = 'tegra'
遍历 config.Resources.GPUs
Pattern.Matches('tegra')?
index = '0', '1', ...
devices.setEntry(name, index, &tegraDevice{})
updateDeviceMapWithReplicas
遍历DeviceMap创建resourceManager
return \[\]ResourceManager

tegraDevice 实现 --- 全部硬编码返回固定值:

go 复制代码
func (d *tegraDevice) GetUUID() (string, error) { return "tegra", nil }
func (d *tegraDevice) GetPaths() ([]string, error) { return nil, nil }  // 无设备路径
func (d *tegraDevice) GetNumaNode() (bool, int, error) { return false, -1, nil }
func (d *tegraDevice) GetTotalMemory() (uint64, error) { return 0, nil }
func (d *tegraDevice) GetComputeCapability() (string, error) { return "0.0", nil }

设计意图 :Tegra(Jetson)平台是集成GPU,无需NVML,通过/dev/nvidia0直接访问。设备路径为空意味着不挂载特定设备文件,容器中通过其他方式访问GPU。

4.4 WSL 后端 (wsl_devices.go)

go 复制代码
type wslAllGPUsDevice struct{}
go 复制代码
func (d wslAllGPUsDevice) GetUUID() (string, error) { return "all", nil }
func (d wslAllGPUsDevice) GetPaths() ([]string, error) { return []string{"/dev/dxg"}, nil }
func (d wslAllGPUsDevice) GetNumaNode() (bool, int, error) { return false, 0, nil }
func (d wslAllGPUsDevice) GetTotalMemory() (uint64, error) { return 0, nil }
func (d wslAllGPUsDevice) GetComputeCapability() (string, error) { return "", nil }

设计意图 :WSL2中所有GPU通过单一的/dev/dxg设备访问,UUID为"all"表示不区分具体GPU。WSL后端使用基础resourceManager(无健康检查、无对齐分配)。

4.5 设备分配算法

4.5.1 分配策略选择 (nvml_manager.go)

#mermaid-svg-X38RkhvEGwhfEwdt{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-X38RkhvEGwhfEwdt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-X38RkhvEGwhfEwdt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-X38RkhvEGwhfEwdt .error-icon{fill:#552222;}#mermaid-svg-X38RkhvEGwhfEwdt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-X38RkhvEGwhfEwdt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-X38RkhvEGwhfEwdt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-X38RkhvEGwhfEwdt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-X38RkhvEGwhfEwdt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-X38RkhvEGwhfEwdt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-X38RkhvEGwhfEwdt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-X38RkhvEGwhfEwdt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-X38RkhvEGwhfEwdt .marker.cross{stroke:#333333;}#mermaid-svg-X38RkhvEGwhfEwdt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-X38RkhvEGwhfEwdt p{margin:0;}#mermaid-svg-X38RkhvEGwhfEwdt .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-X38RkhvEGwhfEwdt .cluster-label text{fill:#333;}#mermaid-svg-X38RkhvEGwhfEwdt .cluster-label span{color:#333;}#mermaid-svg-X38RkhvEGwhfEwdt .cluster-label span p{background-color:transparent;}#mermaid-svg-X38RkhvEGwhfEwdt .label text,#mermaid-svg-X38RkhvEGwhfEwdt span{fill:#333;color:#333;}#mermaid-svg-X38RkhvEGwhfEwdt .node rect,#mermaid-svg-X38RkhvEGwhfEwdt .node circle,#mermaid-svg-X38RkhvEGwhfEwdt .node ellipse,#mermaid-svg-X38RkhvEGwhfEwdt .node polygon,#mermaid-svg-X38RkhvEGwhfEwdt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-X38RkhvEGwhfEwdt .rough-node .label text,#mermaid-svg-X38RkhvEGwhfEwdt .node .label text,#mermaid-svg-X38RkhvEGwhfEwdt .image-shape .label,#mermaid-svg-X38RkhvEGwhfEwdt .icon-shape .label{text-anchor:middle;}#mermaid-svg-X38RkhvEGwhfEwdt .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-X38RkhvEGwhfEwdt .rough-node .label,#mermaid-svg-X38RkhvEGwhfEwdt .node .label,#mermaid-svg-X38RkhvEGwhfEwdt .image-shape .label,#mermaid-svg-X38RkhvEGwhfEwdt .icon-shape .label{text-align:center;}#mermaid-svg-X38RkhvEGwhfEwdt .node.clickable{cursor:pointer;}#mermaid-svg-X38RkhvEGwhfEwdt .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-X38RkhvEGwhfEwdt .arrowheadPath{fill:#333333;}#mermaid-svg-X38RkhvEGwhfEwdt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-X38RkhvEGwhfEwdt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-X38RkhvEGwhfEwdt .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-X38RkhvEGwhfEwdt .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-X38RkhvEGwhfEwdt .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-X38RkhvEGwhfEwdt .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-X38RkhvEGwhfEwdt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-X38RkhvEGwhfEwdt .cluster text{fill:#333;}#mermaid-svg-X38RkhvEGwhfEwdt .cluster span{color:#333;}#mermaid-svg-X38RkhvEGwhfEwdt 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-X38RkhvEGwhfEwdt .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-X38RkhvEGwhfEwdt rect.text{fill:none;stroke-width:0;}#mermaid-svg-X38RkhvEGwhfEwdt .icon-shape,#mermaid-svg-X38RkhvEGwhfEwdt .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-X38RkhvEGwhfEwdt .icon-shape p,#mermaid-svg-X38RkhvEGwhfEwdt .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-X38RkhvEGwhfEwdt .icon-shape .label rect,#mermaid-svg-X38RkhvEGwhfEwdt .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-X38RkhvEGwhfEwdt .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-X38RkhvEGwhfEwdt .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-X38RkhvEGwhfEwdt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

GetPreferredAllocation

(available, required, size)
getPreferredAllocation
AlignedAllocationSupported()

且无AnnotatedID?
alignedAlloc

对齐分配
distributedAlloc

分布式分配
return devices

go 复制代码
func (r *nvmlResourceManager) getPreferredAllocation(
    available, required []string, size int) ([]string, error) {
    // 如果所有可用设备都是完整GPU且无副本
    if r.Devices().AlignedAllocationSupported() && 
       !AnnotatedIDs(available).AnyHasAnnotations() {
        return r.alignedAlloc(available, required, size)
    }
    // 否则使用分布式分配
    return r.distributedAlloc(available, required, size)
}
4.5.2 对齐分配: alignedAlloc

#mermaid-svg-S0weO4jXohGTkPZg{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-S0weO4jXohGTkPZg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-S0weO4jXohGTkPZg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-S0weO4jXohGTkPZg .error-icon{fill:#552222;}#mermaid-svg-S0weO4jXohGTkPZg .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-S0weO4jXohGTkPZg .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-S0weO4jXohGTkPZg .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-S0weO4jXohGTkPZg .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-S0weO4jXohGTkPZg .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-S0weO4jXohGTkPZg .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-S0weO4jXohGTkPZg .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-S0weO4jXohGTkPZg .marker{fill:#333333;stroke:#333333;}#mermaid-svg-S0weO4jXohGTkPZg .marker.cross{stroke:#333333;}#mermaid-svg-S0weO4jXohGTkPZg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-S0weO4jXohGTkPZg p{margin:0;}#mermaid-svg-S0weO4jXohGTkPZg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-S0weO4jXohGTkPZg .cluster-label text{fill:#333;}#mermaid-svg-S0weO4jXohGTkPZg .cluster-label span{color:#333;}#mermaid-svg-S0weO4jXohGTkPZg .cluster-label span p{background-color:transparent;}#mermaid-svg-S0weO4jXohGTkPZg .label text,#mermaid-svg-S0weO4jXohGTkPZg span{fill:#333;color:#333;}#mermaid-svg-S0weO4jXohGTkPZg .node rect,#mermaid-svg-S0weO4jXohGTkPZg .node circle,#mermaid-svg-S0weO4jXohGTkPZg .node ellipse,#mermaid-svg-S0weO4jXohGTkPZg .node polygon,#mermaid-svg-S0weO4jXohGTkPZg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-S0weO4jXohGTkPZg .rough-node .label text,#mermaid-svg-S0weO4jXohGTkPZg .node .label text,#mermaid-svg-S0weO4jXohGTkPZg .image-shape .label,#mermaid-svg-S0weO4jXohGTkPZg .icon-shape .label{text-anchor:middle;}#mermaid-svg-S0weO4jXohGTkPZg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-S0weO4jXohGTkPZg .rough-node .label,#mermaid-svg-S0weO4jXohGTkPZg .node .label,#mermaid-svg-S0weO4jXohGTkPZg .image-shape .label,#mermaid-svg-S0weO4jXohGTkPZg .icon-shape .label{text-align:center;}#mermaid-svg-S0weO4jXohGTkPZg .node.clickable{cursor:pointer;}#mermaid-svg-S0weO4jXohGTkPZg .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-S0weO4jXohGTkPZg .arrowheadPath{fill:#333333;}#mermaid-svg-S0weO4jXohGTkPZg .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-S0weO4jXohGTkPZg .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-S0weO4jXohGTkPZg .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-S0weO4jXohGTkPZg .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-S0weO4jXohGTkPZg .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-S0weO4jXohGTkPZg .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-S0weO4jXohGTkPZg .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-S0weO4jXohGTkPZg .cluster text{fill:#333;}#mermaid-svg-S0weO4jXohGTkPZg .cluster span{color:#333;}#mermaid-svg-S0weO4jXohGTkPZg 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-S0weO4jXohGTkPZg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-S0weO4jXohGTkPZg rect.text{fill:none;stroke-width:0;}#mermaid-svg-S0weO4jXohGTkPZg .icon-shape,#mermaid-svg-S0weO4jXohGTkPZg .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-S0weO4jXohGTkPZg .icon-shape p,#mermaid-svg-S0weO4jXohGTkPZg .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-S0weO4jXohGTkPZg .icon-shape .label rect,#mermaid-svg-S0weO4jXohGTkPZg .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-S0weO4jXohGTkPZg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-S0weO4jXohGTkPZg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-S0weO4jXohGTkPZg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} alignedAlloc(available, required, size)
gpuallocator.NewDevices

(WithNvmlLib)
获取GPU拓扑互联信息
linkedDevices.Filter(available)
linkedDevices.Filter(required)
NewBestEffortPolicy().Allocate

(available, required, size)
提取UUID列表
return devices

设计意图 :利用 go-gpuallocator 库根据GPU间的NVLink/NVSwitch拓扑关系选择最优分配组合。BestEffort策略会尽量将互联带宽最高的GPU分配给同一容器。

4.5.3 分布式分配: distributedAlloc (allocate.go)

#mermaid-svg-p52O8nijQLGyMN5X{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-p52O8nijQLGyMN5X .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-p52O8nijQLGyMN5X .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-p52O8nijQLGyMN5X .error-icon{fill:#552222;}#mermaid-svg-p52O8nijQLGyMN5X .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-p52O8nijQLGyMN5X .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-p52O8nijQLGyMN5X .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-p52O8nijQLGyMN5X .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-p52O8nijQLGyMN5X .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-p52O8nijQLGyMN5X .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-p52O8nijQLGyMN5X .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-p52O8nijQLGyMN5X .marker{fill:#333333;stroke:#333333;}#mermaid-svg-p52O8nijQLGyMN5X .marker.cross{stroke:#333333;}#mermaid-svg-p52O8nijQLGyMN5X svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-p52O8nijQLGyMN5X p{margin:0;}#mermaid-svg-p52O8nijQLGyMN5X .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-p52O8nijQLGyMN5X .cluster-label text{fill:#333;}#mermaid-svg-p52O8nijQLGyMN5X .cluster-label span{color:#333;}#mermaid-svg-p52O8nijQLGyMN5X .cluster-label span p{background-color:transparent;}#mermaid-svg-p52O8nijQLGyMN5X .label text,#mermaid-svg-p52O8nijQLGyMN5X span{fill:#333;color:#333;}#mermaid-svg-p52O8nijQLGyMN5X .node rect,#mermaid-svg-p52O8nijQLGyMN5X .node circle,#mermaid-svg-p52O8nijQLGyMN5X .node ellipse,#mermaid-svg-p52O8nijQLGyMN5X .node polygon,#mermaid-svg-p52O8nijQLGyMN5X .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-p52O8nijQLGyMN5X .rough-node .label text,#mermaid-svg-p52O8nijQLGyMN5X .node .label text,#mermaid-svg-p52O8nijQLGyMN5X .image-shape .label,#mermaid-svg-p52O8nijQLGyMN5X .icon-shape .label{text-anchor:middle;}#mermaid-svg-p52O8nijQLGyMN5X .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-p52O8nijQLGyMN5X .rough-node .label,#mermaid-svg-p52O8nijQLGyMN5X .node .label,#mermaid-svg-p52O8nijQLGyMN5X .image-shape .label,#mermaid-svg-p52O8nijQLGyMN5X .icon-shape .label{text-align:center;}#mermaid-svg-p52O8nijQLGyMN5X .node.clickable{cursor:pointer;}#mermaid-svg-p52O8nijQLGyMN5X .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-p52O8nijQLGyMN5X .arrowheadPath{fill:#333333;}#mermaid-svg-p52O8nijQLGyMN5X .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-p52O8nijQLGyMN5X .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-p52O8nijQLGyMN5X .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-p52O8nijQLGyMN5X .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-p52O8nijQLGyMN5X .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-p52O8nijQLGyMN5X .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-p52O8nijQLGyMN5X .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-p52O8nijQLGyMN5X .cluster text{fill:#333;}#mermaid-svg-p52O8nijQLGyMN5X .cluster span{color:#333;}#mermaid-svg-p52O8nijQLGyMN5X 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-p52O8nijQLGyMN5X .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-p52O8nijQLGyMN5X rect.text{fill:none;stroke-width:0;}#mermaid-svg-p52O8nijQLGyMN5X .icon-shape,#mermaid-svg-p52O8nijQLGyMN5X .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-p52O8nijQLGyMN5X .icon-shape p,#mermaid-svg-p52O8nijQLGyMN5X .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-p52O8nijQLGyMN5X .icon-shape .label rect,#mermaid-svg-p52O8nijQLGyMN5X .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-p52O8nijQLGyMN5X .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-p52O8nijQLGyMN5X .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-p52O8nijQLGyMN5X :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是



distributedAlloc

(available, required, size)
candidates = available - required的设备
needed = size - len(required)
candidates < needed?
return error: 设备不足
构建replicas映射

统计每个原始设备的total/available副本数
循环needed次选择设备
按(total-available)升序排序candidates
选择差值最小的设备

(已被分配最少的原始设备)
available--, 移出candidates
还需要选择?
append(required, selected...)
return devices

逐行深度解析

go 复制代码
func (r *resourceManager) distributedAlloc(
    available, required []string, size int) ([]string, error) {
    // 候选设备 = 可用设备中减去已要求的设备
    candidates := r.devices.Subset(available).
        Difference(r.devices.Subset(required)).GetIDs()
    needed := size - len(required)

    if len(candidates) < needed {
        return nil, fmt.Errorf("not enough available devices to satisfy allocation")
    }

    // 构建副本映射: 原始设备ID -> {total副本数, available副本数}
    replicas := make(map[string]*struct{ total, available int })
    for _, c := range candidates {
        id := AnnotatedID(c).GetID()  // 去除::replica后缀
        if _, exists := replicas[id]; !exists {
            replicas[id] = &struct{ total, available int }{}
        }
        replicas[id].available++
    }
    // 统计total: 从r.devices中统计每个原始设备的总副本数
    for d := range r.devices {
        id := AnnotatedID(d).GetID()
        if _, exists := replicas[id]; !exists {
            continue
        }
        replicas[id].total++
    }

    // 逐个选择needed个设备
    var devices []string
    for i := 0; i < needed; i++ {
        // 关键:按(total - available)升序排序
        // 差值越大 = 已被分配的副本越多
        // 选择差值最小的 = 选择被分配最少的原始设备的副本
        sort.Slice(candidates, func(i, j int) bool {
            iid := AnnotatedID(candidates[i]).GetID()
            jid := AnnotatedID(candidates[j]).GetID()
            idiff := replicas[iid].total - replicas[iid].available
            jdiff := replicas[jid].total - replicas[jid].available
            return idiff < jdiff
        })
        id := AnnotatedID(candidates[0]).GetID()
        replicas[id].available--  // 选中后可用数减1
        devices = append(devices, candidates[0])
        candidates = candidates[1:]  // 移除已选
    }

    // 最终结果 = required + 选中的devices
    devices = append(required, devices...)
    return devices, nil
}

算法本质 :这是一种负载均衡分配策略。对于共享设备(时间分片),确保各物理GPU上的副本被均匀分配,避免某个GPU被过度共享而其他GPU闲置。

4.6 健康检查机制 (health.go)

4.6.1 健康检查总流程

#mermaid-svg-d5SUxtPsqJiH8Euf{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-d5SUxtPsqJiH8Euf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-d5SUxtPsqJiH8Euf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-d5SUxtPsqJiH8Euf .error-icon{fill:#552222;}#mermaid-svg-d5SUxtPsqJiH8Euf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-d5SUxtPsqJiH8Euf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-d5SUxtPsqJiH8Euf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-d5SUxtPsqJiH8Euf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-d5SUxtPsqJiH8Euf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-d5SUxtPsqJiH8Euf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-d5SUxtPsqJiH8Euf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-d5SUxtPsqJiH8Euf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-d5SUxtPsqJiH8Euf .marker.cross{stroke:#333333;}#mermaid-svg-d5SUxtPsqJiH8Euf svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-d5SUxtPsqJiH8Euf p{margin:0;}#mermaid-svg-d5SUxtPsqJiH8Euf .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-d5SUxtPsqJiH8Euf .cluster-label text{fill:#333;}#mermaid-svg-d5SUxtPsqJiH8Euf .cluster-label span{color:#333;}#mermaid-svg-d5SUxtPsqJiH8Euf .cluster-label span p{background-color:transparent;}#mermaid-svg-d5SUxtPsqJiH8Euf .label text,#mermaid-svg-d5SUxtPsqJiH8Euf span{fill:#333;color:#333;}#mermaid-svg-d5SUxtPsqJiH8Euf .node rect,#mermaid-svg-d5SUxtPsqJiH8Euf .node circle,#mermaid-svg-d5SUxtPsqJiH8Euf .node ellipse,#mermaid-svg-d5SUxtPsqJiH8Euf .node polygon,#mermaid-svg-d5SUxtPsqJiH8Euf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-d5SUxtPsqJiH8Euf .rough-node .label text,#mermaid-svg-d5SUxtPsqJiH8Euf .node .label text,#mermaid-svg-d5SUxtPsqJiH8Euf .image-shape .label,#mermaid-svg-d5SUxtPsqJiH8Euf .icon-shape .label{text-anchor:middle;}#mermaid-svg-d5SUxtPsqJiH8Euf .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-d5SUxtPsqJiH8Euf .rough-node .label,#mermaid-svg-d5SUxtPsqJiH8Euf .node .label,#mermaid-svg-d5SUxtPsqJiH8Euf .image-shape .label,#mermaid-svg-d5SUxtPsqJiH8Euf .icon-shape .label{text-align:center;}#mermaid-svg-d5SUxtPsqJiH8Euf .node.clickable{cursor:pointer;}#mermaid-svg-d5SUxtPsqJiH8Euf .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-d5SUxtPsqJiH8Euf .arrowheadPath{fill:#333333;}#mermaid-svg-d5SUxtPsqJiH8Euf .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-d5SUxtPsqJiH8Euf .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-d5SUxtPsqJiH8Euf .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d5SUxtPsqJiH8Euf .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-d5SUxtPsqJiH8Euf .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d5SUxtPsqJiH8Euf .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-d5SUxtPsqJiH8Euf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-d5SUxtPsqJiH8Euf .cluster text{fill:#333;}#mermaid-svg-d5SUxtPsqJiH8Euf .cluster span{color:#333;}#mermaid-svg-d5SUxtPsqJiH8Euf 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-d5SUxtPsqJiH8Euf .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-d5SUxtPsqJiH8Euf rect.text{fill:none;stroke-width:0;}#mermaid-svg-d5SUxtPsqJiH8Euf .icon-shape,#mermaid-svg-d5SUxtPsqJiH8Euf .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d5SUxtPsqJiH8Euf .icon-shape p,#mermaid-svg-d5SUxtPsqJiH8Euf .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-d5SUxtPsqJiH8Euf .icon-shape .label rect,#mermaid-svg-d5SUxtPsqJiH8Euf .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d5SUxtPsqJiH8Euf .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-d5SUxtPsqJiH8Euf .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-d5SUxtPsqJiH8Euf :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是



ERROR_NOT_SUPPORTED
其他失败
成功
TIMEOUT
错误
事件




失败
成功






stop信号
CheckHealth(stop, unhealthy)
nvmlResourceManager.CheckHealth
checkHealth(stop, r.devices, unhealthy)
getDisabledHealthCheckXids()
全部禁用?
return nil
nvml.Init()
EventSetCreate()
遍历devices注册事件
getDevicePlacement(d)
获取设备位置失败?
标记为unhealthy
DeviceGetHandleByUUID
GetSupportedEventTypes
RegisterEvents

mask: XidCritical|DoubleBitECC|SingleBitECC
注册失败?
Warning: 设备太老
标记为unhealthy
记录映射关系
进入事件循环
eventSet.Wait(5000ms)
标记所有设备unhealthy
EventType == XidCriticalError?
XID被禁用?
e.Device.GetUUID()
UUID在parentToDeviceMap?
MIG设备且GI/CI有效?
GI/CI匹配?
标记该设备unhealthy
return nil

4.6.2 XID 禁用机制

#mermaid-svg-eOqpV9mT6HHriWZK{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-eOqpV9mT6HHriWZK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-eOqpV9mT6HHriWZK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-eOqpV9mT6HHriWZK .error-icon{fill:#552222;}#mermaid-svg-eOqpV9mT6HHriWZK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eOqpV9mT6HHriWZK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-eOqpV9mT6HHriWZK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eOqpV9mT6HHriWZK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eOqpV9mT6HHriWZK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-eOqpV9mT6HHriWZK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eOqpV9mT6HHriWZK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eOqpV9mT6HHriWZK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eOqpV9mT6HHriWZK .marker.cross{stroke:#333333;}#mermaid-svg-eOqpV9mT6HHriWZK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eOqpV9mT6HHriWZK p{margin:0;}#mermaid-svg-eOqpV9mT6HHriWZK .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-eOqpV9mT6HHriWZK .cluster-label text{fill:#333;}#mermaid-svg-eOqpV9mT6HHriWZK .cluster-label span{color:#333;}#mermaid-svg-eOqpV9mT6HHriWZK .cluster-label span p{background-color:transparent;}#mermaid-svg-eOqpV9mT6HHriWZK .label text,#mermaid-svg-eOqpV9mT6HHriWZK span{fill:#333;color:#333;}#mermaid-svg-eOqpV9mT6HHriWZK .node rect,#mermaid-svg-eOqpV9mT6HHriWZK .node circle,#mermaid-svg-eOqpV9mT6HHriWZK .node ellipse,#mermaid-svg-eOqpV9mT6HHriWZK .node polygon,#mermaid-svg-eOqpV9mT6HHriWZK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eOqpV9mT6HHriWZK .rough-node .label text,#mermaid-svg-eOqpV9mT6HHriWZK .node .label text,#mermaid-svg-eOqpV9mT6HHriWZK .image-shape .label,#mermaid-svg-eOqpV9mT6HHriWZK .icon-shape .label{text-anchor:middle;}#mermaid-svg-eOqpV9mT6HHriWZK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-eOqpV9mT6HHriWZK .rough-node .label,#mermaid-svg-eOqpV9mT6HHriWZK .node .label,#mermaid-svg-eOqpV9mT6HHriWZK .image-shape .label,#mermaid-svg-eOqpV9mT6HHriWZK .icon-shape .label{text-align:center;}#mermaid-svg-eOqpV9mT6HHriWZK .node.clickable{cursor:pointer;}#mermaid-svg-eOqpV9mT6HHriWZK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-eOqpV9mT6HHriWZK .arrowheadPath{fill:#333333;}#mermaid-svg-eOqpV9mT6HHriWZK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-eOqpV9mT6HHriWZK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-eOqpV9mT6HHriWZK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eOqpV9mT6HHriWZK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-eOqpV9mT6HHriWZK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eOqpV9mT6HHriWZK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-eOqpV9mT6HHriWZK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-eOqpV9mT6HHriWZK .cluster text{fill:#333;}#mermaid-svg-eOqpV9mT6HHriWZK .cluster span{color:#333;}#mermaid-svg-eOqpV9mT6HHriWZK 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-eOqpV9mT6HHriWZK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-eOqpV9mT6HHriWZK rect.text{fill:none;stroke-width:0;}#mermaid-svg-eOqpV9mT6HHriWZK .icon-shape,#mermaid-svg-eOqpV9mT6HHriWZK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eOqpV9mT6HHriWZK .icon-shape p,#mermaid-svg-eOqpV9mT6HHriWZK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-eOqpV9mT6HHriWZK .icon-shape .label rect,#mermaid-svg-eOqpV9mT6HHriWZK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eOqpV9mT6HHriWZK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-eOqpV9mT6HHriWZK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-eOqpV9mT6HHriWZK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} getDisabledHealthCheckXids()
从DP_DISABLE_HEALTHCHECKS

读取禁用XID列表
从DP_ENABLE_HEALTHCHECKS

读取启用XID列表
添加硬编码忽略XID

13,31,43,45,68,109
用启用列表覆盖禁用列表

enabled→disabledid=false
return disabledXIDs

硬编码忽略的XID及其含义

XID 含义 忽略原因
13 Graphics Engine Exception 应用程序错误,GPU仍健康
31 GPU memory page fault 应用程序错误
43 GPU stopped processing 应用程序错误
45 Preemptive cleanup 因前序错误导致的清理
68 Video processor exception 视频处理异常
109 Context Switch Timeout Error 上下文切换超时

disabledXIDs 逻辑详解

go 复制代码
type disabledXIDs map[uint64]bool  // key=XID编号, value=true表示禁用

// IsAllDisabled: 是否全部禁用
func (h disabledXIDs) IsAllDisabled() bool {
    if allDisabled, ok := h[allXIDs]; ok {
        return allDisabled  // allXIDs=0 被设置为true
    }
    return false
}

// IsDisabled: 某个XID是否被禁用
func (h disabledXIDs) IsDisabled(xid uint64) bool {
    // 如果XID被显式启用(all=false),则不禁用
    if explicitAll, ok := h[allXIDs]; ok && !explicitAll {
        return false
    }
    // 如果XID被显式禁用或启用,以显式设置为准
    if disabled, ok := h[xid]; ok {
        return disabled
    }
    // 否则看是否全部禁用
    return h.IsAllDisabled()
}
4.6.3 设备位置定位: getDevicePlacement

#mermaid-svg-0EMlZ2lRYxO7eI7Z{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-0EMlZ2lRYxO7eI7Z .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .error-icon{fill:#552222;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .marker.cross{stroke:#333333;}#mermaid-svg-0EMlZ2lRYxO7eI7Z svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0EMlZ2lRYxO7eI7Z p{margin:0;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .cluster-label text{fill:#333;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .cluster-label span{color:#333;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .cluster-label span p{background-color:transparent;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .label text,#mermaid-svg-0EMlZ2lRYxO7eI7Z span{fill:#333;color:#333;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .node rect,#mermaid-svg-0EMlZ2lRYxO7eI7Z .node circle,#mermaid-svg-0EMlZ2lRYxO7eI7Z .node ellipse,#mermaid-svg-0EMlZ2lRYxO7eI7Z .node polygon,#mermaid-svg-0EMlZ2lRYxO7eI7Z .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .rough-node .label text,#mermaid-svg-0EMlZ2lRYxO7eI7Z .node .label text,#mermaid-svg-0EMlZ2lRYxO7eI7Z .image-shape .label,#mermaid-svg-0EMlZ2lRYxO7eI7Z .icon-shape .label{text-anchor:middle;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .rough-node .label,#mermaid-svg-0EMlZ2lRYxO7eI7Z .node .label,#mermaid-svg-0EMlZ2lRYxO7eI7Z .image-shape .label,#mermaid-svg-0EMlZ2lRYxO7eI7Z .icon-shape .label{text-align:center;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .node.clickable{cursor:pointer;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .arrowheadPath{fill:#333333;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-0EMlZ2lRYxO7eI7Z .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0EMlZ2lRYxO7eI7Z .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-0EMlZ2lRYxO7eI7Z .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .cluster text{fill:#333;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .cluster span{color:#333;}#mermaid-svg-0EMlZ2lRYxO7eI7Z 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-0EMlZ2lRYxO7eI7Z .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0EMlZ2lRYxO7eI7Z rect.text{fill:none;stroke-width:0;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .icon-shape,#mermaid-svg-0EMlZ2lRYxO7eI7Z .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .icon-shape p,#mermaid-svg-0EMlZ2lRYxO7eI7Z .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .icon-shape .label rect,#mermaid-svg-0EMlZ2lRYxO7eI7Z .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0EMlZ2lRYxO7eI7Z .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-0EMlZ2lRYxO7eI7Z .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-0EMlZ2lRYxO7eI7Z :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否

成功
失败(旧驱动)
getDevicePlacement(d)
d.IsMigDevice()?
return (d.GetUUID(), 0xFFFFFFFF, 0xFFFFFFFF, nil)
getMigDeviceParts(d)
nvml.DeviceGetHandleByUUID(uuid)
GetDeviceHandleFromMigDeviceHandle
parentUUID, gi, ci
return (parentUUID, gi, ci, nil)
parseMigDeviceUUID(uuid)
解析 MIG-GPU-xxxgi/ci 格式
return (parentUUID, gi, ci, nil)

MIG UUID 解析 --- parseMigDeviceUUID

MIG设备UUID格式: MIG-GPU-xxxx/gi/ci

go 复制代码
func parseMigDeviceUUID(mig string) (string, uint32, uint32, error) {
    // 第一步:按"-"分割,验证以"MIG"开头
    tokens := strings.SplitN(mig, "-", 2)
    if len(tokens) != 2 || tokens[0] != "MIG" {
        return "", 0, 0, fmt.Errorf("unable to parse UUID as MIG device")
    }
    // 第二步:按"/"分割,提取 parentUUID/gi/ci
    tokens = strings.SplitN(tokens[1], "/", 3)
    if len(tokens) != 3 || !strings.HasPrefix(tokens[0], "GPU-") {
        return "", 0, 0, fmt.Errorf("unable to parse UUID as MIG device")
    }
    gi, _ := toUint32(tokens[1])
    ci, _ := toUint32(tokens[2])
    return tokens[0], gi, ci, nil
}

4.7 请求校验: ValidateRequest (rm.go)

#mermaid-svg-6qY3FwPXOcQFc6SY{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-6qY3FwPXOcQFc6SY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6qY3FwPXOcQFc6SY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6qY3FwPXOcQFc6SY .error-icon{fill:#552222;}#mermaid-svg-6qY3FwPXOcQFc6SY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6qY3FwPXOcQFc6SY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6qY3FwPXOcQFc6SY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6qY3FwPXOcQFc6SY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6qY3FwPXOcQFc6SY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6qY3FwPXOcQFc6SY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6qY3FwPXOcQFc6SY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6qY3FwPXOcQFc6SY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6qY3FwPXOcQFc6SY .marker.cross{stroke:#333333;}#mermaid-svg-6qY3FwPXOcQFc6SY svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6qY3FwPXOcQFc6SY p{margin:0;}#mermaid-svg-6qY3FwPXOcQFc6SY .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-6qY3FwPXOcQFc6SY .cluster-label text{fill:#333;}#mermaid-svg-6qY3FwPXOcQFc6SY .cluster-label span{color:#333;}#mermaid-svg-6qY3FwPXOcQFc6SY .cluster-label span p{background-color:transparent;}#mermaid-svg-6qY3FwPXOcQFc6SY .label text,#mermaid-svg-6qY3FwPXOcQFc6SY span{fill:#333;color:#333;}#mermaid-svg-6qY3FwPXOcQFc6SY .node rect,#mermaid-svg-6qY3FwPXOcQFc6SY .node circle,#mermaid-svg-6qY3FwPXOcQFc6SY .node ellipse,#mermaid-svg-6qY3FwPXOcQFc6SY .node polygon,#mermaid-svg-6qY3FwPXOcQFc6SY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6qY3FwPXOcQFc6SY .rough-node .label text,#mermaid-svg-6qY3FwPXOcQFc6SY .node .label text,#mermaid-svg-6qY3FwPXOcQFc6SY .image-shape .label,#mermaid-svg-6qY3FwPXOcQFc6SY .icon-shape .label{text-anchor:middle;}#mermaid-svg-6qY3FwPXOcQFc6SY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-6qY3FwPXOcQFc6SY .rough-node .label,#mermaid-svg-6qY3FwPXOcQFc6SY .node .label,#mermaid-svg-6qY3FwPXOcQFc6SY .image-shape .label,#mermaid-svg-6qY3FwPXOcQFc6SY .icon-shape .label{text-align:center;}#mermaid-svg-6qY3FwPXOcQFc6SY .node.clickable{cursor:pointer;}#mermaid-svg-6qY3FwPXOcQFc6SY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-6qY3FwPXOcQFc6SY .arrowheadPath{fill:#333333;}#mermaid-svg-6qY3FwPXOcQFc6SY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-6qY3FwPXOcQFc6SY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-6qY3FwPXOcQFc6SY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6qY3FwPXOcQFc6SY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-6qY3FwPXOcQFc6SY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6qY3FwPXOcQFc6SY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-6qY3FwPXOcQFc6SY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6qY3FwPXOcQFc6SY .cluster text{fill:#333;}#mermaid-svg-6qY3FwPXOcQFc6SY .cluster span{color:#333;}#mermaid-svg-6qY3FwPXOcQFc6SY 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-6qY3FwPXOcQFc6SY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6qY3FwPXOcQFc6SY rect.text{fill:none;stroke-width:0;}#mermaid-svg-6qY3FwPXOcQFc6SY .icon-shape,#mermaid-svg-6qY3FwPXOcQFc6SY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6qY3FwPXOcQFc6SY .icon-shape p,#mermaid-svg-6qY3FwPXOcQFc6SY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-6qY3FwPXOcQFc6SY .icon-shape .label rect,#mermaid-svg-6qY3FwPXOcQFc6SY .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6qY3FwPXOcQFc6SY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-6qY3FwPXOcQFc6SY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-6qY3FwPXOcQFc6SY :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否

TimeSlicing

true
false

MPS


ValidateRequest(ids AnnotatedIDs)
遍历ids检查设备存在性
所有ID都在devices中?
return error: unknown device
includesReplicas = ids.AnyHasAnnotations()
SharingStrategy?
includesReplicas且>1个请求?
FailRequestsGreaterThanOne?
return error: 最大请求数为1
return nil
includesReplicas且>1个请求?
return error: 最大请求数为1

MPS忽略FailRequestsGreaterThanOne

设计意图

  • 共享设备(副本)的请求限制为1个,因为时间分片/MPS共享时一个容器不应同时占用多个副本
  • TimeSlicing可通过FailRequestsGreaterThanOne配置放宽(向后兼容)
  • MPS明确忽略该配置,始终限制为1

4.8 GetDevicePaths 路径处理

#mermaid-svg-yhlw3x0EnXssnqgm{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-yhlw3x0EnXssnqgm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yhlw3x0EnXssnqgm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yhlw3x0EnXssnqgm .error-icon{fill:#552222;}#mermaid-svg-yhlw3x0EnXssnqgm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yhlw3x0EnXssnqgm .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yhlw3x0EnXssnqgm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yhlw3x0EnXssnqgm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yhlw3x0EnXssnqgm .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yhlw3x0EnXssnqgm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yhlw3x0EnXssnqgm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yhlw3x0EnXssnqgm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yhlw3x0EnXssnqgm .marker.cross{stroke:#333333;}#mermaid-svg-yhlw3x0EnXssnqgm svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yhlw3x0EnXssnqgm p{margin:0;}#mermaid-svg-yhlw3x0EnXssnqgm .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yhlw3x0EnXssnqgm .cluster-label text{fill:#333;}#mermaid-svg-yhlw3x0EnXssnqgm .cluster-label span{color:#333;}#mermaid-svg-yhlw3x0EnXssnqgm .cluster-label span p{background-color:transparent;}#mermaid-svg-yhlw3x0EnXssnqgm .label text,#mermaid-svg-yhlw3x0EnXssnqgm span{fill:#333;color:#333;}#mermaid-svg-yhlw3x0EnXssnqgm .node rect,#mermaid-svg-yhlw3x0EnXssnqgm .node circle,#mermaid-svg-yhlw3x0EnXssnqgm .node ellipse,#mermaid-svg-yhlw3x0EnXssnqgm .node polygon,#mermaid-svg-yhlw3x0EnXssnqgm .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yhlw3x0EnXssnqgm .rough-node .label text,#mermaid-svg-yhlw3x0EnXssnqgm .node .label text,#mermaid-svg-yhlw3x0EnXssnqgm .image-shape .label,#mermaid-svg-yhlw3x0EnXssnqgm .icon-shape .label{text-anchor:middle;}#mermaid-svg-yhlw3x0EnXssnqgm .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yhlw3x0EnXssnqgm .rough-node .label,#mermaid-svg-yhlw3x0EnXssnqgm .node .label,#mermaid-svg-yhlw3x0EnXssnqgm .image-shape .label,#mermaid-svg-yhlw3x0EnXssnqgm .icon-shape .label{text-align:center;}#mermaid-svg-yhlw3x0EnXssnqgm .node.clickable{cursor:pointer;}#mermaid-svg-yhlw3x0EnXssnqgm .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yhlw3x0EnXssnqgm .arrowheadPath{fill:#333333;}#mermaid-svg-yhlw3x0EnXssnqgm .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yhlw3x0EnXssnqgm .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yhlw3x0EnXssnqgm .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yhlw3x0EnXssnqgm .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yhlw3x0EnXssnqgm .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yhlw3x0EnXssnqgm .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yhlw3x0EnXssnqgm .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yhlw3x0EnXssnqgm .cluster text{fill:#333;}#mermaid-svg-yhlw3x0EnXssnqgm .cluster span{color:#333;}#mermaid-svg-yhlw3x0EnXssnqgm 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-yhlw3x0EnXssnqgm .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yhlw3x0EnXssnqgm rect.text{fill:none;stroke-width:0;}#mermaid-svg-yhlw3x0EnXssnqgm .icon-shape,#mermaid-svg-yhlw3x0EnXssnqgm .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yhlw3x0EnXssnqgm .icon-shape p,#mermaid-svg-yhlw3x0EnXssnqgm .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yhlw3x0EnXssnqgm .icon-shape .label rect,#mermaid-svg-yhlw3x0EnXssnqgm .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yhlw3x0EnXssnqgm .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yhlw3x0EnXssnqgm .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yhlw3x0EnXssnqgm :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 基础resourceManager
nvmlResourceManager
GetDevicePaths(ids)
ResourceManager类型
Subset(ids).GetPaths()
附加公共设备路径
/dev/nvidiactl

/dev/nvidia-uvm

/dev/nvidia-uvm-tools

/dev/nvidia-modeset
append(r.resourceManager.GetDevicePaths(ids))
return paths

NVML后端额外挂载的公共设备文件

  • /dev/nvidiactl --- NVIDIA控制设备
  • /dev/nvidia-uvm --- Unified Memory设备
  • /dev/nvidia-uvm-tools --- UVM调试工具
  • /dev/nvidia-modeset --- 模式设置设备

4.9 AddDefaultResourcesToConfig (rm.go)

#mermaid-svg-fdS5SAeun9jlCdbj{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-fdS5SAeun9jlCdbj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fdS5SAeun9jlCdbj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fdS5SAeun9jlCdbj .error-icon{fill:#552222;}#mermaid-svg-fdS5SAeun9jlCdbj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fdS5SAeun9jlCdbj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fdS5SAeun9jlCdbj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fdS5SAeun9jlCdbj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fdS5SAeun9jlCdbj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fdS5SAeun9jlCdbj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fdS5SAeun9jlCdbj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fdS5SAeun9jlCdbj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fdS5SAeun9jlCdbj .marker.cross{stroke:#333333;}#mermaid-svg-fdS5SAeun9jlCdbj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fdS5SAeun9jlCdbj p{margin:0;}#mermaid-svg-fdS5SAeun9jlCdbj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-fdS5SAeun9jlCdbj .cluster-label text{fill:#333;}#mermaid-svg-fdS5SAeun9jlCdbj .cluster-label span{color:#333;}#mermaid-svg-fdS5SAeun9jlCdbj .cluster-label span p{background-color:transparent;}#mermaid-svg-fdS5SAeun9jlCdbj .label text,#mermaid-svg-fdS5SAeun9jlCdbj span{fill:#333;color:#333;}#mermaid-svg-fdS5SAeun9jlCdbj .node rect,#mermaid-svg-fdS5SAeun9jlCdbj .node circle,#mermaid-svg-fdS5SAeun9jlCdbj .node ellipse,#mermaid-svg-fdS5SAeun9jlCdbj .node polygon,#mermaid-svg-fdS5SAeun9jlCdbj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fdS5SAeun9jlCdbj .rough-node .label text,#mermaid-svg-fdS5SAeun9jlCdbj .node .label text,#mermaid-svg-fdS5SAeun9jlCdbj .image-shape .label,#mermaid-svg-fdS5SAeun9jlCdbj .icon-shape .label{text-anchor:middle;}#mermaid-svg-fdS5SAeun9jlCdbj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-fdS5SAeun9jlCdbj .rough-node .label,#mermaid-svg-fdS5SAeun9jlCdbj .node .label,#mermaid-svg-fdS5SAeun9jlCdbj .image-shape .label,#mermaid-svg-fdS5SAeun9jlCdbj .icon-shape .label{text-align:center;}#mermaid-svg-fdS5SAeun9jlCdbj .node.clickable{cursor:pointer;}#mermaid-svg-fdS5SAeun9jlCdbj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-fdS5SAeun9jlCdbj .arrowheadPath{fill:#333333;}#mermaid-svg-fdS5SAeun9jlCdbj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-fdS5SAeun9jlCdbj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-fdS5SAeun9jlCdbj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fdS5SAeun9jlCdbj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-fdS5SAeun9jlCdbj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fdS5SAeun9jlCdbj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-fdS5SAeun9jlCdbj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-fdS5SAeun9jlCdbj .cluster text{fill:#333;}#mermaid-svg-fdS5SAeun9jlCdbj .cluster span{color:#333;}#mermaid-svg-fdS5SAeun9jlCdbj 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-fdS5SAeun9jlCdbj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-fdS5SAeun9jlCdbj rect.text{fill:none;stroke-width:0;}#mermaid-svg-fdS5SAeun9jlCdbj .icon-shape,#mermaid-svg-fdS5SAeun9jlCdbj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fdS5SAeun9jlCdbj .icon-shape p,#mermaid-svg-fdS5SAeun9jlCdbj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-fdS5SAeun9jlCdbj .icon-shape .label rect,#mermaid-svg-fdS5SAeun9jlCdbj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fdS5SAeun9jlCdbj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-fdS5SAeun9jlCdbj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-fdS5SAeun9jlCdbj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

Single
Mixed


失败
true
false
成功


AddDefaultResourcesToConfig

(infolib, nvmllib, devicelib, config)
AddGPUResource('*', 'gpu')
MigStrategy == nil?
return nil
MigStrategy值
AddMIGResource('*', 'gpu')

所有MIG设备归为同一资源
HasNvml()?
Warning + return nil
nvmllib.Init()
FailOnInitError?
return error
VisitMigProfiles回调
p.GetInfo()
C == G?

(计算实例数==GPU实例数)
resourceName = 'mig-' + profile

如 mig-1g.10gb
AddMIGResource(profile, resourceName)

设计意图

  • MigStrategySingle: 所有MIG设备使用统一的资源名 nvidia.com/gpu
  • MigStrategyMixed: 每个 MIG profile(如 1g.10gb2g.20gb)对应独立的资源名 nvidia.com/mig-1g.10gb
  • C == G 检查:确保该profile的计算实例数等于GPU实例数(即CI=GI,没有共享CI的情况)

4.10 helper.go: uint8Slice

go 复制代码
type uint8Slice []uint8

func (s uint8Slice) String() string {
    var b []byte
    for _, c := range s {
        if c == 0 { break }  // 遇到null终止符停止
        b = append(b, c)
    }
    return string(b)
}

用途 :NVML返回的PCI BusId是 [32]uint8 固定长度字节数组(C风格null终止字符串)。uint8Slice 将其转换为Go string。


五、完整数据流图

5.1 设备发现数据流

#mermaid-svg-8R9ugDHzlwvTR6QJ{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-8R9ugDHzlwvTR6QJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8R9ugDHzlwvTR6QJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8R9ugDHzlwvTR6QJ .error-icon{fill:#552222;}#mermaid-svg-8R9ugDHzlwvTR6QJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8R9ugDHzlwvTR6QJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8R9ugDHzlwvTR6QJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8R9ugDHzlwvTR6QJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8R9ugDHzlwvTR6QJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8R9ugDHzlwvTR6QJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8R9ugDHzlwvTR6QJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8R9ugDHzlwvTR6QJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8R9ugDHzlwvTR6QJ .marker.cross{stroke:#333333;}#mermaid-svg-8R9ugDHzlwvTR6QJ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8R9ugDHzlwvTR6QJ p{margin:0;}#mermaid-svg-8R9ugDHzlwvTR6QJ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8R9ugDHzlwvTR6QJ .cluster-label text{fill:#333;}#mermaid-svg-8R9ugDHzlwvTR6QJ .cluster-label span{color:#333;}#mermaid-svg-8R9ugDHzlwvTR6QJ .cluster-label span p{background-color:transparent;}#mermaid-svg-8R9ugDHzlwvTR6QJ .label text,#mermaid-svg-8R9ugDHzlwvTR6QJ span{fill:#333;color:#333;}#mermaid-svg-8R9ugDHzlwvTR6QJ .node rect,#mermaid-svg-8R9ugDHzlwvTR6QJ .node circle,#mermaid-svg-8R9ugDHzlwvTR6QJ .node ellipse,#mermaid-svg-8R9ugDHzlwvTR6QJ .node polygon,#mermaid-svg-8R9ugDHzlwvTR6QJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8R9ugDHzlwvTR6QJ .rough-node .label text,#mermaid-svg-8R9ugDHzlwvTR6QJ .node .label text,#mermaid-svg-8R9ugDHzlwvTR6QJ .image-shape .label,#mermaid-svg-8R9ugDHzlwvTR6QJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-8R9ugDHzlwvTR6QJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8R9ugDHzlwvTR6QJ .rough-node .label,#mermaid-svg-8R9ugDHzlwvTR6QJ .node .label,#mermaid-svg-8R9ugDHzlwvTR6QJ .image-shape .label,#mermaid-svg-8R9ugDHzlwvTR6QJ .icon-shape .label{text-align:center;}#mermaid-svg-8R9ugDHzlwvTR6QJ .node.clickable{cursor:pointer;}#mermaid-svg-8R9ugDHzlwvTR6QJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8R9ugDHzlwvTR6QJ .arrowheadPath{fill:#333333;}#mermaid-svg-8R9ugDHzlwvTR6QJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8R9ugDHzlwvTR6QJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8R9ugDHzlwvTR6QJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8R9ugDHzlwvTR6QJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8R9ugDHzlwvTR6QJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8R9ugDHzlwvTR6QJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8R9ugDHzlwvTR6QJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8R9ugDHzlwvTR6QJ .cluster text{fill:#333;}#mermaid-svg-8R9ugDHzlwvTR6QJ .cluster span{color:#333;}#mermaid-svg-8R9ugDHzlwvTR6QJ 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-8R9ugDHzlwvTR6QJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8R9ugDHzlwvTR6QJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-8R9ugDHzlwvTR6QJ .icon-shape,#mermaid-svg-8R9ugDHzlwvTR6QJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8R9ugDHzlwvTR6QJ .icon-shape p,#mermaid-svg-8R9ugDHzlwvTR6QJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8R9ugDHzlwvTR6QJ .icon-shape .label rect,#mermaid-svg-8R9ugDHzlwvTR6QJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8R9ugDHzlwvTR6QJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8R9ugDHzlwvTR6QJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8R9ugDHzlwvTR6QJ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输出
处理
输入
nvml.Interface
spec.Config
info.Platform
NewDeviceMap
deviceMapBuilder.build
buildGPUDeviceMap
buildMigDeviceMap
assertAllMigDevicesAreValid
updateDeviceMapWithReplicas
DeviceMap
mapResourceNameDevices

5.2 设备分配数据流

#mermaid-svg-M8bXZzOv1T7ibo1o{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-M8bXZzOv1T7ibo1o .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-M8bXZzOv1T7ibo1o .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-M8bXZzOv1T7ibo1o .error-icon{fill:#552222;}#mermaid-svg-M8bXZzOv1T7ibo1o .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-M8bXZzOv1T7ibo1o .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-M8bXZzOv1T7ibo1o .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-M8bXZzOv1T7ibo1o .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-M8bXZzOv1T7ibo1o .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-M8bXZzOv1T7ibo1o .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-M8bXZzOv1T7ibo1o .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-M8bXZzOv1T7ibo1o .marker{fill:#333333;stroke:#333333;}#mermaid-svg-M8bXZzOv1T7ibo1o .marker.cross{stroke:#333333;}#mermaid-svg-M8bXZzOv1T7ibo1o svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-M8bXZzOv1T7ibo1o p{margin:0;}#mermaid-svg-M8bXZzOv1T7ibo1o .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-M8bXZzOv1T7ibo1o .cluster-label text{fill:#333;}#mermaid-svg-M8bXZzOv1T7ibo1o .cluster-label span{color:#333;}#mermaid-svg-M8bXZzOv1T7ibo1o .cluster-label span p{background-color:transparent;}#mermaid-svg-M8bXZzOv1T7ibo1o .label text,#mermaid-svg-M8bXZzOv1T7ibo1o span{fill:#333;color:#333;}#mermaid-svg-M8bXZzOv1T7ibo1o .node rect,#mermaid-svg-M8bXZzOv1T7ibo1o .node circle,#mermaid-svg-M8bXZzOv1T7ibo1o .node ellipse,#mermaid-svg-M8bXZzOv1T7ibo1o .node polygon,#mermaid-svg-M8bXZzOv1T7ibo1o .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-M8bXZzOv1T7ibo1o .rough-node .label text,#mermaid-svg-M8bXZzOv1T7ibo1o .node .label text,#mermaid-svg-M8bXZzOv1T7ibo1o .image-shape .label,#mermaid-svg-M8bXZzOv1T7ibo1o .icon-shape .label{text-anchor:middle;}#mermaid-svg-M8bXZzOv1T7ibo1o .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-M8bXZzOv1T7ibo1o .rough-node .label,#mermaid-svg-M8bXZzOv1T7ibo1o .node .label,#mermaid-svg-M8bXZzOv1T7ibo1o .image-shape .label,#mermaid-svg-M8bXZzOv1T7ibo1o .icon-shape .label{text-align:center;}#mermaid-svg-M8bXZzOv1T7ibo1o .node.clickable{cursor:pointer;}#mermaid-svg-M8bXZzOv1T7ibo1o .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-M8bXZzOv1T7ibo1o .arrowheadPath{fill:#333333;}#mermaid-svg-M8bXZzOv1T7ibo1o .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-M8bXZzOv1T7ibo1o .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-M8bXZzOv1T7ibo1o .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-M8bXZzOv1T7ibo1o .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-M8bXZzOv1T7ibo1o .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-M8bXZzOv1T7ibo1o .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-M8bXZzOv1T7ibo1o .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-M8bXZzOv1T7ibo1o .cluster text{fill:#333;}#mermaid-svg-M8bXZzOv1T7ibo1o .cluster span{color:#333;}#mermaid-svg-M8bXZzOv1T7ibo1o 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-M8bXZzOv1T7ibo1o .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-M8bXZzOv1T7ibo1o rect.text{fill:none;stroke-width:0;}#mermaid-svg-M8bXZzOv1T7ibo1o .icon-shape,#mermaid-svg-M8bXZzOv1T7ibo1o .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-M8bXZzOv1T7ibo1o .icon-shape p,#mermaid-svg-M8bXZzOv1T7ibo1o .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-M8bXZzOv1T7ibo1o .icon-shape .label rect,#mermaid-svg-M8bXZzOv1T7ibo1o .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-M8bXZzOv1T7ibo1o .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-M8bXZzOv1T7ibo1o .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-M8bXZzOv1T7ibo1o :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 分布式分配
对齐分配
决策
输入


available: 可用设备ID列表
required: 必须分配的设备ID列表
size: 需要分配的总数
AlignedAllocationSupported?

无副本?
alignedAlloc
distributedAlloc
gpuallocator.NewDevices
拓扑感知策略
BestEffortPolicy.Allocate
计算候选设备
构建副本映射
负载均衡排序
逐个选择
\[\]string 设备ID列表

5.3 健康检查数据流

#mermaid-svg-sKRJPHxpnFQzz35W{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-sKRJPHxpnFQzz35W .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-sKRJPHxpnFQzz35W .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-sKRJPHxpnFQzz35W .error-icon{fill:#552222;}#mermaid-svg-sKRJPHxpnFQzz35W .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-sKRJPHxpnFQzz35W .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-sKRJPHxpnFQzz35W .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-sKRJPHxpnFQzz35W .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-sKRJPHxpnFQzz35W .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-sKRJPHxpnFQzz35W .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-sKRJPHxpnFQzz35W .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-sKRJPHxpnFQzz35W .marker{fill:#333333;stroke:#333333;}#mermaid-svg-sKRJPHxpnFQzz35W .marker.cross{stroke:#333333;}#mermaid-svg-sKRJPHxpnFQzz35W svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-sKRJPHxpnFQzz35W p{margin:0;}#mermaid-svg-sKRJPHxpnFQzz35W .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-sKRJPHxpnFQzz35W .cluster-label text{fill:#333;}#mermaid-svg-sKRJPHxpnFQzz35W .cluster-label span{color:#333;}#mermaid-svg-sKRJPHxpnFQzz35W .cluster-label span p{background-color:transparent;}#mermaid-svg-sKRJPHxpnFQzz35W .label text,#mermaid-svg-sKRJPHxpnFQzz35W span{fill:#333;color:#333;}#mermaid-svg-sKRJPHxpnFQzz35W .node rect,#mermaid-svg-sKRJPHxpnFQzz35W .node circle,#mermaid-svg-sKRJPHxpnFQzz35W .node ellipse,#mermaid-svg-sKRJPHxpnFQzz35W .node polygon,#mermaid-svg-sKRJPHxpnFQzz35W .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-sKRJPHxpnFQzz35W .rough-node .label text,#mermaid-svg-sKRJPHxpnFQzz35W .node .label text,#mermaid-svg-sKRJPHxpnFQzz35W .image-shape .label,#mermaid-svg-sKRJPHxpnFQzz35W .icon-shape .label{text-anchor:middle;}#mermaid-svg-sKRJPHxpnFQzz35W .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-sKRJPHxpnFQzz35W .rough-node .label,#mermaid-svg-sKRJPHxpnFQzz35W .node .label,#mermaid-svg-sKRJPHxpnFQzz35W .image-shape .label,#mermaid-svg-sKRJPHxpnFQzz35W .icon-shape .label{text-align:center;}#mermaid-svg-sKRJPHxpnFQzz35W .node.clickable{cursor:pointer;}#mermaid-svg-sKRJPHxpnFQzz35W .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-sKRJPHxpnFQzz35W .arrowheadPath{fill:#333333;}#mermaid-svg-sKRJPHxpnFQzz35W .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-sKRJPHxpnFQzz35W .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-sKRJPHxpnFQzz35W .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sKRJPHxpnFQzz35W .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-sKRJPHxpnFQzz35W .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sKRJPHxpnFQzz35W .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-sKRJPHxpnFQzz35W .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-sKRJPHxpnFQzz35W .cluster text{fill:#333;}#mermaid-svg-sKRJPHxpnFQzz35W .cluster span{color:#333;}#mermaid-svg-sKRJPHxpnFQzz35W 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-sKRJPHxpnFQzz35W .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-sKRJPHxpnFQzz35W rect.text{fill:none;stroke-width:0;}#mermaid-svg-sKRJPHxpnFQzz35W .icon-shape,#mermaid-svg-sKRJPHxpnFQzz35W .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sKRJPHxpnFQzz35W .icon-shape p,#mermaid-svg-sKRJPHxpnFQzz35W .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-sKRJPHxpnFQzz35W .icon-shape .label rect,#mermaid-svg-sKRJPHxpnFQzz35W .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sKRJPHxpnFQzz35W .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-sKRJPHxpnFQzz35W .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-sKRJPHxpnFQzz35W :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输出
事件循环
初始化
非XidCritical
XidCritical
禁用
启用
匹配
不匹配
getDisabledHealthCheckXids
nvml.Init
EventSetCreate
注册事件掩码
eventSet.Wait 5s
EventType?
跳过非XidCritical
XID被禁用?
获取事件设备UUID
MIG GI/CI匹配?
标记unhealthy
unhealthy chan<- *Device


六、Manager 继承与平台策略

6.1 三平台对比

#mermaid-svg-ZMOlXFkoZ4WGxyBw{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-ZMOlXFkoZ4WGxyBw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .error-icon{fill:#552222;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .marker.cross{stroke:#333333;}#mermaid-svg-ZMOlXFkoZ4WGxyBw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZMOlXFkoZ4WGxyBw p{margin:0;}#mermaid-svg-ZMOlXFkoZ4WGxyBw g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-ZMOlXFkoZ4WGxyBw g.classGroup text .title{font-weight:bolder;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .cluster-label text{fill:#333;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .cluster-label span{color:#333;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .cluster-label span p{background-color:transparent;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .cluster text{fill:#333;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .cluster span{color:#333;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .nodeLabel,#mermaid-svg-ZMOlXFkoZ4WGxyBw .edgeLabel{color:#131300;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .label text{fill:#131300;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .labelBkg{background:#ECECFF;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .classTitle{font-weight:bolder;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .node rect,#mermaid-svg-ZMOlXFkoZ4WGxyBw .node circle,#mermaid-svg-ZMOlXFkoZ4WGxyBw .node ellipse,#mermaid-svg-ZMOlXFkoZ4WGxyBw .node polygon,#mermaid-svg-ZMOlXFkoZ4WGxyBw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-ZMOlXFkoZ4WGxyBw g.clickable{cursor:pointer;}#mermaid-svg-ZMOlXFkoZ4WGxyBw g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-ZMOlXFkoZ4WGxyBw g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .dashed-line{stroke-dasharray:3;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-ZMOlXFkoZ4WGxyBw #compositionStart,#mermaid-svg-ZMOlXFkoZ4WGxyBw .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ZMOlXFkoZ4WGxyBw #compositionEnd,#mermaid-svg-ZMOlXFkoZ4WGxyBw .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ZMOlXFkoZ4WGxyBw #dependencyStart,#mermaid-svg-ZMOlXFkoZ4WGxyBw .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ZMOlXFkoZ4WGxyBw #dependencyStart,#mermaid-svg-ZMOlXFkoZ4WGxyBw .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ZMOlXFkoZ4WGxyBw #extensionStart,#mermaid-svg-ZMOlXFkoZ4WGxyBw .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ZMOlXFkoZ4WGxyBw #extensionEnd,#mermaid-svg-ZMOlXFkoZ4WGxyBw .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ZMOlXFkoZ4WGxyBw #aggregationStart,#mermaid-svg-ZMOlXFkoZ4WGxyBw .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ZMOlXFkoZ4WGxyBw #aggregationEnd,#mermaid-svg-ZMOlXFkoZ4WGxyBw .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ZMOlXFkoZ4WGxyBw #lollipopStart,#mermaid-svg-ZMOlXFkoZ4WGxyBw .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ZMOlXFkoZ4WGxyBw #lollipopEnd,#mermaid-svg-ZMOlXFkoZ4WGxyBw .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZMOlXFkoZ4WGxyBw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZMOlXFkoZ4WGxyBw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} resourceManager
+config *spec.Config
+resource ResourceName
+devices Devices
+CheckHealth() : --- 默认禁用
+GetDevicePaths() : --- 仅设备路径
+GetPreferredAllocation() : --- distributedAlloc
nvmlResourceManager
+nvml nvml.Interface
+CheckHealth() : --- Xid事件监控
+GetDevicePaths() : --- 附加公共设备
+GetPreferredAllocation() : --- alignedAlloc优先
<<使用基础resourceManager>>
tegraResourceManager
<<使用基础resourceManager>>
wslResourceManager

6.2 平台能力矩阵

能力 NVML Tegra WSL
设备发现 NVML遍历 硬编码单设备 硬编码单设备
设备路径 /dev/nvidiaN /dev/dxg
MIG支持
健康检查 ✅ Xid事件
对齐分配 ✅ gpuallocator
分布式分配
NUMA拓扑 ✅ sysfs读取
公共设备路径 ✅ nvidiactl等
副本/共享

七、关键设计模式与总结

7.1 设计模式

  1. 策略模式deviceInfo 接口 + 多后端实现(NVML/Tegra/WSL),newGPUDevice 工厂函数实现平台切换
  2. 模板方法resourceManager 提供默认实现,nvmlResourceManager 覆写关键方法
  3. 装饰器模式nvmlResourceManager 嵌入 resourceManager 并扩展功能
  4. 工厂模式NewNVMLResourceManagers / NewTegraResourceManagers 作为工厂入口
  5. 观察者模式:健康检查通过 NVML 事件订阅 + channel 通知

7.2 AnnotatedID 设计精髓

复制代码
原始GPU UUID: GPU-abc-123
    ↓ 时间分片(Replicas=4)
副本ID:
    GPU-abc-123::0  (副本0)
    GPU-abc-123::1  (副本1)
    GPU-abc-123::2  (副本2)
    GPU-abc-123::3  (副本3)
  • kubelet看到4个独立"设备"
  • 实际共享同一物理GPU
  • :: 分隔符确保不与UUID格式冲突
  • GetUUID() 去除后缀即可获得原始UUID

7.3 健康检查事件掩码

复制代码
eventMask = XidCriticalError | DoubleBitEccError | SingleBitEccError
  • XidCriticalError: GPU致命错误(如XID 48 ECC双重位错误)
  • DoubleBitEccError: 双位ECC错误(不可纠正)
  • SingleBitEccError: 单位ECC错误(可纠正但需关注)

7.4 MIG 设备路径三层结构

MIG设备挂载到容器需要3个路径:

  1. 父GPU设备 : /dev/nvidia0 --- 物理GPU字符设备
  2. GI access : /proc/driver/nvidia/capabilities/gpu0/mig/gi1/access --- GPU实例访问权限
  3. CI access : /proc/driver/nvidia/capabilities/gpu0/mig/gi1/ci0/access --- 计算实例访问权限

这种设计确保容器只能访问被分配的MIG切片,而非整个GPU。

7.5 配置驱动架构

整个模块高度依赖 spec.Config 配置:

  • config.Flags.MigStrategy --- 决定MIG设备处理方式
  • config.Resources.GPUs/MIGs --- 决定设备名匹配规则
  • config.Sharing --- 决定共享策略和副本数
  • config.Flags.FailOnInitError --- 决定NVML初始化失败行为

这种配置驱动设计使得同一份代码可以适应不同的部署场景(纯GPU、MIG单一切片、MIG混合切片、时间分片共享、MPS共享等)。


附录:文件依赖关系

#mermaid-svg-xXKwpSuOohZFNIoT{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-xXKwpSuOohZFNIoT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xXKwpSuOohZFNIoT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xXKwpSuOohZFNIoT .error-icon{fill:#552222;}#mermaid-svg-xXKwpSuOohZFNIoT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xXKwpSuOohZFNIoT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xXKwpSuOohZFNIoT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xXKwpSuOohZFNIoT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xXKwpSuOohZFNIoT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xXKwpSuOohZFNIoT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xXKwpSuOohZFNIoT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xXKwpSuOohZFNIoT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xXKwpSuOohZFNIoT .marker.cross{stroke:#333333;}#mermaid-svg-xXKwpSuOohZFNIoT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xXKwpSuOohZFNIoT p{margin:0;}#mermaid-svg-xXKwpSuOohZFNIoT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xXKwpSuOohZFNIoT .cluster-label text{fill:#333;}#mermaid-svg-xXKwpSuOohZFNIoT .cluster-label span{color:#333;}#mermaid-svg-xXKwpSuOohZFNIoT .cluster-label span p{background-color:transparent;}#mermaid-svg-xXKwpSuOohZFNIoT .label text,#mermaid-svg-xXKwpSuOohZFNIoT span{fill:#333;color:#333;}#mermaid-svg-xXKwpSuOohZFNIoT .node rect,#mermaid-svg-xXKwpSuOohZFNIoT .node circle,#mermaid-svg-xXKwpSuOohZFNIoT .node ellipse,#mermaid-svg-xXKwpSuOohZFNIoT .node polygon,#mermaid-svg-xXKwpSuOohZFNIoT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xXKwpSuOohZFNIoT .rough-node .label text,#mermaid-svg-xXKwpSuOohZFNIoT .node .label text,#mermaid-svg-xXKwpSuOohZFNIoT .image-shape .label,#mermaid-svg-xXKwpSuOohZFNIoT .icon-shape .label{text-anchor:middle;}#mermaid-svg-xXKwpSuOohZFNIoT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xXKwpSuOohZFNIoT .rough-node .label,#mermaid-svg-xXKwpSuOohZFNIoT .node .label,#mermaid-svg-xXKwpSuOohZFNIoT .image-shape .label,#mermaid-svg-xXKwpSuOohZFNIoT .icon-shape .label{text-align:center;}#mermaid-svg-xXKwpSuOohZFNIoT .node.clickable{cursor:pointer;}#mermaid-svg-xXKwpSuOohZFNIoT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xXKwpSuOohZFNIoT .arrowheadPath{fill:#333333;}#mermaid-svg-xXKwpSuOohZFNIoT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xXKwpSuOohZFNIoT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xXKwpSuOohZFNIoT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xXKwpSuOohZFNIoT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xXKwpSuOohZFNIoT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xXKwpSuOohZFNIoT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xXKwpSuOohZFNIoT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xXKwpSuOohZFNIoT .cluster text{fill:#333;}#mermaid-svg-xXKwpSuOohZFNIoT .cluster span{color:#333;}#mermaid-svg-xXKwpSuOohZFNIoT 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-xXKwpSuOohZFNIoT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xXKwpSuOohZFNIoT rect.text{fill:none;stroke-width:0;}#mermaid-svg-xXKwpSuOohZFNIoT .icon-shape,#mermaid-svg-xXKwpSuOohZFNIoT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xXKwpSuOohZFNIoT .icon-shape p,#mermaid-svg-xXKwpSuOohZFNIoT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xXKwpSuOohZFNIoT .icon-shape .label rect,#mermaid-svg-xXKwpSuOohZFNIoT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xXKwpSuOohZFNIoT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xXKwpSuOohZFNIoT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xXKwpSuOohZFNIoT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} rm.go

ResourceManager接口+基础实现
devices.go

Device/Devices/AnnotatedID
device_map.go

DeviceMap构建+副本管理
health.go

Xid健康检查
allocate.go

分布式分配算法
helper.go

uint8Slice辅助
nvml_devices.go

NVML deviceInfo实现
nvml_manager.go

NVML ResourceManager
tegra_devices.go

Tegra deviceInfo实现
tegra_manager.go

Tegra ResourceManager
wsl_devices.go

WSL deviceInfo实现


分析完成。本文档基于 NVIDIA k8s-device-plugin v0.19.3 internal/rm 模块源码,逐文件、逐函数进行深度解析,所有内容严格对应代码实现。

相关推荐
小小工匠2 小时前
Skill - 把无限画布装进 Codex:Cowart 的架构拆解与实践指南
架构·cowart
roman_日积跬步-终至千里2 小时前
【从零开始学架构】DDIA 精要:一套关于“数据系统架构”的分层理论
架构
亲爱的马哥2 小时前
Vue3 + Element Plus 低代码表单设计器架构拆解与私有化落地实践
低代码·架构·敏捷流程
Chengbei113 小时前
云安全漏洞挖掘SKILL、一站式云漏洞挖掘工具,支持S3爆破、IMDS探测、K8s检测与AK/SK权限利用
前端·人工智能·网络安全·云原生·容器·kubernetes·系统安全
LONGZETECH3 小时前
工业实训仿真设计实践:电机拆装软件的 DAG 流程建模、工具精度分级与数据体系搭建
大数据·算法·unity·架构·汽车
Ai拆代码的曹操4 小时前
K8s 调度器 predicate 阶段揭秘:为什么你的 Pod 总是堆在同一台机器
后端·容器
Ai拆代码的曹操4 小时前
手摸手排查:Pod CrashLoopBackOff 日志丢失问题,3 层兜底方案
后端·容器
瞬间&永恒~5 小时前
【MySQL】练习5-1:配置慢查询日志
linux·运维·云原生
张忠琳5 小时前
【NVIDIA】k8s-device-plugin v0.19.3 — CDI / MIG / vGPU 模块超深度代码分析之五
云原生·容器·架构·kubernetes·nvidia