CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/go-amdsmi

AMD System Management Interface (AMD SMI) Go library for unified GPU and CPU management and monitoring

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

initialization.mddocs/

Initialization and Discovery

Core system initialization, device enumeration, and handle management for AMD processors. These functions must be called before using any other AMD SMI functionality.

Capabilities

Library Initialization

Initialize the AMD SMI library and specify which processor types to manage.

amdsmi_status_t amdsmi_init(uint64_t init_flags);

Parameters:

  • init_flags: Bitwise combination of initialization flags

Initialization Flags:

typedef enum {
    AMDSMI_INIT_ALL_PROCESSORS = 0xFFFFFFFF,
    AMDSMI_INIT_AMD_CPUS = (1 << 0),
    AMDSMI_INIT_AMD_GPUS = (1 << 1), 
    AMDSMI_INIT_NON_AMD_CPUS = (1 << 2),
    AMDSMI_INIT_NON_AMD_GPUS = (1 << 3),
    AMDSMI_INIT_AMD_APUS = (AMDSMI_INIT_AMD_CPUS | AMDSMI_INIT_AMD_GPUS)
} amdsmi_init_flags_t;

Usage Example:

// Initialize for AMD GPUs only
amdsmi_status_t status = amdsmi_init(AMDSMI_INIT_AMD_GPUS);
if (status != AMDSMI_STATUS_SUCCESS) {
    // Handle initialization failure
}

// Initialize for both AMD CPUs and GPUs  
status = amdsmi_init(AMDSMI_INIT_AMD_APUS);

Library Shutdown

Clean up resources and shut down the AMD SMI library.

amdsmi_status_t amdsmi_shut_down(void);

Returns: Status code indicating success or failure

Usage Example:

// Always call shutdown to clean up resources
amdsmi_shut_down();

Processor Handle Discovery

Get handles to available processors for subsequent API calls.

amdsmi_status_t amdsmi_get_processor_handles(amdsmi_processor_type_t processor_type,
                                           amdsmi_processor_handle* processor_handles,
                                           uint32_t* num_devices);

Parameters:

  • processor_type: Type of processors to enumerate
  • processor_handles: Array to store processor handles (can be NULL to query count)
  • num_devices: Input: array size, Output: actual number of devices

Processor Types:

typedef enum {
    AMDSMI_PROCESSOR_TYPE_AMD_GPU,
    AMDSMI_PROCESSOR_TYPE_AMD_CPU,
    AMDSMI_PROCESSOR_TYPE_NON_AMD_GPU,
    AMDSMI_PROCESSOR_TYPE_NON_AMD_CPU
} amdsmi_processor_type_t;

Usage Example:

// First, get the number of AMD GPUs
uint32_t num_gpus = 0;
amdsmi_status_t status = amdsmi_get_processor_handles(AMDSMI_PROCESSOR_TYPE_AMD_GPU, 
                                                     nullptr, &num_gpus);

if (status == AMDSMI_STATUS_SUCCESS && num_gpus > 0) {
    // Allocate array for handles
    std::vector<amdsmi_processor_handle> gpu_handles(num_gpus);
    
    // Get the actual handles
    status = amdsmi_get_processor_handles(AMDSMI_PROCESSOR_TYPE_AMD_GPU,
                                         gpu_handles.data(), &num_gpus);
    
    // Use the handles for subsequent API calls
    for (const auto& handle : gpu_handles) {
        // Perform operations on each GPU
    }
}

Processor Type Detection

Determine the type of a given processor handle.

amdsmi_status_t amdsmi_get_processor_type(amdsmi_processor_handle processor_handle,
                                         amdsmi_processor_type_t* processor_type);

Parameters:

  • processor_handle: Handle to query
  • processor_type: Output pointer to store processor type

Usage Example:

amdsmi_processor_type_t type;
amdsmi_status_t status = amdsmi_get_processor_type(processor_handle, &type);

if (status == AMDSMI_STATUS_SUCCESS) {
    switch (type) {
        case AMDSMI_PROCESSOR_TYPE_AMD_GPU:
            // Handle AMD GPU specific operations
            break;
        case AMDSMI_PROCESSOR_TYPE_AMD_CPU:
            // Handle AMD CPU specific operations
            break;
        default:
            // Handle other processor types
            break;
    }
}

Socket Discovery

Get socket-level handles for CPU management.

amdsmi_status_t amdsmi_get_socket_handles(uint32_t* num_sockets,
                                         amdsmi_socket_handle* socket_handles);

Parameters:

  • num_sockets: Input: array size, Output: actual number of sockets
  • socket_handles: Array to store socket handles (can be NULL to query count)
amdsmi_status_t amdsmi_get_socket_info(amdsmi_socket_handle socket_handle,
                                      amdsmi_socket_info_t* socket_info);

Socket Information Structure:

typedef struct {
    uint32_t socket_id;
    uint32_t num_cpu_cores;
    uint32_t num_gpus;
} amdsmi_socket_info_t;

Language Interface Examples

Python

import amdsmi

# Initialize library
amdsmi.amdsmi_init(amdsmi.AmdSmiInitFlag.AMD_GPUS)

# Get GPU handles
gpu_handles = amdsmi.amdsmi_get_processor_handles(amdsmi.AmdSmiProcessorType.AMD_GPU)
print(f"Found {len(gpu_handles)} AMD GPU(s)")

# Get socket handles for CPU management
socket_handles = amdsmi.amdsmi_get_socket_handles()
print(f"Found {len(socket_handles)} CPU socket(s)")

# Cleanup
amdsmi.amdsmi_shut_down()

Go

The Go interface provides direct initialization functions for GPU and CPU monitoring:

func GO_gpu_init() bool
func GO_gpu_shutdown() bool  
func GO_gpu_num_monitor_devices() uint
func GO_cpu_init() bool
func GO_cpu_number_of_sockets_get() uint
func GO_cpu_number_of_threads_get() uint
func GO_cpu_threads_per_core_get() uint

Usage Example:

package main

import (
    "fmt" 
    "log"
)

func main() {
    // Initialize for GPU monitoring
    if !goamdsmi.GO_gpu_init() {
        log.Fatal("Failed to initialize AMD SMI for GPUs")
    }
    defer func() {
        if !goamdsmi.GO_gpu_shutdown() {
            log.Println("Warning: Failed to shutdown GPU monitoring")
        }
    }()

    // Get number of monitor devices  
    numGPUs := goamdsmi.GO_gpu_num_monitor_devices()
    fmt.Printf("Found %d GPU(s) available for monitoring\n", numGPUs)

    // Initialize CPU monitoring separately if needed
    if goamdsmi.GO_cpu_init() {
        numSockets := goamdsmi.GO_cpu_number_of_sockets_get()
        numThreads := goamdsmi.GO_cpu_number_of_threads_get()
        threadsPerCore := goamdsmi.GO_cpu_threads_per_core_get()
        
        fmt.Printf("CPU Info: %d sockets, %d threads, %d threads per core\n", 
                   numSockets, numThreads, threadsPerCore)
    }
}

Rust

use amdsmi::{init, shut_down, get_processor_handles, ProcessorType, InitFlag};

// Initialize library
init(InitFlag::AMD_GPUS)?;

// Get GPU handles
let gpu_handles = get_processor_handles(ProcessorType::AmdGpu)?;
println!("Found {} GPU(s)", gpu_handles.len());

// Cleanup
shut_down();

Error Handling

All initialization functions return status codes that should be checked:

typedef enum {
    AMDSMI_STATUS_SUCCESS = 0,
    AMDSMI_STATUS_INVAL,
    AMDSMI_STATUS_NOT_SUPPORTED,
    AMDSMI_STATUS_FILE_ERROR,
    AMDSMI_STATUS_PERMISSION,
    AMDSMI_STATUS_OUT_OF_RESOURCES,
    AMDSMI_STATUS_INTERNAL_EXCEPTION,
    AMDSMI_STATUS_INPUT_OUT_OF_BOUNDS,
    AMDSMI_STATUS_INIT_ERROR,
    AMDSMI_STATUS_NOT_YET_IMPLEMENTED,
    AMDSMI_STATUS_NOT_FOUND,
    AMDSMI_STATUS_INSUFFICIENT_SIZE,
    AMDSMI_STATUS_INTERRUPT,
    AMDSMI_STATUS_UNEXPECTED_SIZE,
    AMDSMI_STATUS_NO_DATA,
    AMDSMI_STATUS_UNEXPECTED_DATA,
    AMDSMI_STATUS_BUSY,
    AMDSMI_STATUS_REFCOUNT_OVERFLOW,
    AMDSMI_STATUS_UNKNOWN_ERROR
} amdsmi_status_t;

Common Error Conditions:

  • AMDSMI_STATUS_INIT_ERROR: Library not initialized or initialization failed
  • AMDSMI_STATUS_PERMISSION: Insufficient permissions (especially for control operations)
  • AMDSMI_STATUS_NOT_SUPPORTED: Feature not supported on current hardware
  • AMDSMI_STATUS_FILE_ERROR: Driver files not accessible

Install with Tessl CLI

npx tessl i tessl/go-amdsmi

docs

cpu-management.md

device-info.md

events.md

gpu-performance.md

index.md

initialization.md

memory.md

performance-control.md

power-thermal.md

topology-ras.md

tile.json