1+ //go:build linux 
2+ 
3+ package  gpuinfo
4+ 
5+ import  (
6+ 	"bufio" 
7+ 	"os" 
8+ 	"path/filepath" 
9+ 	"regexp" 
10+ 	"sort" 
11+ 	"strconv" 
12+ 	"strings" 
13+ )
14+ 
15+ // supportedAMDGPUs are the AMD GPU targets that should use ROCm 
16+ var  supportedAMDGPUs  =  map [string ]bool {
17+ 	"gfx908" :  true ,
18+ 	"gfx90a" :  true ,
19+ 	"gfx942" :  true ,
20+ 	"gfx1010" : true ,
21+ 	"gfx1030" : true ,
22+ 	"gfx1100" : true ,
23+ 	"gfx1200" : true ,
24+ 	"gfx1201" : true ,
25+ 	"gfx1151" : true ,
26+ }
27+ 
28+ func  hasSupportedAMDGPU () (bool , error ) {
29+ 	// Check if KFD topology directory exists 
30+ 	topologyDir  :=  "/sys/class/kfd/kfd/topology/nodes/" 
31+ 	info , err  :=  os .Stat (topologyDir )
32+ 	if  err  !=  nil  ||  ! info .IsDir () {
33+ 		return  false , nil  // KFD not available 
34+ 	}
35+ 
36+ 	entries , err  :=  os .ReadDir (topologyDir )
37+ 	if  err  !=  nil  {
38+ 		return  false , err 
39+ 	}
40+ 
41+ 	// Sort entries by name to maintain consistent order 
42+ 	sort .Slice (entries , func (i , j  int ) bool  {
43+ 		return  entries [i ].Name () <  entries [j ].Name ()
44+ 	})
45+ 
46+ 	// Compile regex to match gfx_target_version lines 
47+ 	reTarget  :=  regexp .MustCompile (`gfx_target_version[ \t]+([0-9]+)` )
48+ 
49+ 	for  _ , e  :=  range  entries  {
50+ 		if  ! e .IsDir () {
51+ 			continue 
52+ 		}
53+ 		nodePath  :=  filepath .Join (topologyDir , e .Name ())
54+ 		propPath  :=  filepath .Join (nodePath , "properties" )
55+ 
56+ 		// Attempt to open the properties file directly; skip on error (e.g., permissions) 
57+ 		f , err  :=  os .Open (propPath )
58+ 		if  err  !=  nil  {
59+ 			// Could be permission denied or file doesn't exist; just skip like the Python code 
60+ 			continue 
61+ 		}
62+ 
63+ 		sc  :=  bufio .NewScanner (f )
64+ 		for  sc .Scan () {
65+ 			line  :=  sc .Text ()
66+ 			matches  :=  reTarget .FindStringSubmatch (line )
67+ 			if  len (matches ) <  2  {
68+ 				continue 
69+ 			}
70+ 
71+ 			deviceIDStr  :=  matches [1 ]
72+ 			deviceID , err  :=  strconv .Atoi (deviceIDStr )
73+ 			if  err  !=  nil  ||  deviceID  ==  0  {
74+ 				continue 
75+ 			}
76+ 
77+ 			var  majorVer , minorVer , steppingVer  int 
78+ 			if  gfxOverride  :=  os .Getenv ("HSA_OVERRIDE_GFX_VERSION" ); gfxOverride  !=  ""  {
79+ 				parts  :=  strings .Split (strings .TrimSpace (gfxOverride ), "." )
80+ 				if  len (parts ) !=  3  {
81+ 					// Invalid format, skip 
82+ 					continue 
83+ 				}
84+ 				mv , err1  :=  strconv .Atoi (parts [0 ])
85+ 				nv , err2  :=  strconv .Atoi (parts [1 ])
86+ 				sv , err3  :=  strconv .Atoi (parts [2 ])
87+ 				if  err1  !=  nil  ||  err2  !=  nil  ||  err3  !=  nil  {
88+ 					// Invalid format, skip 
89+ 					continue 
90+ 				}
91+ 				if  mv  >  63  ||  nv  >  255  ||  sv  >  255  {
92+ 					// Invalid values, skip 
93+ 					continue 
94+ 				}
95+ 				majorVer , minorVer , steppingVer  =  mv , nv , sv 
96+ 			} else  {
97+ 				majorVer  =  (deviceID  /  10000 ) %  100 
98+ 				minorVer  =  (deviceID  /  100 ) %  100 
99+ 				steppingVer  =  deviceID  %  100 
100+ 			}
101+ 
102+ 			gfx  :=  "gfx"  + 
103+ 				strconv .FormatInt (int64 (majorVer ), 10 ) + 
104+ 				strconv .FormatInt (int64 (minorVer ), 16 ) + 
105+ 				strconv .FormatInt (int64 (steppingVer ), 16 )
106+ 
107+ 			if  supportedAMDGPUs [gfx ] {
108+ 				f .Close ()
109+ 				return  true , nil  // Found a supported AMD GPU 
110+ 			}
111+ 		}
112+ 		f .Close ()
113+ 	}
114+ 
115+ 	return  false , nil  // No supported AMD GPU found 
116+ }
0 commit comments