ONNX Runtime GenAI C++ GPU 推理完整指南

ONNX Runtime GenAI C++ GPU 推理完整指南

问题背景

在使用 ONNX Runtime GenAI v0.12.0 进行 C++ GPU 推理时,遇到了多个挑战:

  1. C++ API 兼容性问题:官方预编译包只导出 C API,C++ API 符号缺失
  2. 库版本不匹配:初始下载的 onnxruntime 版本过旧(1.17.1),不支持 genai 所需的 API version
  3. 模型 Opset 兼容性:Phi-4 等新模型使用最新的 GroupQueryAttention softcap 属性,需要 onnxruntime v1.20+

解决方案

一、从 C++ API 改为 C API

官方预编译包不支持 C++ API(OgaModel、OgaTokenizer 等类),所以需要改用 C API 调用:

C++ API(不可用):

cpp 复制代码
auto model = OgaModel::Create(model_path);  // ❌ 链接时 undefined reference

C API(可用):

cpp 复制代码
OgaModel* model = NULL;
CHECK_OGA(OgaCreateModel(model_path, &model));  // ✅ 官方包导出的符号

二、解决库依赖问题

运行时报错:

复制代码
Failed to load onnxruntime. Set ORTGENAI_LOG_ORT_LIB envvar to enable detailed logging.

根本原因:genai SDK 需要链接 libonnxruntime.so,但官方预编译包缺少这个库。

解决方案:在 CMake 中自动下载兼容版本的 onnxruntime,并复制库文件到 genai SDK lib 目录。

三、版本匹配

不同版本要求:

组件 版本 需求
onnxruntime-genai 0.12.0 ORT API version ≥ 18
onnxruntime 1.17.1 仅支持 API version ≤ 17 ❌
onnxruntime 1.18.1 支持 API version 18 ✅
onnxruntime 1.20.1 支持 API version 18+,新 Opset ✅✅
Phi-4 ONNX 模型 - 需要 GroupQueryAttention softcap(1.20+)

最终实现

1. 修改 CMakeLists.txt

cmake 复制代码
# 添加 onnxruntime.cmake 支持(可选备选)
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
set(SHERPA_ONNX_ENABLE_GPU ${ENABLE_CUDA})
include(onnxruntime)  # 可选

# 自动下载和配置 genai SDK
include(onnxruntime-genai)

2. 关键文件:cmake/onnxruntime-genai.cmake

cmake 复制代码
# ONNX Runtime GenAI v0.12.0 配置
include(FetchContent)

set(ONNX_GENAI_VERSION "0.12.0")
set(ONNXRUNTIME_VERSION "1.20.1")  # 兼容最新模型

# 根据平台选择下载 URL
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
    if(ENABLE_CUDA)
        set(GENAI_URL "https://github.com/microsoft/onnxruntime-genai/releases/download/v${ONNX_GENAI_VERSION}/onnxruntime-genai-${ONNX_GENAI_VERSION}-linux-x64-cuda.tar.gz")
        set(ORT_URL "https://github.com/microsoft/onnxruntime/releases/download/v${ONNXRUNTIME_VERSION}/onnxruntime-linux-x64-gpu-${ONNXRUNTIME_VERSION}.tgz")
    else()
        set(GENAI_URL "https://github.com/microsoft/onnxruntime-genai/releases/download/v${ONNX_GENAI_VERSION}/onnxruntime-genai-${ONNX_GENAI_VERSION}-linux-x64.tar.gz")
        set(ORT_URL "https://github.com/microsoft/onnxruntime/releases/download/v${ONNXRUNTIME_VERSION}/onnxruntime-linux-x64-${ONNXRUNTIME_VERSION}.tgz")
    endif()
endif()

# 下载 genai SDK
FetchContent_Declare(onnxruntime_genai URL ${GENAI_URL})
FetchContent_MakeAvailable(onnxruntime_genai)

set(ONNX_GENAI_SDK_DIR ${onnxruntime_genai_SOURCE_DIR})
set(ONNX_GENAI_INCLUDE_DIRS "${ONNX_GENAI_SDK_DIR}/include")
set(ONNX_GENAI_LIB_DIRS "${ONNX_GENAI_SDK_DIR}/lib")

# 下载兼容版本的 onnxruntime
FetchContent_Declare(onnxruntime_compat URL ${ORT_URL})
FetchContent_MakeAvailable(onnxruntime_compat)

# 复制 libonnxruntime.so* 到 genai SDK lib 目录
file(GLOB ORT_LIBS "${onnxruntime_compat_SOURCE_DIR}/lib/libonnxruntime.so*")
if(ORT_LIBS)
    file(COPY ${ORT_LIBS} DESTINATION "${ONNX_GENAI_LIB_DIRS}")
    message(STATUS "✓ Copied onnxruntime libraries")
endif()

message(STATUS "✅ ONNX Runtime GenAI v${ONNX_GENAI_VERSION} ready!")

3. C API 推理代码(test/test.cpp)

cpp 复制代码
#include <ort_genai_c.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define CHECK_OGA(call) do { \
    OgaResult* _res = (call); \
    if (_res) { \
        fprintf(stderr, "❌ Error: %s\n", OgaResultGetError(_res)); \
        OgaDestroyResult(_res); \
        exit(1); \
    } \
} while(0)

int main() {
    const char* model_path = "/mnt/f/cache/Phi-4-mini-instruct-onnx/gpu/gpu-int4-rtn-block-32";
    const char* prompt = "用简单易懂的话解释 ONNX Runtime GenAI.用中文回答。";

    OgaModel* model = NULL;
    OgaTokenizer* tokenizer = NULL;
    OgaSequences* sequences = NULL;
    OgaGeneratorParams* params = NULL;
    OgaGenerator* generator = NULL;

    // 1. 加载模型
    CHECK_OGA(OgaCreateModel(model_path, &model));

    // 2. 创建 Tokenizer
    CHECK_OGA(OgaCreateTokenizer(model, &tokenizer));

    // 3. 编码 Prompt
    CHECK_OGA(OgaCreateSequences(&sequences));
    CHECK_OGA(OgaTokenizerEncode(tokenizer, prompt, sequences));

    // 4. Generator 参数
    CHECK_OGA(OgaCreateGeneratorParams(model, &params));
    CHECK_OGA(OgaGeneratorParamsSetSearchNumber(params, "max_length", 256));
    CHECK_OGA(OgaGeneratorParamsSetSearchNumber(params, "temperature", 0.7f));
    CHECK_OGA(OgaGeneratorParamsSetSearchNumber(params, "top_p", 0.9f));
    CHECK_OGA(OgaGeneratorParamsSetSearchBool(params, "do_sample", 1));

    // 5. 创建 Generator
    CHECK_OGA(OgaCreateGenerator(model, params, &generator));
    CHECK_OGA(OgaGenerator_AppendTokenSequences(generator, sequences));

    // 6. Streaming 推理
    printf("=== Streaming Output (GPU, C API) ===\n\n");
    while (!OgaGenerator_IsDone(generator)) {
        CHECK_OGA(OgaGenerator_GenerateNextToken(generator));
        const int32_t* new_tokens = NULL;
        size_t new_token_count = 0;
        CHECK_OGA(OgaGenerator_GetNextTokens(generator, &new_tokens, &new_token_count));
        if (new_token_count > 0) {
            const char* text = NULL;
            CHECK_OGA(OgaTokenizerDecode(tokenizer, new_tokens, new_token_count, &text));
            printf("%s", text);
            fflush(stdout);
            OgaDestroyString(text);
        }
    }
    printf("\n\n=== Done ===\n");

    // 释放资源
    OgaDestroyGenerator(generator);
    OgaDestroyGeneratorParams(params);
    OgaDestroySequences(sequences);
    OgaDestroyTokenizer(tokenizer);
    OgaDestroyModel(model);

    return 0;
}

4. CMake 链接配置(test/CMakeLists.txt)

cmake 复制代码
# 必须同时链接 onnxruntime-genai-cuda 和 onnxruntime
if(ENABLE_CUDA)
    target_link_libraries(test_gpu PRIVATE onnxruntime-genai-cuda onnxruntime-genai)
else()
    target_link_libraries(test_gpu PRIVATE onnxruntime-genai)
endif()

# 链接标准库
target_link_libraries(test_gpu PRIVATE pthread dl)

编译与运行

编译

bash 复制代码
# 清除旧 build
rm -rf /mnt/f/Projects/onnx-genai-decoder/build_test

# 编译(自动下载 genai SDK 和 onnxruntime v1.20.1)
./build_test.sh

编译过程会自动:

  1. 下载 onnxruntime-genai v0.12.0 SDK
  2. 下载 onnxruntime v1.20.1(GPU 版本)
  3. 复制 libonnxruntime.so 到 genai SDK lib 目录
  4. 编译 test_gpu 可执行文件

运行

bash 复制代码
# 设置库路径
export LD_LIBRARY_PATH=/mnt/f/Projects/onnx-genai-decoder/build_test/_deps/onnxruntime_genai-src/lib:$LD_LIBRARY_PATH

# 运行推理
/mnt/f/Projects/onnx-genai-decoder/build_test/bin/test_gpu

输出:

关键要点总结

问题 解决方案
C++ API 符号缺失 改用官方导出的 C API(OgaCreateModel 等)
libonnxruntime.so 缺失 CMake 自动下载兼容版本的 onnxruntime 并复制库文件
版本 API 不匹配(ORT v1.17) 升级到 onnxruntime v1.20.1(支持最新 Opset 和 softcap 属性)
模型 Opset 不兼容 v1.20.1 原生支持 GroupQueryAttention softcap

技术栈

  • ONNX Runtime GenAI: v0.12.0
  • ONNX Runtime: v1.20.1 (GPU/CUDA)
  • CMake: v3.20+
  • C++: 17 标准
  • GPU: NVIDIA CUDA 支持

优势

自动化 :CMake 自动下载所有依赖,无需手动配置

跨平台 :支持 Linux/macOS/Windows(代码已预留平台判断)

版本兼容 :自动选择兼容的 onnxruntime 版本

GPU 加速 :完整 CUDA 支持,高性能推理

流式输出:支持 token 级别的流式生成

相关推荐
鸿乃江边鸟2 小时前
用 oh-my-opencode 写一个word转pdf skill
pdf·大模型·opencode
CoderJia程序员甲10 小时前
GitHub 热榜项目 - 日榜(2026-02-22)
人工智能·ai·大模型·github·ai教程
CoderJia程序员甲12 小时前
GitHub 热榜项目 - 日榜(2026-02-21)
ai·大模型·llm·github·ai教程
重生之我要成为代码大佬12 小时前
AI框架设计与选型
人工智能·langchain·大模型·llama·qwen
梦想画家16 小时前
2026开年大模型最新对比解析及场景落地指南
语言模型·大模型
sg_knight20 小时前
Claude Code 的账号、模型与使用限制说明
ai·大模型·llm·ai编程·claude·code·claude-code
AI周红伟21 小时前
周红伟:Sglang+Vllm+Qwen3.5企业级部署案例实操
大数据·人工智能·大模型·智能体
AI周红伟1 天前
大模型部署入门教程,消费级显卡跑通Qwen3.5-Plus,最低配置部署教程,不能在简单了
大数据·人工智能·大模型·智能体
雪碧聊技术1 天前
提示词书写技巧
大模型·文生图·即梦ai·seedance2.0