Add NumaDomainList and SMTList

This commit is contained in:
Holger Obermaier 2023-09-07 13:49:22 +02:00
parent 8fedef9024
commit fbf178326a

View File

@ -34,6 +34,9 @@ var cache struct {
HwthreadList []int HwthreadList []int
uniqHwthreadList []int uniqHwthreadList []int
SMTList []int
uniqSMTList []int
CoreList []int CoreList []int
uniqCoreList []int uniqCoreList []int
@ -43,6 +46,9 @@ var cache struct {
DieList []int DieList []int
uniqDieList []int uniqDieList []int
NumaDomainList []int
uniqNumaDomainList []int
CpuData []HwthreadEntry CpuData []HwthreadEntry
} }
@ -86,11 +92,68 @@ func init() {
} }
} }
getSMT :=
func(cpuID int, basePath string) int {
// Read thread sibling list
buffer, err := os.ReadFile(filepath.Join(basePath, "thread_siblings_list"))
if err != nil {
cclogger.ComponentError("CCTopology", "init", err.Error())
}
// Create thread sibling list
threadList := make([]int, 0)
stringBuffer := strings.TrimSpace(string(buffer))
for _, x := range strings.Split(stringBuffer, ",") {
id, err := strconv.Atoi(x)
if err != nil {
cclogger.ComponentError("CCTopology", "init", err.Error())
}
threadList = append(threadList, id)
}
// Find index of CPU ID in thread sibling list
// if not found return -1
return slices.Index(threadList, cpuID)
}
getNumaDomain :=
func(basePath string) int {
globPath := filepath.Join(basePath, "node*")
regexPath := filepath.Join(basePath, "node([[:digit:]]+)")
regex := regexp.MustCompile(regexPath)
// File globbing for NUMA node
files, err := filepath.Glob(globPath)
if err != nil {
cclogger.ComponentError("CCTopology", "CpuData:getNumaDomain", err.Error())
}
if len(files) != 1 {
return -1
}
// Extract NUMA node ID
matches := regex.FindStringSubmatch(files[0])
if len(matches) != 2 {
return -1
}
id, err := strconv.Atoi(matches[1])
if err != nil {
return -1
}
return id
}
cache.DieList = make([]int, len(cache.HwthreadList)) cache.DieList = make([]int, len(cache.HwthreadList))
cache.SMTList = make([]int, len(cache.HwthreadList))
cache.NumaDomainList = make([]int, len(cache.HwthreadList))
for i, c := range cache.HwthreadList { for i, c := range cache.HwthreadList {
// Set base directory for topology lookup // Set base directory for topology lookup
cpuStr := fmt.Sprintf("cpu%d", c) base :=
base := filepath.Join("/sys/devices/system/cpu", cpuStr) filepath.Join(
"/sys/devices/system/cpu",
fmt.Sprintf("cpu%d", c),
)
topoBase := filepath.Join(base, "topology") topoBase := filepath.Join(base, "topology")
// Lookup CPU die id // Lookup CPU die id
@ -98,12 +161,22 @@ func init() {
if cache.DieList[i] < 0 { if cache.DieList[i] < 0 {
cache.DieList[i] = cache.SocketList[i] cache.DieList[i] = cache.SocketList[i]
} }
// Lookup SMT thread id
cache.SMTList[i] = getSMT(c, topoBase)
// Lookup NUMA domain id
cache.NumaDomainList[i] = getNumaDomain(base)
} }
cache.uniqHwthreadList = slices.Clone(cache.HwthreadList) cache.uniqHwthreadList = slices.Clone(cache.HwthreadList)
slices.Sort(cache.uniqHwthreadList) slices.Sort(cache.uniqHwthreadList)
cache.uniqHwthreadList = slices.Compact(cache.uniqHwthreadList) cache.uniqHwthreadList = slices.Compact(cache.uniqHwthreadList)
cache.uniqSMTList = slices.Clone(cache.SMTList)
slices.Sort(cache.uniqSMTList)
cache.uniqSMTList = slices.Compact(cache.uniqSMTList)
cache.uniqCoreList = slices.Clone(cache.CoreList) cache.uniqCoreList = slices.Clone(cache.CoreList)
slices.Sort(cache.uniqCoreList) slices.Sort(cache.uniqCoreList)
cache.uniqCoreList = slices.Compact(cache.uniqCoreList) cache.uniqCoreList = slices.Compact(cache.uniqCoreList)
@ -116,73 +189,22 @@ func init() {
slices.Sort(cache.uniqDieList) slices.Sort(cache.uniqDieList)
cache.uniqDieList = slices.Compact(cache.uniqDieList) cache.uniqDieList = slices.Compact(cache.uniqDieList)
getSMT := cache.uniqNumaDomainList = slices.Clone(cache.NumaDomainList)
func(cpuID int, basePath string) int { slices.Sort(cache.uniqNumaDomainList)
buffer, err := os.ReadFile(filepath.Join(basePath, "thread_siblings_list")) cache.uniqNumaDomainList = slices.Compact(cache.uniqNumaDomainList)
if err != nil {
cclogger.ComponentError("CCTopology", "CpuData:getSMT", err.Error())
}
threadList := make([]int, 0)
stringBuffer := strings.TrimSpace(string(buffer))
for _, x := range strings.Split(stringBuffer, ",") {
id, err := strconv.Atoi(x)
if err != nil {
cclogger.ComponentError("CCTopology", "CpuData:getSMT", err.Error())
}
threadList = append(threadList, id)
}
if i := slices.Index(threadList, cpuID); i != -1 {
return i
}
return 1
}
getNumaDomain :=
func(basePath string) int {
globPath := filepath.Join(basePath, "node*")
regexPath := filepath.Join(basePath, "node([[:digit:]]+)")
regex := regexp.MustCompile(regexPath)
files, err := filepath.Glob(globPath)
if err != nil {
cclogger.ComponentError("CCTopology", "CpuData:getNumaDomain", err.Error())
}
for _, file := range files {
matches := regex.FindStringSubmatch(file)
if len(matches) == 2 {
id, err := strconv.Atoi(matches[1])
if err == nil {
return id
}
}
}
return 0
}
cache.CpuData = make([]HwthreadEntry, len(cache.HwthreadList)) cache.CpuData = make([]HwthreadEntry, len(cache.HwthreadList))
for i := range cache.HwthreadList { for i := range cache.HwthreadList {
cache.CpuData[i] = cache.CpuData[i] =
HwthreadEntry{ HwthreadEntry{
CpuID: cache.HwthreadList[i], CpuID: cache.HwthreadList[i],
SMT: cache.SMTList[i],
Socket: cache.SocketList[i], Socket: cache.SocketList[i],
NumaDomain: -1, NumaDomain: cache.NumaDomainList[i],
Die: cache.DieList[i], Die: cache.DieList[i],
Core: cache.CoreList[i], Core: cache.CoreList[i],
} }
} }
for i := range cache.CpuData {
cEntry := &cache.CpuData[i]
// Set base directory for topology lookup
cpuStr := fmt.Sprintf("cpu%d", cEntry.CpuID)
base := filepath.Join("/sys/devices/system/cpu", cpuStr)
topoBase := filepath.Join(base, "topology")
// Lookup SMT thread id
cEntry.SMT = getSMT(cEntry.CpuID, topoBase)
// Lookup NUMA domain id
cEntry.NumaDomain = getNumaDomain(base)
}
} }
// fileToInt reads an integer value from a file // fileToInt reads an integer value from a file
@ -227,56 +249,13 @@ func CoreList() []int {
// Get list of NUMA node IDs // Get list of NUMA node IDs
func NumaNodeList() []int { func NumaNodeList() []int {
numaList := make([]int, 0) return slices.Clone(cache.uniqNumaDomainList)
globPath := filepath.Join(SYSFS_NUMABASE, "node*")
regexPath := filepath.Join(SYSFS_NUMABASE, "node(\\d+)")
regex := regexp.MustCompile(regexPath)
files, err := filepath.Glob(globPath)
if err != nil {
cclogger.ComponentError("CCTopology", "NumaNodeList", err.Error())
}
for _, f := range files {
if !regex.MatchString(f) {
continue
}
finfo, err := os.Lstat(f)
if err != nil {
continue
}
if !finfo.IsDir() {
continue
}
matches := regex.FindStringSubmatch(f)
if len(matches) == 2 {
id, err := strconv.Atoi(matches[1])
if err == nil {
if found := slices.Contains(numaList, id); !found {
numaList = append(numaList, id)
}
}
}
}
return numaList
} }
// DieList gets the list of CPU die IDs // DieList gets the list of CPU die IDs
func DieList() []int { func DieList() []int {
cpuList := HwthreadList() if len(cache.uniqDieList) > 0 {
dieList := make([]int, 0) return slices.Clone(cache.uniqDieList)
for _, c := range cpuList {
diePath := filepath.Join(
SYSFS_CPUBASE,
fmt.Sprintf("cpu%d", c),
"topology/die_id")
dieID := fileToInt(diePath)
if dieID > 0 {
if found := slices.Contains(dieList, dieID); !found {
dieList = append(dieList, dieID)
}
}
}
if len(dieList) > 0 {
return dieList
} }
return SocketList() return SocketList()
} }
@ -316,21 +295,9 @@ type CpuInformation struct {
// CpuInformation reports basic information about the CPU // CpuInformation reports basic information about the CPU
func CpuInfo() CpuInformation { func CpuInfo() CpuInformation {
smtList := make([]int, 0)
numaList := make([]int, 0)
for i := range cache.CpuData {
d := &cache.CpuData[i]
if ok := slices.Contains(smtList, d.SMT); !ok {
smtList = append(smtList, d.SMT)
}
if ok := slices.Contains(numaList, d.NumaDomain); !ok {
numaList = append(numaList, d.NumaDomain)
}
}
return CpuInformation{ return CpuInformation{
NumNumaDomains: len(numaList), NumNumaDomains: len(cache.uniqNumaDomainList),
SMTWidth: len(smtList), SMTWidth: len(cache.uniqSMTList),
NumDies: len(cache.uniqDieList), NumDies: len(cache.uniqDieList),
NumCores: len(cache.uniqCoreList), NumCores: len(cache.uniqCoreList),
NumSockets: len(cache.uniqSocketList), NumSockets: len(cache.uniqSocketList),