hy-smi.go 3.78 KB
Newer Older
liming6's avatar
liming6 committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package gpu

import (
	"encoding/json"
	"get-container/utils"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
)

type HYVersionInfo struct {
	SMIVersion    string
	LibVersion    string
	DriverVersion string
}

type DCUInfo struct {
}

type DCUPidInfo struct {
	Pid             uint64
	PASId           uint64
	HCUNode         []string
	HCUIndex        []string
	GPUID           []string
	PCIBus          []string
	VRamUsed        utils.MemorySize
	VRamUsedPercent int
	SDMAUsed        int
}

var (
	ReEmptyLine   = regexp.MustCompile(`^\s*$`)
	ReUselessLine = regexp.MustCompile(`^=[ =a-zA-Z0-9]*=$`)
)

const (
	PIDHeader             = "PID"
	PASIDHeader           = "PASID"
	HCUNodeHeader         = "HCU Node(Include CPU sort)"
	HCUIndexHeader        = "HCU Index"
	GPUIDHeader           = "GPUID"
	PCIBusHeader          = "PCI BUS"
	VRamUsedHeader        = "VRAM USED(MiB)"
	VRamUsedPercentHeader = "VRAM USED(%)"
	SDMAUsedHeader        = "SDMA USED"
)

// GetDCUPidInfo 获取Pid相关信息
func GetDCUPidInfo() ([]DCUPidInfo, error) {
	output, err := exec.Command("hy-smi", "--showpids").Output()
	if err != nil {
		return nil, err
	}
	return parseDCUPidInfo(string(output))
}

func parseDCUPidInfo(s string) ([]DCUPidInfo, error) {
	lines := strings.Split(strings.Trim(string(s), "\n"), "\n")
	linesArray := make([][]string, 0)
	for _, line := range lines {
		if ReEmptyLine.MatchString(line) || ReUselessLine.MatchString(line) {
			continue
		}
		linesArray = append(linesArray, strings.SplitN(strings.TrimSpace(line), ":", 2))
	}
	infosArray := make([]map[string]string, 0)
	index := -1
	for _, line := range linesArray {
		if line == nil || len(line) != 2 {
			continue
		}
		line[1] = strings.TrimSpace(line[1])
		switch line[0] {
		case PIDHeader:
			index += 1
			infosArray = append(infosArray, make(map[string]string))
			infosArray[index][PIDHeader] = line[1]
			break
		case PASIDHeader:
			infosArray[index][PASIDHeader] = line[1]
			break
		case HCUNodeHeader:
			infosArray[index][HCUNodeHeader] = line[1]
			break
		case HCUIndexHeader:
			infosArray[index][HCUIndexHeader] = line[1]
			break
		case GPUIDHeader:
			infosArray[index][GPUIDHeader] = line[1]
			break
		case PCIBusHeader:
			infosArray[index][PCIBusHeader] = line[1]
			break
		case VRamUsedHeader:
			infosArray[index][VRamUsedHeader] = line[1]
			break
		case VRamUsedPercentHeader:
			infosArray[index][VRamUsedPercentHeader] = line[1]
			break
		case SDMAUsedHeader:
			infosArray[index][SDMAUsedHeader] = line[1]
			break
		default:
			break
		}
	}
	result := make([]DCUPidInfo, 0)
	if len(infosArray) == 0 {
		return result, nil
	}
	for _, info := range infosArray {
		i := DCUPidInfo{}
		pid, innerErr := strconv.ParseUint(info[PIDHeader], 10, 64)
		if innerErr != nil {
			return nil, innerErr
		}
		i.Pid = pid
		i.PASId, innerErr = strconv.ParseUint(info[PASIDHeader], 10, 64)
		if innerErr != nil {
			return nil, innerErr
		}
		_ = json.Unmarshal([]byte(strings.ReplaceAll(info[HCUNodeHeader], "'", `"`)), &i.HCUNode)
		_ = json.Unmarshal([]byte(strings.ReplaceAll(info[HCUIndexHeader], "'", `"`)), &i.HCUIndex)
		_ = json.Unmarshal([]byte(strings.ReplaceAll(info[GPUIDHeader], "'", `"`)), &i.GPUID)
		_ = json.Unmarshal([]byte(strings.ReplaceAll(info[PCIBusHeader], "'", `"`)), &i.PCIBus)
		s, innerErr := strconv.ParseUint(info[VRamUsedHeader], 10, 64)
		if innerErr != nil {
			return nil, innerErr
		}
		i.VRamUsed = utils.MemorySize{Num: s, Unit: utils.MiB}
		if info[VRamUsedPercentHeader] == "" || info[VRamUsedPercentHeader] == "inf" {
			i.VRamUsedPercent = -1
		} else {
			i.VRamUsedPercent, innerErr = strconv.Atoi(info[VRamUsedPercentHeader])
			if innerErr != nil {
				return nil, innerErr
			}
		}
		i.SDMAUsed, innerErr = strconv.Atoi(info[SDMAUsedHeader])
		if innerErr != nil {
			return nil, innerErr
		}
		result = append(result, i)
	}
	return result, nil
}