2024-10-17 08:45:00 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  discover  
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"bufio" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"errors" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"io" 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-12 02:38:25 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"io/fs" 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"log/slog" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"os" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"path/filepath" 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"regexp" 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"slices" 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-25 04:43:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"sort" 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"strconv" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-09 02:11:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/ollama/ollama/envconfig" 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/ollama/ollama/format" 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Discovery logic for AMD/ROCm GPUs
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									DriverVersionFile      =  "/sys/module/amdgpu/version" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AMDNodesSysfsDir       =  "/sys/class/kfd/kfd/topology/nodes/" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									GPUPropertiesFileGlob  =  AMDNodesSysfsDir  +  "*/properties" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Prefix with the node dir
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									GPUTotalMemoryFileGlob  =  "mem_banks/*/properties"  // size_in_bytes line
 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Direct Rendering Manager sysfs location
 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-19 03:34:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									DRMDeviceDirGlob    =  "/sys/class/drm/card*/device" 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									DRMTotalMemoryFile  =  "mem_info_vram_total" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									DRMUsedMemoryFile   =  "mem_info_vram_used" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// In hex; properties file is in decimal
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									DRMUniqueIDFile  =  "unique_id" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									DRMVendorFile    =  "vendor" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									DRMDeviceFile    =  "device" 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Used to validate if the given ROCm lib is usable
 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-02 06:47:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ROCmLibGlobs           =  [ ] string { "libhipblas.so.2*" ,  "rocblas" }  // TODO - probably include more coverage of files here...
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RocmStandardLocations  =  [ ] string { "/opt/rocm/lib" ,  "/usr/lib64" } 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Gather GPU information from the amdgpu driver if any supported GPUs are detected
  
						 
					
						
							
								
									
										
										
										
											2024-10-15 07:26:45 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// Only called once during bootstrap
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  AMDGetGPUInfo ( )  ( [ ] RocmGPUInfo ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2024-05-16 06:13:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									resp  :=  [ ] RocmGPUInfo { } 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ! AMDDetected ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-15 07:26:45 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  resp ,  fmt . Errorf ( "AMD GPUs not detected" ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Opportunistic logging of driver version to aid in troubleshooting
 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									driverMajor ,  driverMinor ,  err  :=  AMDDriverVersion ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										// TODO - if we see users crash and burn with the upstreamed kernel this can be adjusted to hard-fail rocm support and fallback to CPU
 
							 
						 
					
						
							
								
									
										
										
										
											2025-07-31 03:02:54 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										slog . Warn ( "ollama recommends running the https://www.amd.com/en/support/download/linux-drivers.html" ,  "error" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Determine if the user has already pre-selected which GPUs to look at, then ignore the others
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  visibleDevices  [ ] string 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-04 10:30:19 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									hipVD  :=  envconfig . HipVisibleDevices ( )    // zero based index only
 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-27 05:04:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									rocrVD  :=  envconfig . RocrVisibleDevices ( )  // zero based index or UUID
 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-04 10:30:19 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									gpuDO  :=  envconfig . GpuDeviceOrdinal ( )     // zero based index
 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									switch  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  rocrVD  !=  "" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										visibleDevices  =  strings . Split ( rocrVD ,  "," ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-27 05:04:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  hipVD  !=  "" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										visibleDevices  =  strings . Split ( hipVD ,  "," ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									case  gpuDO  !=  "" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										visibleDevices  =  strings . Split ( gpuDO ,  "," ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-04 10:30:19 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									gfxOverride  :=  envconfig . HsaOverrideGfxVersion ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									var  supported  [ ] string 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-30 07:03:38 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  libDir  string 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// The amdgpu driver always exposes the host CPU(s) first, but we have to skip them and subtract
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// from the other IDs to get alignment with the HIP libraries expectations (zero is the first GPU, not the CPU)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									matches ,  _  :=  filepath . Glob ( GPUPropertiesFileGlob ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-25 04:43:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									sort . Slice ( matches ,  func ( i ,  j  int )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// /sys/class/kfd/kfd/topology/nodes/<number>/properties
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										a ,  err  :=  strconv . ParseInt ( filepath . Base ( filepath . Dir ( matches [ i ] ) ) ,  10 ,  64 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											slog . Debug ( "parse err" ,  "error" ,  err ,  "match" ,  matches [ i ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										b ,  err  :=  strconv . ParseInt ( filepath . Base ( filepath . Dir ( matches [ j ] ) ) ,  10 ,  64 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											slog . Debug ( "parse err" ,  "error" ,  err ,  "match" ,  matches [ i ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  a  <  b 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-27 05:04:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									gpuCount  :=  0 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-30 03:21:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									gpuOrdinalID  :=  0 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									for  _ ,  match  :=  range  matches  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slog . Debug ( "evaluating amdgpu node "  +  match ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fp ,  err  :=  os . Open ( match ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											slog . Debug ( "failed to open sysfs node" ,  "file" ,  match ,  "error" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										defer  fp . Close ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										scanner  :=  bufio . NewScanner ( fp ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										isCPU  :=  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  major ,  minor ,  patch  uint64 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										var  vendor ,  device ,  uniqueID  uint64 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										for  scanner . Scan ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											line  :=  strings . TrimSpace ( scanner . Text ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Note: we could also use "cpu_cores_count X" where X is greater than zero to detect CPUs
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  strings . HasPrefix ( line ,  "gfx_target_version" )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ver  :=  strings . Fields ( line ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												// Detect CPUs
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  len ( ver )  ==  2  &&  ver [ 1 ]  ==  "0"  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													slog . Debug ( "detected CPU "  +  match ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													isCPU  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												if  len ( ver )  !=  2  ||  len ( ver [ 1 ] )  <  5  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													slog . Warn ( "malformed " + match ,  "gfx_target_version" ,  line ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													// If this winds up being a CPU, our offsets may be wrong
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												l  :=  len ( ver [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												var  err1 ,  err2 ,  err3  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												patch ,  err1  =  strconv . ParseUint ( ver [ 1 ] [ l - 2 : l ] ,  10 ,  32 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												minor ,  err2  =  strconv . ParseUint ( ver [ 1 ] [ l - 4 : l - 2 ] ,  10 ,  32 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												major ,  err3  =  strconv . ParseUint ( ver [ 1 ] [ : l - 4 ] ,  10 ,  32 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  err1  !=  nil  ||  err2  !=  nil  ||  err3  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													slog . Debug ( "malformed int "  +  line ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											}  else  if  strings . HasPrefix ( line ,  "vendor_id" )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ver  :=  strings . Fields ( line ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  len ( ver )  !=  2  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													slog . Debug ( "malformed" ,  "vendor_id" ,  line ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												vendor ,  err  =  strconv . ParseUint ( ver [ 1 ] ,  10 ,  64 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													slog . Debug ( "malformed" ,  "vendor_id" ,  line ,  "error" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  if  strings . HasPrefix ( line ,  "device_id" )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ver  :=  strings . Fields ( line ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  len ( ver )  !=  2  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													slog . Debug ( "malformed" ,  "device_id" ,  line ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												device ,  err  =  strconv . ParseUint ( ver [ 1 ] ,  10 ,  64 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													slog . Debug ( "malformed" ,  "device_id" ,  line ,  "error" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  if  strings . HasPrefix ( line ,  "unique_id" )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ver  :=  strings . Fields ( line ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  len ( ver )  !=  2  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													slog . Debug ( "malformed" ,  "unique_id" ,  line ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												uniqueID ,  err  =  strconv . ParseUint ( ver [ 1 ] ,  10 ,  64 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													slog . Debug ( "malformed" ,  "unique_id" ,  line ,  "error" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// TODO - any other properties we want to extract and record?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// vendor_id + device_id -> pci lookup for "Name"
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Other metrics that may help us understand relative performance between multiple GPUs
 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										// Note: while ./mem_banks/*/used_memory exists, it doesn't appear to take other VRAM consumers
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// into consideration, so we instead map the device over to the DRM driver sysfs nodes which
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// do reliably report VRAM usage.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  isCPU  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-27 05:04:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Skip over any GPUs that are masked
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  major  ==  0  &&  minor  ==  0  &&  patch  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											slog . Debug ( "skipping gpu with gfx000" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Look up the memory for the current node
 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										totalMemory  :=  uint64 ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										usedMemory  :=  uint64 ( 0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-16 06:13:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										var  usedFile  string 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										mapping  :=  [ ] struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											id        uint64 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											filename  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											{ vendor ,  DRMVendorFile } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											{ device ,  DRMDeviceFile } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											{ uniqueID ,  DRMUniqueIDFile } ,  // Not all devices will report this
 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										slog . Debug ( "mapping amdgpu to drm sysfs nodes" ,  "amdgpu" ,  match ,  "vendor" ,  vendor ,  "device" ,  device ,  "unique_id" ,  uniqueID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Map over to DRM location to find the total/free memory
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										drmMatches ,  _  :=  filepath . Glob ( DRMDeviceDirGlob ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  devDir  :=  range  drmMatches  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											matched  :=  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  _ ,  m  :=  range  mapping  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  m . id  ==  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-06 03:07:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													// Null ID means it didn't populate, so we can't use it to match
 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												filename  :=  filepath . Join ( devDir ,  m . filename ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-06 03:07:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												buf ,  err  :=  os . ReadFile ( filename ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													slog . Debug ( "failed to read sysfs node" ,  "file" ,  filename ,  "error" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													matched  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-06 03:07:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												// values here are in hex, strip off the lead 0x and parse so we can compare the numeric (decimal) values in amdgpu
 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												cmp ,  err  :=  strconv . ParseUint ( strings . TrimPrefix ( strings . TrimSpace ( string ( buf ) ) ,  "0x" ) ,  16 ,  64 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													slog . Debug ( "failed to parse sysfs node" ,  "file" ,  filename ,  "error" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													matched  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  cmp  !=  m . id  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													matched  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ! matched  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Found the matching DRM directory
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											slog . Debug ( "matched" ,  "amdgpu" ,  match ,  "drm" ,  devDir ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											totalFile  :=  filepath . Join ( devDir ,  DRMTotalMemoryFile ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-06 03:07:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											buf ,  err  :=  os . ReadFile ( totalFile ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												slog . Debug ( "failed to read sysfs node" ,  "file" ,  totalFile ,  "error" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											totalMemory ,  err  =  strconv . ParseUint ( strings . TrimSpace ( string ( buf ) ) ,  10 ,  64 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												slog . Debug ( "failed to parse sysfs node" ,  "file" ,  totalFile ,  "error" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-16 06:13:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											usedFile  =  filepath . Join ( devDir ,  DRMUsedMemoryFile ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											usedMemory ,  err  =  getFreeMemory ( usedFile ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-16 06:13:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												slog . Debug ( "failed to update used memory" ,  "error" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 07:18:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											break 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										var  name  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// TODO - PCI ID lookup
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  vendor  >  0  &&  device  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											name  =  fmt . Sprintf ( "%04x:%04x" ,  vendor ,  device ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-27 05:04:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Favor UUIDs if available to reduce possibility of getting the numeric IDs wrong
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  ID  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  uniqueID  !=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ID  =  fmt . Sprintf ( "GPU-%016x" ,  uniqueID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-30 03:21:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ID  =  strconv . Itoa ( gpuOrdinalID ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-27 05:04:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-16 06:13:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										gpuInfo  :=  RocmGPUInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											GpuInfo :  GpuInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Library :  "rocm" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												memInfo :  memInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													TotalMemory :  totalMemory , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													FreeMemory :   ( totalMemory  -  usedMemory ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} , 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-27 05:04:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												ID :             ID , 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-30 03:17:31 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												filterID :       gpuOrdinalID , 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-16 06:13:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												Name :           name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Compute :        fmt . Sprintf ( "gfx%d%x%x" ,  major ,  minor ,  patch ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												MinimumMemory :  rocmMinimumMemory , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												DriverMajor :    driverMajor , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												DriverMinor :    driverMinor , 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} , 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-16 06:13:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											usedFilepath :  usedFile , 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-30 03:21:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											index :         gpuCount , 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-30 03:21:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Keep track of numeric IDs based on valid GPUs
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										gpuCount  +=  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// If the user wants to filter to a subset of devices, filter out if we aren't a match
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( visibleDevices )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											include  :=  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  _ ,  visible  :=  range  visibleDevices  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( uniqueID  !=  0  &&  visible  ==  gpuInfo . ID )  ||  visible  ==  strconv . Itoa ( gpuInfo . index )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													include  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ! include  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												reason  :=  "filtering out device per user request" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												slog . Info ( reason ,  "id" ,  gpuInfo . ID ,  "index" ,  gpuInfo . index ,  "visible_devices" ,  visibleDevices ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												unsupportedGPUs  =  append ( unsupportedGPUs ,  UnsupportedGPUInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													GpuInfo :  gpuInfo . GpuInfo , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													Reason :   reason , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Ordinal IDs are based on the visible GPUs
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										gpuOrdinalID  +=  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-15 07:26:45 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										// iGPU detection, remove this check once we can support an iGPU variant of the rocm library
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  totalMemory  <  IGPUMemLimit  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reason  :=  "unsupported Radeon iGPU detected skipping" 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-30 03:21:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											slog . Info ( reason ,  "id" ,  gpuInfo . ID ,  "total" ,  format . HumanBytes2 ( totalMemory ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-15 07:26:45 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											unsupportedGPUs  =  append ( unsupportedGPUs ,  UnsupportedGPUInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												GpuInfo :  gpuInfo . GpuInfo , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Reason :   reason , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												build: Make target improvements (#7499)
* llama: wire up builtin runner
This adds a new entrypoint into the ollama CLI to run the cgo built runner.
On Mac arm64, this will have GPU support, but on all other platforms it will
be the lowest common denominator CPU build.  After we fully transition
to the new Go runners more tech-debt can be removed and we can stop building
the "default" runner via make and rely on the builtin always.
* build: Make target improvements
Add a few new targets and help for building locally.
This also adjusts the runner lookup to favor local builds, then
runners relative to the executable, and finally payloads.
* Support customized CPU flags for runners
This implements a simplified custom CPU flags pattern for the runners.
When built without overrides, the runner name contains the vector flag
we check for (AVX) to ensure we don't try to run on unsupported systems
and crash.  If the user builds a customized set, we omit the naming
scheme and don't check for compatibility.  This avoids checking
requirements at runtime, so that logic has been removed as well.  This
can be used to build GPU runners with no vector flags, or CPU/GPU
runners with additional flags (e.g. AVX512) enabled.
* Use relative paths
If the user checks out the repo in a path that contains spaces, make gets
really confused so use relative paths for everything in-repo to avoid breakage.
* Remove payloads from main binary
* install: clean up prior libraries
This removes support for v0.3.6 and older versions (before the tar bundle)
and ensures we clean up prior libraries before extracting the bundle(s).
Without this change, runners and dependent libraries could leak when we
update and lead to subtle runtime errors.
											 
										 
										
											2024-12-11 01:47:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										minVer ,  err  :=  strconv . Atoi ( RocmComputeMajorMin ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											slog . Error ( "invalid RocmComputeMajorMin setting" ,  "value" ,  RocmComputeMajorMin ,  "error" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  int ( major )  <  minVer  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-15 07:26:45 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											reason  :=  fmt . Sprintf ( "amdgpu too old gfx%d%x%x" ,  major ,  minor ,  patch ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-30 03:21:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											slog . Warn ( reason ,  "gpu" ,  gpuInfo . ID ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-15 07:26:45 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											unsupportedGPUs  =  append ( unsupportedGPUs ,  UnsupportedGPUInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												GpuInfo :  gpuInfo . GpuInfo , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Reason :   reason , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-30 03:21:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										slog . Debug ( "amdgpu memory" ,  "gpu" ,  gpuInfo . ID ,  "total" ,  format . HumanBytes2 ( totalMemory ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slog . Debug ( "amdgpu memory" ,  "gpu" ,  gpuInfo . ID ,  "available" ,  format . HumanBytes2 ( totalMemory - usedMemory ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Final validation is gfx compatibility - load the library if we haven't already loaded it
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// even if the user overrides, we still need to validate the library
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  libDir  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											libDir ,  err  =  AMDValidateLibDir ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-15 07:26:45 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												err  =  fmt . Errorf ( "unable to verify rocm library: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												slog . Warn ( err . Error ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												unsupportedGPUs  =  append ( unsupportedGPUs ,  UnsupportedGPUInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													GpuInfo :  gpuInfo . GpuInfo , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													Reason :   err . Error ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-30 07:03:38 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										gpuInfo . DependencyPath  =  [ ] string { libDir } 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  gfxOverride  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Only load supported list once
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  len ( supported )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												supported ,  err  =  GetSupportedGFX ( libDir ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-15 07:26:45 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													err  =  fmt . Errorf ( "failed to lookup supported GFX types: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													slog . Warn ( err . Error ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													unsupportedGPUs  =  append ( unsupportedGPUs ,  UnsupportedGPUInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														GpuInfo :  gpuInfo . GpuInfo , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														Reason :   err . Error ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  nil ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												slog . Debug ( "rocm supported GPUs" ,  "types" ,  supported ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											gfx  :=  gpuInfo . Compute 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											if  ! slices . Contains [ [ ] string ,  string ] ( supported ,  gfx )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-15 07:26:45 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												reason  :=  fmt . Sprintf ( "amdgpu is not supported (supported types:%s)" ,  supported ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												slog . Warn ( reason ,  "gpu_type" ,  gfx ,  "gpu" ,  gpuInfo . ID ,  "library" ,  libDir ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												unsupportedGPUs  =  append ( unsupportedGPUs ,  UnsupportedGPUInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													GpuInfo :  gpuInfo . GpuInfo , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													Reason :   reason , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												// TODO - consider discrete markdown just for ROCM troubleshooting?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												slog . Warn ( "See https://github.com/ollama/ollama/blob/main/docs/gpu.md#overrides for HSA_OVERRIDE_GFX_VERSION usage" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												slog . Info ( "amdgpu is supported" ,  "gpu" ,  gpuInfo . ID ,  "gpu_type" ,  gfx ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											slog . Info ( "skipping rocm gfx compatibility check" ,  "HSA_OVERRIDE_GFX_VERSION" ,  gfxOverride ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-01 07:15:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										// Check for env var workarounds
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  name  ==  "1002:687f"  {  // Vega RX 56
 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-30 03:17:31 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											gpuInfo . EnvWorkarounds  =  append ( gpuInfo . EnvWorkarounds ,  "HSA_ENABLE_SDMA=0" ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-01 07:15:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										// The GPU has passed all the verification steps and is supported
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										resp  =  append ( resp ,  gpuInfo ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  len ( resp )  ==  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-15 07:26:45 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										err  :=  fmt . Errorf ( "no compatible amdgpu devices detected" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slog . Info ( err . Error ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-12 02:38:25 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  :=  verifyKFDDriverAccess ( ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-15 07:26:45 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										err  =  fmt . Errorf ( "amdgpu devices detected but permission problems block access: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slog . Error ( err . Error ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-12 02:38:25 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-15 07:26:45 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  resp ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Quick check for AMD driver so we can skip amdgpu discovery if not present
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  AMDDetected ( )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Some driver versions (older?) don't have a version file, so just lookup the parent dir
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sysfsDir  :=  filepath . Dir ( DriverVersionFile ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_ ,  err  :=  os . Stat ( sysfsDir ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  errors . Is ( err ,  os . ErrNotExist )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slog . Debug ( "amdgpu driver not detected "  +  sysfsDir ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										slog . Debug ( "error looking up amd driver" ,  "path" ,  sysfsDir ,  "error" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Prefer to use host installed ROCm, as long as it meets our minimum requirements
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// failing that, tell the user how to download it on their own
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  AMDValidateLibDir ( )  ( string ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									libDir ,  err  :=  commonAMDValidateLibDir ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-11 03:13:46 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  libDir ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-11 03:13:46 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-09 01:45:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Well known ollama installer path
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									installedRocmDir  :=  "/usr/share/ollama/lib/rocm" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  rocmLibUsable ( installedRocmDir )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-31 00:50:05 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  installedRocmDir ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-09 01:45:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// If we still haven't found a usable rocm, the user will have to install it on their own
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									slog . Warn ( "amdgpu detected, but no compatible rocm library found.  Either install rocm v6, or follow manual install instructions at https://github.com/ollama/ollama/blob/main/docs/linux.md#manual-install" ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-02 05:52:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  "" ,  errors . New ( "no suitable rocm found, falling back to CPU" ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  AMDDriverVersion ( )  ( driverMajor ,  driverMinor  int ,  err  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_ ,  err  =  os . Stat ( DriverVersionFile ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  0 ,  0 ,  fmt . Errorf ( "amdgpu version file missing: %s %w" ,  DriverVersionFile ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fp ,  err  :=  os . Open ( DriverVersionFile ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  0 ,  0 ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  fp . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									verString ,  err  :=  io . ReadAll ( fp ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  0 ,  0 ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pattern  :=  ` \A(\d+)\.(\d+).* ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									regex  :=  regexp . MustCompile ( pattern ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									match  :=  regex . FindStringSubmatch ( string ( verString ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  len ( match )  <  2  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ,  0 ,  fmt . Errorf ( "malformed version string %s" ,  string ( verString ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									driverMajor ,  err  =  strconv . Atoi ( match [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ,  0 ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									driverMinor ,  err  =  strconv . Atoi ( match [ 2 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ,  0 ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-08 05:54:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  driverMajor ,  driverMinor ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-16 09:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2024-05-16 06:13:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( gpus  RocmGPUInfoList )  RefreshFreeMemory ( )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  len ( gpus )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  range  gpus  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										usedMemory ,  err  :=  getFreeMemory ( gpus [ i ] . usedFilepath ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slog . Debug ( "updating rocm free memory" ,  "gpu" ,  gpus [ i ] . ID ,  "name" ,  gpus [ i ] . Name ,  "before" ,  format . HumanBytes2 ( gpus [ i ] . FreeMemory ) ,  "now" ,  format . HumanBytes2 ( gpus [ i ] . TotalMemory - usedMemory ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										gpus [ i ] . FreeMemory  =  gpus [ i ] . TotalMemory  -  usedMemory 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  getFreeMemory ( usedFile  string )  ( uint64 ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2024-06-06 03:07:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									buf ,  err  :=  os . ReadFile ( usedFile ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-16 06:13:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ,  fmt . Errorf ( "failed to read sysfs node %s %w" ,  usedFile ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usedMemory ,  err  :=  strconv . ParseUint ( strings . TrimSpace ( string ( buf ) ) ,  10 ,  64 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slog . Debug ( "failed to parse sysfs node" ,  "file" ,  usedFile ,  "error" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ,  fmt . Errorf ( "failed to parse sysfs node %s %w" ,  usedFile ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  usedMemory ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2024-09-12 02:38:25 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  verifyKFDDriverAccess ( )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Verify we have permissions - either running as root, or we have group access to the driver
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fd ,  err  :=  os . OpenFile ( "/dev/kfd" ,  os . O_RDWR ,  0 o666 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  errors . Is ( err ,  fs . ErrPermission )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  fmt . Errorf ( "permissions not set up properly.  Either run ollama as root, or add you user account to the render group. %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  errors . Is ( err ,  fs . ErrNotExist )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Container runtime failure?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  fmt . Errorf ( "kfd driver not loaded.  If running in a container, remember to include '--device /dev/kfd --device /dev/dri'" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Errorf ( "failed to check permission on /dev/kfd: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fd . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2024-10-27 05:04:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-30 03:17:31 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  rocmGetVisibleDevicesEnv ( gpuInfo  [ ] GpuInfo )  string  {  
						 
					
						
							
								
									
										
										
										
											2024-10-27 05:04:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ids  :=  [ ] string { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  info  :=  range  gpuInfo  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  info . Library  !=  "rocm"  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-30 03:17:31 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// If the devices requires a numeric ID, for filtering purposes, we use the unfiltered ID number
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  _ ,  err  :=  strconv . Atoi ( info . ID ) ;  err  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ids  =  append ( ids ,  fmt . Sprintf ( "%d" ,  info . filterID ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ids  =  append ( ids ,  info . ID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-27 05:04:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-30 03:17:31 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  len ( ids )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-27 05:04:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// There are 3 potential env vars to use to select GPUs.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// ROCR_VISIBLE_DEVICES supports UUID or numeric so is our preferred on linux
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// GPU_DEVICE_ORDINAL supports numeric IDs only
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// HIP_VISIBLE_DEVICES supports numeric IDs only
 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-30 03:17:31 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  "ROCR_VISIBLE_DEVICES="  +  strings . Join ( ids ,  "," ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-27 05:04:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}