onnxruntime_go

repository·master·Indexed 20 days ago

https://github.com/yalue/onnxruntime_go

A cross-platform Go wrapper for the ONNX Runtime C API that enables loading and executing ONNX neural networks. It supports Windows via manual shared library loading and provides integration for hardware accelerators including CUDA, TensorRT, and CoreML. The library provides tools for managing tensors, shapes, and sessions via AdvancedSession and DynamicAdvancedSession, as well as support for complex ONNX types like sequences and maps.

Tokens
8.1K
Snippets
23
Records
34
Agent score
69%

What's inside onnxruntime_go

  1. Use AdvancedSession instead of typed Session

    master

    The library previously used typed Session[T] and DynamicSession[T] structs. These are now considered deprecated.

    While they remain in the library for backwards compatibility (delegating to AdvancedSession internally), all new code should use AdvancedSession directly. This provides a more flexible way to manage sessions without unnecessary type parameter association.

  2. Set up onnxruntime_go with a shared library

    master

    To use onnxruntime_go, you must have a Go installation with cgo support and a copy of the onnxruntime shared library (e.g., .so, .dll, or .dylib) corresponding to your OS and architecture.

    Before initializing the environment, you must provide the path to the shared library using ort.SetSharedLibraryPath(...). While the library attempts to find onnxruntime.dll on Windows or onnxruntime.so on other systems by default, explicitly setting the path is recommended for stability.

    If you are running tests and need to use a specific library (e.g., for CUDA support or on unsupported architectures), set the ONNXRUNTIME_SHARED_LIBRARY_PATH environment variable.

    import ort "github.com/yalue/onnxruntime_go"
    
    func main() {
        ort.SetSharedLibraryPath("path/to/onnxruntime.so")
        // ...
    }
  3. Load and run an ONNX network

    master

    To execute an ONNX model, follow these steps:

    1. Initialize the environment: Call ort.InitializeEnvironment() and ensure you defer ort.DestroyEnvironment().
    2. Prepare Tensors: Create input and output tensors. For performance, it is recommended to create these before creating the session. Use ort.NewTensor for existing data or ort.NewEmptyTensor[T] for pre-allocating output buffers. Always defer tensor.Destroy().
    3. Create a Session: Use ort.NewAdvancedSession to link the model file, input/output names, and the pre-allocated tensors.
    4. Run Inference: Call session.Run(). This reads from the input tensors and writes results into the output tensors.
    5. Access Data: Use tensor.GetData() to retrieve a slice view of the results.

    Note: For use cases where input/output shapes change, use the DynamicAdvancedSession type instead.

    import (
        "fmt"
        ort "github.com/yalue/onnxruntime_go"
        "os"
    )
    
    func main() {
        // 1. Set library path and initialize
        ort.SetSharedLibraryPath("path/to/onnxruntime.so")
    
        err := ort.InitializeEnvironment()
        if err != nil {
            panic(err)
        }
        defer ort.DestroyEnvironment()
    
        // 2. Prepare input and output tensors
        inputData := []float32{0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}
        inputShape := ort.NewShape(2, 5)
        inputTensor, err := ort.NewTensor(inputShape, inputData)
        if err != nil { panic(err) }
        defer inputTensor.Destroy()
    
        outputShape := ort.NewShape(2, 3, 4)
        outputTensor, err := ort.NewEmptyTensor[float32](outputShape)
        if err != nil { panic(err) }
        defer outputTensor.Destroy()
    
        // 3. Create session
        session, err := ort.NewAdvancedSession("path/to/network.onnx",
            []string{"Input 1 Name"}, []string{"Output 1 Name"},
            []ort.Value{inputTensor}, []ort.Value{outputTensor}, nil)
        if err != nil { panic(err) }
        defer session.Destroy()
    
        // 4. Run inference
        err = session.Run()
        if err != nil { panic(err) }
    
        // 5. Get results
        outputData := outputTensor.GetData()
        fmt.Println(outputData)
    }
  4. How to update or change the onnxruntime version

    master

    This library is tied to specific onnxruntime C API header versions. If you need to use a version other than the one currently supported (v1.28.0), follow these steps:

    1. Update Headers: Replace onnxruntime_c_api.h and onnxruntime_ep_c_api.h with the versions from your target onnxruntime release.
    2. Update Shared Library: Replace the existing shared library files (e.g., test_data/onnxruntime.dll or test_data/onnxruntime*.so) with the version you wish to use.
    3. DirectML Support (Optional): If using DirectML, verify that the entries in the DummyOrtDMLAPI struct in onnxruntime_wrapper.c match the order in the official OrtDmlApi struct from dml_provider_factory.h.

    Header and library files can be found in the official onnxruntime releases.

  5. Use TensorData constraints for generic Tensors

    master

    The onnxruntime_go package uses specific type constraints to ensure that generic Tensors are initialized with supported ONNX data types. When working with generic Tensor implementations, your data type must satisfy the TensorData interface.

    Supported types include:

    • Floats: float32, float64
    • Integers: int8, uint8, int16, uint16, int32, uint32, int64, uint64
    • Booleans: bool
  6. Migrate from deprecated Session types to AdvancedSession

    master

    The Session[T] and DynamicSession[in, out] types are deprecated and are maintained only for backward compatibility. They internally delegate to AdvancedSession and DynamicAdvancedSession respectively.

    Recommendation:

    • If using Session[T], migrate to AdvancedSession.
    • If using DynamicSession[in, out], migrate to DynamicAdvancedSession.
    • If using NewSessionWithONNXData, migrate to NewAdvancedSessionWithONNXData.
    • If using NewDynamicSessionWithONNXData, migrate to NewDynamicAdvancedSessionWithONNXData.
  7. Initialize and destroy the ONNX Runtime environment

    master

    Before using the library, you must initialize the internal ONNX Runtime environment. This manages the core state and memory info. Once finished, you must call DestroyEnvironment to prevent memory leaks.

    If you need to specify a custom path for the shared library (onnxruntime.so or onnxruntime.dll), call SetSharedLibraryPath before calling InitializeEnvironment.

    import "github.com/yalue/onnxruntime_go"
    
    func main() {
        // Optional: Set custom path to the shared library
        onnxruntime_go.SetSharedLibraryPath("/path/to/onnxruntime.so")
    
        // Initialize the environment
        err := onnxruntime_go.InitializeEnvironment()
        if err != nil {
            panic(err)
        }
        // Ensure cleanup
        defer onnxruntime_go.DestroyEnvironment()
    
        // ... use the library ...
    }
  8. Enable Hardware Acceleration (CUDA, TensorRT, CoreML, etc.)

    master

    You can enable specific execution providers (hardware backends) via SessionOptions.

    CUDA:

    1. Create options: NewCUDAProviderOptions().
    2. Configure: cudaOpts.Update(map[string]string{"device_id": "0"}).
    3. Attach: sessionOpts.AppendExecutionProviderCUDA(cudaOpts).
    4. Cleanup: cudaOpts.Destroy() (can be done immediately after Append...).

    TensorRT:

    1. Create options: NewTensorRTProviderOptions().
    2. Configure: trtOpts.Update(map[string]string{...}).
    3. Attach: sessionOpts.AppendExecutionProviderTensorRT(trtOpts).
    4. Cleanup: trtOpts.Destroy().

    CoreML (Apple):

    • Use AppendExecutionProviderCoreMLV2(options map[string]string) (recommended for ONNX 1.20.0+).
    • AppendExecutionProviderCoreML(flags uint32) is deprecated.

    DirectML (Windows):

    • Use AppendExecutionProviderDirectML(deviceID int).

    OpenVINO (Intel):

    • Use AppendExecutionProviderOpenVINO(options map[string]string).

    Generic Provider:

    • Use AppendExecutionProvider(providerName string, options map[string]string) for any other provider.
    // Example: Enabling CUDA
    cudaOpts, _ := NewCUDAProviderOptions()
    cudaOpts.Update(map[string]string{"device_id": "0"})
    
    sessOpts, _ := NewSessionOptions()
    sessOpts.AppendExecutionProviderCUDA(cudaOpts)
    
    // Cleanup CUDA options as soon as they are appended
    cudaOpts.Destroy()
  9. Configure the ONNX Runtime environment with options

    master

    You can pass EnvironmentOption functions to InitializeEnvironment to configure the runtime during startup. Common options include setting the logging level.

    Available logging levels via LoggingLevel:

    • LoggingLevelVerbose
    • LoggingLevelInfo
    • LoggingLevelWarning
    • LoggingLevelError (Default)
    • LoggingLevelFatal
    // Initialize with verbose logging
    err := onnxruntime_go.InitializeEnvironment(
        onnxruntime_go.WithLogLevelVerbose(),
    )
  10. Note on Onnxruntime Training API support

    master

    The onnxruntime training API was deprecated in version 1.20. Consequently, onnxruntime_go has replaced its training wrapper functions with stubs that return an error.

    If your project requires the training API, you must use an older version of the library, such as:

    • onnxruntime_go version v1.12.1
    • onnxruntime version 1.19.2
  11. Note on removed Training API support

    master

    Support for the ONNX Runtime Training API has been removed from onnxruntime_go following its deprecation in onnxruntime versions 1.19.2 and later. The last version of onnxruntime_go that supported the training API was v1.12.1.

    All functions and types related to training (e.g., TrainingSession, TrainStep, OptimizerStep) will return TrainingAPIRemovedError and are no longer functional.

  12. Retrieve model metadata from an ONNX file

    master

    To access model-specific metadata (like producer information or versioning), use the metadata retrieval functions. These also create a temporary session and are computationally expensive.

    Important: The returned *ModelMetadata object must be manually freed by calling its Destroy() method to avoid memory leaks.

    Available methods:

    • GetModelMetadata(path string): Uses default options.
    • GetModelMetadataWithOptions(path string, options *SessionOptions): Uses specific SessionOptions.
    • GetModelMetadataWithONNXData(data []byte): Extracts metadata from a raw byte slice.
    // Example: Getting metadata and ensuring it is destroyed
    metadata, err := onnxruntime_go.GetModelMetadata("model.onnx")
    if err != nil {
        log.Fatal(err)
    }
    // Crucial: Call Destroy() when finished
    defer metadata.Destroy()
    
    fmt.Println("Metadata retrieved successfully")