本库提供了使用 Microsoft onnxruntime 加载和执行 ONNX 神经网络的 Go 接口。在原版 yalue/onnxruntime_go 基础上扩展了:
machineid/cert 集成实现企业授权go get cnb.cool/svn/onnxruntime
还需要下载对应平台的 ONNX Runtime 共享库,从 onnxruntime releases 获取。
package main
import (
"fmt"
ort "cnb.cool/svn/onnxruntime"
)
func main() {
// 设置库路径
ort.SetSharedLibraryPath("/path/to/libonnxruntime.so")
// 初始化环境
if err := ort.InitializeEnvironment(); err != nil {
panic(err)
}
defer ort.DestroyEnvironment()
// 创建输入张量
inputShape := ort.NewShape(1, 3, 224, 224)
inputData := make([]float32, inputShape.FlattenedSize())
inputTensor, _ := ort.NewTensor(inputShape, inputData)
defer inputTensor.Destroy()
// 创建输出张量
outputShape := ort.NewShape(1, 1000)
outputTensor, _ := ort.NewEmptyTensor[float32](outputShape)
defer outputTensor.Destroy()
// 创建会话并运行
session, _ := ort.NewAdvancedSession("model.onnx",
[]string{"input"}, []string{"output"},
[]ort.Value{inputTensor}, []ort.Value{outputTensor}, nil)
defer session.Destroy()
session.Run()
result := outputTensor.GetData()
fmt.Println("结果:", result[:10])
}
package main
import (
ort "cnb.cool/svn/onnxruntime"
)
func main() {
ort.SetSharedLibraryPath("/path/to/libonnxruntime.so")
ort.InitializeEnvironment()
defer ort.DestroyEnvironment()
// 加密密钥(AES-256 需要 32 字节)
key := []byte("your-32-byte-secret-key-here!!")
// 加密模型(一次性操作)
ort.EncryptModel("model.onnx", "model.onnx.enc", key)
// 从加密文件获取模型信息
inputs, outputs, _ := ort.GetInputOutputInfoFromEncryptedFile("model.onnx.enc", key)
// 从加密模型创建会话
session, _ := ort.NewDynamicAdvancedSessionFromEncryptedFile(
"model.onnx.enc", key,
[]string{inputs[0].Name}, []string{outputs[0].Name}, nil)
defer session.Destroy()
// 执行推理...
}
package main
import (
"github.com/darkit/machineid"
ort "cnb.cool/svn/onnxruntime"
)
func main() {
ort.SetSharedLibraryPath("/path/to/libonnxruntime.so")
ort.InitializeEnvironment()
defer ort.DestroyEnvironment()
// 获取机器 ID
machineID, _ := machineid.ID()
moduleName := "ai.model.classifier"
salt := []byte("app-specific-salt")
// 为当前机器加密模型
ort.EncryptModelForMachine("model.onnx", "model.onnx.enc",
machineID, moduleName, salt)
// 派生密钥并创建会话
key := ort.DeriveModelKey(machineID, moduleName, salt)
session, _ := ort.NewDynamicAdvancedSessionFromEncryptedFile(
"model.onnx.enc", key, inputNames, outputNames, nil)
defer session.Destroy()
}
func SetSharedLibraryPath(path string)
设置 ONNX Runtime 共享库路径。必须在 InitializeEnvironment() 之前调用。
func InitializeEnvironment(opts ...EnvironmentOption) error
初始化 ONNX Runtime 环境。必须在创建任何会话之前调用。
选项:
WithLogLevelVerbose() - 启用详细日志WithLogLevelInfo() - 启用信息日志WithLogLevelWarning() - 启用警告日志(默认)WithLogLevelError() - 仅启用错误日志WithLogLevelFatal() - 仅启用致命错误日志func DestroyEnvironment() error
清理 ONNX Runtime 环境。使用完毕后应调用此函数。
func IsInitialized() bool
返回环境是否已初始化。
func GetVersion() string
返回 ONNX Runtime 版本字符串。
func DisableTelemetry() error
func EnableTelemetry() error
控制 ONNX Runtime 遥测数据收集。
func SetEnvironmentLogLevel(level LoggingLevel) error
设置环境日志级别。
func NewShape(dimensions ...int64) Shape
从给定维度创建新的张量形状。
func (s Shape) FlattenedSize() int64 // 元素总数
func (s Shape) Validate() error // 验证维度为正数
func (s Shape) Clone() Shape // 创建副本
func (s Shape) String() string // 字符串表示
func (s Shape) Equals(other Shape) bool // 比较两个形状
数值数据类型的泛型张量。
func NewTensor[T TensorData](s Shape, data []T) (*Tensor[T], error)
func NewEmptyTensor[T TensorData](s Shape) (*Tensor[T], error)
支持的类型 (TensorData):
float32, float64int8, int16, int32, int64uint8, uint16, uint32, uint64方法:
func (t *Tensor[T]) GetData() []T // 获取底层数据切片
func (t *Tensor[T]) GetShape() Shape // 获取张量形状
func (t *Tensor[T]) Clone() (*Tensor[T], error) // 创建副本
func (t *Tensor[T]) ZeroContents() // 清零所有元素
func (t *Tensor[T]) Destroy() error // 释放资源
func (t *Tensor[T]) GetONNXType() ONNXType // 返回 ONNXTypeTensor
func (t *Tensor[T]) DataType() ONNXTensorElementDataType
单值张量(0 维)。
func NewScalar[T TensorData](data T) (*Scalar[T], error)
func NewEmptyScalar[T TensorData]() (*Scalar[T], error)
方法:
func (s *Scalar[T]) GetData() T // 获取标量值
func (s *Scalar[T]) Set(value T) // 设置标量值
func (s *Scalar[T]) Destroy() error
包含字符串数据的张量。
func NewStringTensor(shape Shape) (*StringTensor, error)
方法:
func (t *StringTensor) SetContents(contents []string) error
func (t *StringTensor) GetContents() ([]string, error)
func (t *StringTensor) SetElement(index int64, s string) error
func (t *StringTensor) GetElement(index int64) (string, error)
func (t *StringTensor) Destroy() error
自定义二进制数据和元素类型的张量。
func NewCustomDataTensor(s Shape, data []byte, dataType TensorElementDataType) (*CustomDataTensor, error)
方法:
func (t *CustomDataTensor) GetData() []byte
func (t *CustomDataTensor) Destroy() error
ONNX 序列容器。
func NewSequence(contents []Value) (*Sequence, error)
方法:
func (s *Sequence) GetValues() ([]Value, error)
func (s *Sequence) Destroy() error
ONNX 映射容器。
func NewMap(keys, values Value) (*Map, error)
func NewMapFromGoMap[K, V TensorData](m map[K]V) (*Map, error)
方法:
func (m *Map) GetKeysAndValues() (Value, Value, error)
func (m *Map) Destroy() error
预绑定输入/输出张量的静态会话。
func NewAdvancedSession(onnxFilePath string, inputNames, outputNames []string,
inputs, outputs []Value, options *SessionOptions) (*AdvancedSession, error)
func NewAdvancedSessionWithONNXData(onnxData []byte, inputNames, outputNames []string,
inputs, outputs []Value, options *SessionOptions) (*AdvancedSession, error)
方法:
func (s *AdvancedSession) Run() error
func (s *AdvancedSession) RunWithOptions(opts *RunOptions) error
func (s *AdvancedSession) GetModelMetadata() (*ModelMetadata, error)
func (s *AdvancedSession) Destroy() error
运行时指定输入/输出的动态会话。
func NewDynamicAdvancedSession(onnxFilePath string, inputNames, outputNames []string,
options *SessionOptions) (*DynamicAdvancedSession, error)
func NewDynamicAdvancedSessionWithONNXData(onnxData []byte, inputNames, outputNames []string,
options *SessionOptions) (*DynamicAdvancedSession, error)
方法:
func (s *DynamicAdvancedSession) Run(inputs, outputs []Value) error
func (s *DynamicAdvancedSession) RunWithOptions(inputs, outputs []Value, opts *RunOptions) error
func (s *DynamicAdvancedSession) RunWithBinding(b *IoBinding) error
func (s *DynamicAdvancedSession) CreateIoBinding() (*IoBinding, error)
func (s *DynamicAdvancedSession) GetModelMetadata() (*ModelMetadata, error)
func (s *DynamicAdvancedSession) Destroy() error
用于优化内存管理的 I/O 绑定。
func (s *DynamicAdvancedSession) CreateIoBinding() (*IoBinding, error)
方法:
func (b *IoBinding) BindInput(name string, value Value) error
func (b *IoBinding) BindOutput(name string, value Value) error
func (b *IoBinding) GetBoundOutputNames() ([]string, error)
func (b *IoBinding) GetBoundOutputValues() ([]Value, error)
func (b *IoBinding) ClearBoundInputs()
func (b *IoBinding) ClearBoundOutputs()
func (b *IoBinding) Destroy() error
func NewSessionOptions() (*SessionOptions, error)
方法:
// 执行配置
func (o *SessionOptions) SetExecutionMode(mode ExecutionMode) error
func (o *SessionOptions) SetGraphOptimizationLevel(level GraphOptimizationLevel) error
func (o *SessionOptions) SetLogSeverityLevel(level LoggingLevel) error
func (o *SessionOptions) SetIntraOpNumThreads(n int) error
func (o *SessionOptions) SetInterOpNumThreads(n int) error
func (o *SessionOptions) SetCpuMemArena(isEnabled bool) error
func (o *SessionOptions) SetMemPattern(isEnabled bool) error
// 会话配置项
func (o *SessionOptions) HasSessionConfigEntry(key string) (bool, error)
func (o *SessionOptions) GetSessionConfigEntry(key string) (string, error)
func (o *SessionOptions) AddSessionConfigEntry(key, value string) error
// 执行提供程序
func (o *SessionOptions) AppendExecutionProviderCUDA(cudaOptions *CUDAProviderOptions) error
func (o *SessionOptions) AppendExecutionProviderTensorRT(tensorrtOptions *TensorRTProviderOptions) error
func (o *SessionOptions) AppendExecutionProviderCoreML(flags uint32) error
func (o *SessionOptions) AppendExecutionProviderCoreMLV2(options map[string]string) error
func (o *SessionOptions) AppendExecutionProviderDirectML(deviceID int) error
func (o *SessionOptions) AppendExecutionProviderOpenVINO(options map[string]string) error
func (o *SessionOptions) AppendExecutionProvider(providerName string, options map[string]string) error
func (o *SessionOptions) Destroy() error
ExecutionMode(执行模式):
ExecutionModeSequential - 顺序执行ExecutionModeParallel - 并行执行GraphOptimizationLevel(图优化级别):
GraphOptLevelDisableAll - 无优化GraphOptLevelBasic - 基础优化GraphOptLevelExtended - 扩展优化GraphOptLevelAll - 全部优化func NewRunOptions() (*RunOptions, error)
方法:
func (o *RunOptions) Terminate() error // 请求终止
func (o *RunOptions) UnsetTerminate() error // 清除终止标志
func (o *RunOptions) Destroy() error
func NewCUDAProviderOptions() (*CUDAProviderOptions, error)
方法:
func (o *CUDAProviderOptions) Update(options map[string]string) error
func (o *CUDAProviderOptions) Destroy() error
常用选项:
"device_id" - GPU 设备 ID"gpu_mem_limit" - 内存限制(字节)"arena_extend_strategy" - 内存分配策略func NewTensorRTProviderOptions() (*TensorRTProviderOptions, error)
方法:
func (o *TensorRTProviderOptions) Update(options map[string]string) error
func (o *TensorRTProviderOptions) Destroy() error
常用选项:
"device_id" - GPU 设备 ID"trt_max_workspace_size" - 最大工作空间大小"trt_fp16_enable" - 启用 FP16 精度"trt_int8_enable" - 启用 INT8 精度func GetInputOutputInfo(path string) ([]InputOutputInfo, []InputOutputInfo, error)
func GetInputOutputInfoWithOptions(path string, options *SessionOptions) ([]InputOutputInfo, []InputOutputInfo, error)
func GetInputOutputInfoWithONNXData(data []byte) ([]InputOutputInfo, []InputOutputInfo, error)
返回模型的输入和输出张量信息。
type InputOutputInfo struct {
Name string
DataType TensorElementDataType
Dimensions []int64
}
func (n *InputOutputInfo) String() string
func GetModelMetadata(path string) (*ModelMetadata, error)
func (m *ModelMetadata) GetProducerName() (string, error)
func (m *ModelMetadata) GetGraphName() (string, error)
func (m *ModelMetadata) GetDomain() (string, error)
func (m *ModelMetadata) GetDescription() (string, error)
func (m *ModelMetadata) GetVersion() (int64, error)
func (m *ModelMetadata) GetCustomMetadataMapKeys() ([]string, error)
func (m *ModelMetadata) LookupCustomMetadataMap(key string) (string, bool, error)
func (m *ModelMetadata) Destroy() error
// 加密模型文件
func EncryptModel(inputPath, outputPath string, key []byte) error
// 解密模型文件
func DecryptModel(inputPath, outputPath string, key []byte) error
// 在内存中加密模型数据
func EncryptModelData(plaintext, key []byte) ([]byte, error)
// 在内存中解密模型数据
func DecryptModelData(data, key []byte) ([]byte, error)
// 生成随机 32 字节加密密钥
func GenerateEncryptionKey() ([]byte, error)
加密格式: AES-256-GCM,魔数头 ORTENC01
// 从加密文件创建会话
func NewAdvancedSessionFromEncryptedFile(encryptedPath string, key []byte,
inputNames, outputNames []string, inputs, outputs []Value,
options *SessionOptions) (*AdvancedSession, error)
func NewDynamicAdvancedSessionFromEncryptedFile(encryptedPath string, key []byte,
inputNames, outputNames []string,
options *SessionOptions) (*DynamicAdvancedSession, error)
// 从加密数据创建会话
func NewAdvancedSessionFromEncryptedData(encryptedData, key []byte,
inputNames, outputNames []string, inputs, outputs []Value,
options *SessionOptions) (*AdvancedSession, error)
func NewDynamicAdvancedSessionFromEncryptedData(encryptedData, key []byte,
inputNames, outputNames []string,
options *SessionOptions) (*DynamicAdvancedSession, error)
// 从加密文件获取模型信息
func GetInputOutputInfoFromEncryptedFile(encryptedPath string, key []byte) (
[]InputOutputInfo, []InputOutputInfo, error)
// 从机器 ID 派生加密密钥
func DeriveModelKey(machineID, moduleName string, salt []byte) []byte
// 从 Authorization 对象派生密钥
func DeriveModelKeyFromAuth(auth Authorization, moduleName string, salt []byte) ([]byte, error)
// 为特定机器加密模型
func EncryptModelForMachine(inputPath, outputPath, machineID, moduleName string, salt []byte) error
// 为特定机器加密模型数据
func EncryptModelDataForMachine(plaintext []byte, machineID, moduleName string, salt []byte) ([]byte, error)
与 machineid/cert 包集成,实现企业授权。
type Authorization interface {
Validate(machineID string) error
HasModule(name string) bool
GetModuleQuota(name string) int
ValidateModule(name string) error
ExpiresAt() time.Time
MachineIDs() []string
}
type SecurityChecker interface {
Check() error // 反调试、虚拟机检测等
}
type AuthorizedModelConfig struct {
ModuleName string // 授权模块名称
MachineID string // 当前机器 ID
Authorization Authorization // 授权对象
SecurityChecker SecurityChecker // 可选安全检查器
KeyDerivationSalt []byte // 密钥派生盐值
ValidateOnEveryRun bool // 每次推理前验证
QuotaTracker QuotaTracker // 可选配额追踪
}
func NewAuthorizedSession(encryptedPath string, config AuthorizedModelConfig,
inputNames, outputNames []string, options *SessionOptions) (*AuthorizedSession, error)
func NewAuthorizedSessionFromData(encryptedData []byte, config AuthorizedModelConfig,
inputNames, outputNames []string, options *SessionOptions) (*AuthorizedSession, error)
方法:
func (s *AuthorizedSession) Run(inputs, outputs []Value) error
func (s *AuthorizedSession) GetSession() *DynamicAdvancedSession
func (s *AuthorizedSession) Destroy() error
type QuotaTracker interface {
Increment(moduleName string) (int, error)
GetCount(moduleName string) int
Reset(moduleName string)
}
// 内置实现
func NewInMemoryQuotaTracker() *InMemoryQuotaTracker
type ModelAuthorizationInfo struct {
ModuleName string `json:"module_name"`
Salt []byte `json:"salt"`
ModelHash []byte `json:"model_hash,omitempty"`
InputNames []string `json:"input_names"`
OutputNames []string `json:"output_names"`
Description string `json:"description,omitempty"`
Version string `json:"version,omitempty"`
}
func (info *ModelAuthorizationInfo) ValidateModelHash(encryptedData []byte) bool
const (
TensorElementDataTypeUndefined TensorElementDataType = iota
TensorElementDataTypeFloat // float32
TensorElementDataTypeUint8 // uint8
TensorElementDataTypeInt8 // int8
TensorElementDataTypeUint16 // uint16
TensorElementDataTypeInt16 // int16
TensorElementDataTypeInt32 // int32
TensorElementDataTypeInt64 // int64
TensorElementDataTypeString // string
TensorElementDataTypeBool // bool
TensorElementDataTypeFloat16 // float16
TensorElementDataTypeDouble // float64
TensorElementDataTypeUint32 // uint32
TensorElementDataTypeUint64 // uint64
TensorElementDataTypeComplex64 // complex64
TensorElementDataTypeComplex128 // complex128
TensorElementDataTypeBFloat16 // bfloat16
)
const (
ONNXTypeUnknown ONNXType = iota
ONNXTypeTensor
ONNXTypeSequence
ONNXTypeMap
ONNXTypeOpaque
ONNXTypeSparseTensor
ONNXTypeOptional
)
const (
LoggingLevelVerbose LoggingLevel = iota // 详细
LoggingLevelInfo // 信息
LoggingLevelWarning // 警告
LoggingLevelError // 错误
LoggingLevelFatal // 致命
)
const (
EncryptedModelMagic = "ORTENC01" // 加密文件魔数头
AESKeySize = 32 // AES-256 密钥长度
GCMNonceSize = 12 // GCM nonce 长度
)
以下 API 已弃用,但为向后兼容而保留:
// 请使用 AdvancedSession 代替
type Session[T TensorData] struct{}
type DynamicSession[In, Out TensorData] struct{}
func NewSession[T TensorData](...) (*Session[T], error)
func NewDynamicSession[In, Out TensorData](...) (*DynamicSession[In, Out], error)
func NewSessionWithONNXData[T TensorData](...) (*Session[T], error)
func NewDynamicSessionWithONNXData[In, Out TensorData](...) (*DynamicSession[In, Out], error)
// Training API(onnxruntime 1.20+ 已弃用)
type TrainingSession struct{}
func NewTrainingSession(...) (*TrainingSession, error)
func IsTrainingSupported() bool // 始终返回 false
cudaOpts, _ := ort.NewCUDAProviderOptions()
defer cudaOpts.Destroy()
cudaOpts.Update(map[string]string{
"device_id": "0",
})
sessionOpts, _ := ort.NewSessionOptions()
defer sessionOpts.Destroy()
sessionOpts.AppendExecutionProviderCUDA(cudaOpts)
session, _ := ort.NewAdvancedSession("model.onnx",
inputNames, outputNames, inputs, outputs, sessionOpts)
trtOpts, _ := ort.NewTensorRTProviderOptions()
defer trtOpts.Destroy()
trtOpts.Update(map[string]string{
"device_id": "0",
"trt_fp16_enable": "1",
"trt_max_workspace_size": "2147483648",
})
sessionOpts, _ := ort.NewSessionOptions()
defer sessionOpts.Destroy()
sessionOpts.AppendExecutionProviderTensorRT(trtOpts)
session, _ := ort.NewDynamicAdvancedSession("model.onnx",
inputNames, outputNames, sessionOpts)
import (
"github.com/darkit/machineid"
"github.com/darkit/machineid/cert"
ort "cnb.cool/svn/onnxruntime"
)
func main() {
// 获取机器 ID
machineID, _ := machineid.ID()
// 创建授权验证器并加载证书
authorizer, _ := cert.NewAuthorizer().
WithCA(caPEM, caKeyPEM).
Build()
certAuth, _ := cert.NewCertAuthorization(certPEM, authorizer)
// 创建安全检查器
securityMgr := cert.NewSecurityManager(cert.SecurityLevelAdvanced)
// 配置授权会话
config := ort.AuthorizedModelConfig{
ModuleName: "ai.model.classifier",
MachineID: machineID,
Authorization: certAuth, // 实现 ort.Authorization 接口
SecurityChecker: securityMgr,
KeyDerivationSalt: []byte("app-salt"),
ValidateOnEveryRun: true,
QuotaTracker: ort.NewInMemoryQuotaTracker(),
}
session, _ := ort.NewAuthorizedSession("model.onnx.enc", config,
inputNames, outputNames, nil)
defer session.Destroy()
// 带授权检查的推理
session.Run(inputs, outputs)
}
# 运行所有测试
go test -v
# 运行基准测试
go test -v -bench=.
# 使用自定义 onnxruntime 库
ONNXRUNTIME_SHARED_LIBRARY_PATH=/path/to/libonnxruntime.so go test -v
本库使用 ONNX Runtime C API 版本 1.23.2。如需使用其他版本:
onnxruntime_c_api.h 和 onnxruntime_ep_c_api.h 为对应版本test_data/ 中的共享库请参阅原版 yalue/onnxruntime_go 仓库的许可证信息。
默认情况下,本库在运行时动态加载 ONNX Runtime。要使用静态链接的 ONNX Runtime 库,请使用 static 构建标签。
# 设置头文件和库路径
export CGO_CFLAGS="-I/opt/onnxruntime/include"
export CGO_LDFLAGS="-L/opt/onnxruntime/lib -l:libonnxruntime.a -lstdc++ -lm -lpthread -ldl"
# 使用 static 标签构建
go build -tags static ./...
Linux (仅 CPU):
export CGO_CFLAGS="-I/opt/onnxruntime/include"
export CGO_LDFLAGS="-L/opt/onnxruntime/lib -l:libonnxruntime.a -lstdc++ -lm -lpthread -ldl"
go build -tags static ./...
Linux (带 CUDA):
export CGO_CFLAGS="-I/opt/onnxruntime/include -I/usr/local/cuda/include"
export CGO_LDFLAGS="-L/opt/onnxruntime/lib -L/usr/local/cuda/lib64 \
-l:libonnxruntime.a -lcudart -lcublas -lcublasLt -lcudnn \
-lstdc++ -lm -lpthread -ldl"
go build -tags static ./...
Linux (带 TensorRT):
export CGO_CFLAGS="-I/opt/onnxruntime/include -I/usr/local/cuda/include -I/opt/TensorRT/include"
export CGO_LDFLAGS="-L/opt/onnxruntime/lib -L/usr/local/cuda/lib64 -L/opt/TensorRT/lib \
-l:libonnxruntime.a -lcudart -lcublas -lcublasLt -lcudnn \
-lnvinfer -lnvinfer_plugin -lnvonnxparser \
-lstdc++ -lm -lpthread -ldl"
go build -tags static ./...
macOS:
export CGO_CFLAGS="-I/opt/onnxruntime/include"
export CGO_LDFLAGS="-L/opt/onnxruntime/lib -lonnxruntime -lc++ \
-framework Foundation -framework CoreML"
go build -tags static ./...
Windows (MinGW):
set CGO_CFLAGS=-I/opt/onnxruntime/include
set CGO_LDFLAGS=-L/opt/onnxruntime/lib -lonnxruntime -lstdc++ -lm -lpthread
go build -tags static ./...
使用静态构建时,不需要调用 SetSharedLibraryPath():
package main
import (
ort "github.com/yalue/onnxruntime_go"
)
func main() {
// 静态构建:无需设置库路径
// 静态模式下 ort.SetSharedLibraryPath() 会被忽略
// 检查是否使用静态构建
if ort.IsStaticBuild() {
println("使用静态库")
}
// 正常初始化
if err := ort.InitializeEnvironment(); err != nil {
panic(err)
}
defer ort.DestroyEnvironment()
// ... 其余代码
}
// IsStaticBuild 返回是否使用 -tags static 编译
func IsStaticBuild() bool
可以混合使用静态和动态链接以获得最佳部署效果:
# -l:libxxx.a 强制静态链接指定库
# -lxxx 优先动态链接,找不到则静态
# -Wl,-Bstatic 后续库使用静态链接
# -Wl,-Bdynamic 后续库使用动态链接
export CGO_CFLAGS="-I/opt/onnxruntime/include -I/usr/local/cuda/include"
export CGO_LDFLAGS="\
-L/opt/onnxruntime/lib \
-L/usr/local/cuda/lib64 \
-Wl,-Bstatic -lonnxruntime \
-Wl,-Bdynamic -lcudart -lcublas -lcublasLt -lcudnn \
-lstdc++ -lm -lpthread -ldl"
go build -tags static ./...
export CGO_LDFLAGS="\
-L/opt/onnxruntime/lib \
-L/usr/local/cuda/lib64 \
-L/opt/TensorRT/lib \
-Wl,-Bstatic -lonnxruntime \
-Wl,-Bdynamic -lcudart -lcublas -lcudnn \
-lnvinfer -lnvinfer_plugin \
-lstdc++ -lm -lpthread -ldl"
export CGO_LDFLAGS="\
-L/opt/onnxruntime/lib \
-L/usr/local/cuda/lib64/stubs \
-Wl,-Bstatic \
-lonnxruntime \
-lcudart_static -lcublas_static -lcublasLt_static \
-Wl,-Bdynamic \
-ldl -lpthread -lrt -lm"
# Linux - 查看动态依赖
ldd ./myapp
# 查看所有符号(包括静态链接的)
nm ./myapp | grep -i onnx
# macOS
otool -L ./myapp
| 优点 | 缺点 |
|---|---|
| 核心功能便携 | 配置较复杂 |
| GPU 库可随系统更新 | 需要理解链接器行为 |
| 可执行文件相对较小 | 部分库仍需部署 |
| 兼顾便携性和灵活性 | 调试时需注意版本匹配 |
# onnxruntime 静态(核心功能便携)
# CUDA/cuDNN 动态(跟随驱动版本)
# 系统库动态(libc, libm, libpthread)
CGO_LDFLAGS="\
-Wl,-Bstatic -l:libonnxruntime.a \
-Wl,-Bdynamic -lcudart -lcudnn -lcublas \
-lstdc++ -lm -lpthread -ldl"
这样编译出的程序:
libonnxruntime.so