NVIDIA k8s-device-plugin v0.19.3 资源管理器模块深度分析
模块路径:
internal/rm分析版本: v0.19.3
文件数: 11
一、模块定位
1.1 业务职责
internal/rm 是 NVIDIA k8s-device-plugin 的资源管理核心模块,负责:
- 设备发现:通过 NVML / Tegra / WSL 三种后端发现 GPU 及 MIG 设备
- 设备映射:将物理设备映射到 Kubernetes 可识别的 ResourceName
- 设备共享:支持时间分片(TimeSlicing)和 MPS 两种共享策略下的设备副本(replica)管理
- 设备分配:提供 PreferredAllocation 算法,支持对齐分配(AlignedAlloc)和分布式分配(DistributedAlloc)
- 健康检查:基于 NVML Xid 事件 + ECC 错误的实时设备健康监控
- 请求校验:校验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嵌入提供了ID、Health、Topology三个字段,这是 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)
Devices 是 map[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/gpu、nvidia.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/gpuMigStrategyMixed: 每个 MIG profile(如1g.10gb、2g.20gb)对应独立的资源名nvidia.com/mig-1g.10gbC == 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 设计模式
- 策略模式 :
deviceInfo接口 + 多后端实现(NVML/Tegra/WSL),newGPUDevice工厂函数实现平台切换 - 模板方法 :
resourceManager提供默认实现,nvmlResourceManager覆写关键方法 - 装饰器模式 :
nvmlResourceManager嵌入resourceManager并扩展功能 - 工厂模式 :
NewNVMLResourceManagers/NewTegraResourceManagers作为工厂入口 - 观察者模式:健康检查通过 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个路径:
- 父GPU设备 :
/dev/nvidia0--- 物理GPU字符设备 - GI access :
/proc/driver/nvidia/capabilities/gpu0/mig/gi1/access--- GPU实例访问权限 - 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 模块源码,逐文件、逐函数进行深度解析,所有内容严格对应代码实现。