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.
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user