环境配置

CUDA 环境

graph TD
    A[CUDA 环境] --> B[CUDA 12.4]
    A --> C[PyTorch 2.5.1+cu124]
    A --> D[onnxruntime-gpu 1.20.0]
    A --> E[cuDNN 9.x]

依赖版本

# 核心依赖
torch>=2.0.0,<2.6.0
torchvision>=0.15.0,<0.21.0
torchaudio>=2.0.0,<2.6.0
onnxruntime-gpu==1.20.0
optimum[onnxruntime-gpu]>=1.12.0,<1.20.0

模型转换流程

1. 转换脚本

#!/bin/bash
# official_convert.sh
 
# 配置路径
ORIGINAL_MODEL="/users/yusizhen/models/vad_turn"
OUTPUT_BASE="./converted_models"
ONNX_OUTPUT="$OUTPUT_BASE/onnx"
 
# 转换为ONNX
optimum-cli export onnx \
    --model "$ORIGINAL_MODEL" \
    --task sequence-classification \
    --framework pt \
    --opset 14 \
    --atol 1e-3 \
    "$ONNX_OUTPUT"

2. 性能优化

graph LR
    A[模型转换] --> B[ONNX Runtime]
    B --> C[CUDA 执行]
    B --> D[CPU 执行]
    C --> E[性能优化]
    E --> F[内存优化]
    E --> G[计算优化]

推理性能

测试结果

  • PyTorch 推理时间: 20.32ms
  • ONNX 推理时间: 9.15ms
  • 加速比: 2.22x

精度验证

  • 预测结果完全一致
  • Logits 最大差异: 0.003769
  • 分类准确率: 100%

代码实现

1. 模型加载

# 加载 ONNX 模型
onnx_model = ORTModelForSequenceClassification.from_pretrained(
    onnx_path,
    provider="CUDAExecutionProvider",
    local_files_only=True
)

2. 推理实现

# 准备输入
inputs = tokenizer(test_text, return_tensors="pt", truncation=True, padding=True)
inputs = {k: v.cuda() for k, v in inputs.items()}
 
# ONNX 推理
onnx_output = onnx_model(**inputs)
onnx_logits = onnx_output.logits
onnx_pred = torch.argmax(onnx_logits, dim=-1).cpu().numpy()[0]

REFER

依赖

# =============================================================================
# 深度学习核心框架
# =============================================================================
--extra-index-url https://download.pytorch.org/whl/cu124
torch>=2.0.0,<2.6.0
torchvision>=0.15.0,<0.21.0
torchaudio>=2.0.0,<2.6.0
 
# =============================================================================
# Transformers生态系统
# =============================================================================
transformers>=4.30.0,<4.50.0
accelerate>=0.20.0,<0.30.0
tokenizers>=0.13.0,<0.20.0
safetensors>=0.3.0,<0.5.0
huggingface-hub>=0.16.0,<0.25.0
 
# =============================================================================
# 数据处理和工具
# =============================================================================
datasets>=2.10.0,<2.20.0
sentencepiece>=0.1.99,<0.2.0
protobuf>=3.20.0,<4.0.0
numpy>=1.21.0,<2.0.0
tiktoken>=0.4.0,<0.8.0
 
# =============================================================================
# 推理优化工具
# ============================================================================
onnxruntime-gpu>=1.18.1
optimum[onnxruntime-gpu]>=1.12.0,<1.20.0
 
# =============================================================================
# Web服务框架
# =============================================================================
fastapi>=0.95.0,<0.110.0
uvicorn>=0.20.0,<0.30.0
pydantic>=2.0.0,<3.0.0
 
# =============================================================================
# 音频处理
# =============================================================================
librosa>=0.10.0,<0.11.0
 
# =============================================================================
# 语音识别(可选,如果需要的话)
# =============================================================================
# funasr>=1.0.0
 
# =============================================================================
# 注意:TensorRT建议单独安装
tensorrt  # 请在环境设置完成后单独安装
# =============================================================================

代码

# correct_onnx_test.py
import time
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification
from optimum.onnxruntime import ORTModelForSequenceClassification
import onnxruntime as ort
 
# 路径配置
original_path = "/users/yusizhen/models/vad_turn"
onnx_path = "/group-shared/models/trained_models/turn-detection-1.5B-250605-onnx"
 
print("🧪 ONNX GPU 性能测试...")
 
# 检查 CUDA 可用性
print("\n🔍 检查 CUDA 可用性...")
cuda_available = torch.cuda.is_available()
print(f"CUDA 是否可用: {'✅' if cuda_available else '❌'}")
 
# 检查 ONNX Runtime 执行提供程序
print("\n🔍 检查 ONNX Runtime 执行提供程序...")
available_providers = ort.get_available_providers()
print(f"可用的执行提供程序: {available_providers}")
 
# 1. Tokenizer 加载
print("\n📦 加载 tokenizer...")
tokenizer = AutoTokenizer.from_pretrained(
    original_path,
    local_files_only=True,
    trust_remote_code=True,
    use_fast=False  # 使用慢速 tokenizer
)
print("✅ Tokenizer 加载成功")
 
# 2. PyTorch 模型加载
print("\n📦 加载 PyTorch 模型...")
pytorch_model = AutoModelForSequenceClassification.from_pretrained(
    original_path,
    local_files_only=True,
    trust_remote_code=True
).cuda()
pytorch_model.eval()
print("✅ PyTorch 模型加载成功")
 
# 3. ONNX 模型加载
print("\n📦 加载 ONNX 模型...")
onnx_model = ORTModelForSequenceClassification.from_pretrained(
    onnx_path,
    provider="CUDAExecutionProvider",
    local_files_only=True
)
print("✅ ONNX 模型加载成功")
print(f"ONNX 模型使用的执行提供程序: {onnx_model.model.get_providers()}")
 
# 4. 测试推理
test_text = "这是一个测试文本,用于验证模型转换效果"
print(f"\n🧪 测试文本: {test_text}")
 
# 准备输入
inputs = tokenizer(test_text, return_tensors="pt", truncation=True, padding=True)
inputs = {k: v.cuda() for k, v in inputs.items()}
 
# 测试 PyTorch
print("\n🐌 测试 PyTorch 推理...")
with torch.no_grad():
    pytorch_output = pytorch_model(**inputs)
pytorch_logits = pytorch_output.logits
pytorch_pred = torch.argmax(pytorch_logits, dim=-1).cpu().numpy()[0]
 
# 测试 ONNX
print("🚀 测试 ONNX 推理...")
onnx_output = onnx_model(**inputs)
onnx_logits = onnx_output.logits
onnx_pred = torch.argmax(onnx_logits, dim=-1).cpu().numpy()[0]
 
# 验证精度
print("\n🔍 精度验证:")
print(f"PyTorch 预测: {pytorch_pred}")
print(f"ONNX 预测: {onnx_pred}")
print(f"预测一致: {'✅' if pytorch_pred == onnx_pred else '❌'}")
 
# 计算 logits 差异
pytorch_logits = pytorch_logits.cpu()  # 将 PyTorch logits 移到 CPU
onnx_logits = onnx_logits.cpu()  # 确保 ONNX logits 也在 CPU 上
max_diff = torch.max(torch.abs(pytorch_logits - onnx_logits)).item()
print(f"Logits 最大差异: {max_diff:.6f}")
 
# 性能测试
print("\n⚡ 性能测试 (10次推理平均):")
# PyTorch
start = time.time()
for _ in range(10):
    with torch.no_grad():
        _ = pytorch_model(**inputs)
pytorch_time = (time.time() - start) / 10 * 1000
 
# ONNX
start = time.time()
for _ in range(10):
    _ = onnx_model(**inputs)
onnx_time = (time.time() - start) / 10 * 1000
 
print(f"PyTorch: {pytorch_time:.2f}ms")
print(f"ONNX:    {onnx_time:.2f}ms")
print(f"加速比:   {pytorch_time/onnx_time:.2f}x")
 
print(f"\n🎉 测试完成!")