Files
claude 28c2ffb84f Make aggregate ONNX gates execute for real
Reference-count the process-global ONNX Runtime across embedder and routing-head sessions, make close idempotent, and require named proof that both aggregate routing gates executed rather than self-skipped (V-716). Owner explicitly requested direct commits to master.
2026-08-13 03:03:25 +04:00

125 lines
3.5 KiB
Go

package router
import (
"fmt"
"path/filepath"
"sync"
ort "github.com/yalue/onnxruntime_go"
)
// ONNXRuntimeLease keeps the process-global ONNX Runtime environment alive.
//
// onnxruntime_go exposes the environment as package-global state: it may be
// initialized only once, and destroying it while any session is alive is
// unsafe. A lease makes that ownership explicit. Model wrappers hold one for
// the lifetime of their session; TestMain may hold an additional lease so a
// package's model-aware gates share one environment instead of repeatedly
// loading and unloading the shared library.
type ONNXRuntimeLease struct {
once sync.Once
err error
}
var sharedONNXRuntime = struct {
sync.Mutex
refs int
libPath string
managed bool
}{}
// AcquireONNXRuntime acquires the process-global ONNX Runtime environment.
// The first caller initializes it; later callers share it. A non-empty library
// path must agree with the path that initialized the active environment.
//
// The external-environment branch is intentional. It keeps this package safe
// when an executable initialized onnxruntime_go directly before constructing
// a router model; in that case the lease never destroys state it does not own.
func AcquireONNXRuntime(libPath string) (*ONNXRuntimeLease, error) {
libPath = cleanONNXLibraryPath(libPath)
sharedONNXRuntime.Lock()
defer sharedONNXRuntime.Unlock()
if sharedONNXRuntime.refs > 0 {
if err := compatibleONNXLibraryPath(sharedONNXRuntime.libPath, libPath); err != nil {
return nil, err
}
sharedONNXRuntime.refs++
return &ONNXRuntimeLease{}, nil
}
if ort.IsInitialized() {
// Some other component owns the already-live environment. Attach to it,
// but never unload its shared library when our last lease closes.
sharedONNXRuntime.refs = 1
sharedONNXRuntime.libPath = libPath
sharedONNXRuntime.managed = false
return &ONNXRuntimeLease{}, nil
}
if libPath != "" {
ort.SetSharedLibraryPath(libPath)
}
if err := ort.InitializeEnvironment(); err != nil {
return nil, fmt.Errorf("onnx: init environment: %w", err)
}
sharedONNXRuntime.refs = 1
sharedONNXRuntime.libPath = libPath
sharedONNXRuntime.managed = true
return &ONNXRuntimeLease{}, nil
}
// Close releases one environment lease. The last lease destroys an
// environment initialized by this package, after every model session that
// held a lease has already been destroyed.
func (l *ONNXRuntimeLease) Close() error {
if l == nil {
return nil
}
l.once.Do(func() {
l.err = releaseONNXRuntime()
})
return l.err
}
func releaseONNXRuntime() error {
sharedONNXRuntime.Lock()
defer sharedONNXRuntime.Unlock()
if sharedONNXRuntime.refs == 0 {
return fmt.Errorf("onnx: release environment without a lease")
}
sharedONNXRuntime.refs--
if sharedONNXRuntime.refs != 0 {
return nil
}
managed := sharedONNXRuntime.managed
sharedONNXRuntime.libPath = ""
sharedONNXRuntime.managed = false
if !managed {
return nil
}
if err := ort.DestroyEnvironment(); err != nil {
return fmt.Errorf("onnx: destroy environment: %w", err)
}
return nil
}
func cleanONNXLibraryPath(path string) string {
if path == "" {
return ""
}
return filepath.Clean(path)
}
func compatibleONNXLibraryPath(active, requested string) error {
// Empty means "use the environment that is already active". RouterHeads
// intentionally has no second copy of the embedder's library-path config.
if active == "" || requested == "" || active == requested {
return nil
}
return fmt.Errorf("onnx: runtime already uses shared library %q, cannot also use %q", active, requested)
}