ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Triton Inference Server C API 内嵌模式指南:通过 libtritonserver.so 将推理服务直接集成进 C/C++ 应用

2026/9/24 4:08:45 拓冰建站 浏览量
Triton Inference Server C API 内嵌模式指南:通过 libtritonserver.so 将推理服务直接集成进 C/C++ 应用 模型推理服务AI 应用后端【免费下载链接】serverThe Triton Inference Server provides an optimized cloud and edge inferencing solution.项目地址https://gitcode.com/gh_mirrors/server117/server点击查看免费下载本篇技术指南以 Triton Inference Server 的 C APIServer API为主题讲解如何将 Triton 的全部核心能力以共享库Linux 下为libtritonserver.so的形式链接进自有 C/C 应用从而绕过 HTTP/gRPC 网络层、以进程内方式直接完成模型管理、健康检查与异步推理。读完本文你将掌握TRITONSERVER_Server的创建、TRITONSERVER_Error错误对象生命周期管理、Server API 版本兼容性检查以及基于TRITONSERVER_ResponseAllocator与回调机制的完整异步推理请求流程并理解 Triton 自身的 HTTP/REST 与 gRPC 端点是如何以这套 API 为底层实现的。从独立进程到进程内嵌入C API 的定位Triton Inference Server 的全部功能都被封装在一个共享库中该共享库由 Triton 的 core 仓库源码构建而来。当你将这份共享库链接进自己的应用时并没有启动一个独立的 Triton 进程而是把 Triton 核心逻辑直接包含在了应用内部应用与 Triton 核心逻辑之间不经过 HTTP/REST 或 gRPC 协议不存在网络序列化与反序列化开销所有通信都必须通过tritonserver.h中定义的Server API完成在 Triton Docker 镜像中该共享库位于/opt/tritonserver/lib在 Linux 上即libtritonserver.so头文件为include/triton/core/tritonserver.h定义并完整文档化 Server API该头文件属于 core 仓库。这一进程内嵌入模式的权威佐证就在本仓库自身Triton 的tritonserver可执行程序实现的 HTTP/REST 与 gRPC 端点正是通过 Server API 与核心逻辑通信的主源码文件为 grpc_server.cc 与 http_server.cc。换句话说Triton 官方前端本身就是一个 C API 的超大型客户端示例阅读这两个文件可以看到 Server API 在真实生产代码中的完整调用方式。此外进程内 API 总览文档 还指出Java 绑定inprocess_java_api.md同样构建在tritonserver.h之上供需要在进程内使用 Triton 的 Java 应用使用。顶层抽象TRITONSERVER_Server 与 ServerOptionsServer API 的顶层抽象是TRITONSERVER_Server它代表能够实现 Triton 全部功能与能力的核心逻辑对象。一个TRITONSERVER_Server对象通过调用TRITONSERVER_ServerNew创建调用时需要传入一组描述初始化方式的选项TRITONSERVER_ServerOptions。TRITONSERVER_ServerNew的用法在本仓库的 simple.cc 中得到完整演示。以该示例的main()流程为线索一个最小的服务器创建过程包含以下步骤通过TRITONSERVER_ServerOptionsNew创建选项对象依次调用各类TRITONSERVER_ServerOptionsSet*函数设置初始化参数调用TRITONSERVER_ServerNew(server_ptr, server_options)创建服务器对象创建完成后即可用TRITONSERVER_ServerOptionsDelete删除选项对象服务器已持有所需配置。simple.cc 中使用的关键 ServerOptions 设置函数及语义如下选项设置函数示例参数作用TRITONSERVER_ServerOptionsSetModelRepositoryPath模型仓库路径字符串指定模型仓库位置Triton 启动时加载其中模型TRITONSERVER_ServerOptionsSetLogVerbose0 或 1设置日志详细级别TRITONSERVER_ServerOptionsSetBackendDirectory/opt/tritonserver/backends指定后端backend动态库目录TRITONSERVER_ServerOptionsSetRepoAgentDirectory/opt/tritonserver/repoagents指定仓库代理repository agent目录TRITONSERVER_ServerOptionsSetStrictModelConfigtrue是否启用严格模型配置校验TRITONSERVER_ServerOptionsSetMinSupportedComputeCapabilityTRITON_MIN_COMPUTE_CAPABILITY或 0设置支持的 CUDA 最小计算能力GPU 构建下生效TRITONSERVER_Server对象的生命周期可以由std::shared_ptr结合删除函数TRITONSERVER_ServerDelete托管如 simple.cc 所示TRITONSERVER_Server* server_ptr nullptr; FAIL_IF_ERR( TRITONSERVER_ServerNew(server_ptr, server_options), creating server object); FAIL_IF_ERR( TRITONSERVER_ServerOptionsDelete(server_options), deleting server options); std::shared_ptrTRITONSERVER_Server server( server_ptr, TRITONSERVER_ServerDelete);通常一个应用只需一个服务器对象但 API 也允许在同一应用内创建多个服务器对象。服务器创建完成后所有 Server API 对象的所有权与生命周期规则都以tritonserver.h中的文档为准。错误处理TRITONSERVER_Error 对象与生命周期绝大多数 Server API 函数都会返回一个错误对象来表示成功或失败成功返回nullptrNULL失败返回一个TRITONSERVER_Error对象可通过TRITONSERVER_ErrorCode和TRITONSERVER_ErrorMessage分别取出错误码与错误消息。对于TRITONSERVER_Error所有权会转移给 Server API 函数的调用方。因此应用必须负责管理返回错误对象的生命周期使用完毕后必须调用TRITONSERVER_ErrorDelete删除它。若忘记删除会造成资源泄漏。为了简化错误对象生命周期管理common.h 中提供了一系列便捷宏这是所有 Triton 官方 C/C 代码的通用范式RETURN_IF_ERR(X)出错时直接返回错误对象常用于返回TRITONSERVER_Error*的函数RETURN_MSG_IF_ERR(X, MSG)出错时将自定义消息与原始错误信息拼接后返回GOTO_IF_ERR(X, T)出错时跳转到标签TFAIL_IF_ERR(X, MSG)出错时打印错误码与错误消息、删除错误对象并以退出码 1 终止程序常用于示例代码THROW_IF_ERR(EX_TYPE, X, MSG)出错时抛出指定类型的 C 异常IGNORE_ERR(X)仅删除错误对象忽略错误在启用 GPU 构建时还有FAIL_IF_CUDA_ERR(X, MSG)用于检查 CUDA API 返回值。例如 common.h 中FAIL_IF_ERR的实现#define FAIL_IF_ERR(X, MSG) \ do { \ TRITONSERVER_Error* err__ (X); \ if (err__ ! nullptr) { \ std::cerr error: (MSG) : \ TRITONSERVER_ErrorCodeString(err__) - \ TRITONSERVER_ErrorMessage(err__) std::endl; \ TRITONSERVER_ErrorDelete(err__); \ exit(1); \ } \ } while (false)可以看到宏内部同时完成了取码、取消息、打印与删除这正是文档所强调的管理错误对象生命周期的推荐做法。版本管理与向后兼容性检查Server API 是向后兼容的。只要满足以下条件你的应用就可以安全地使用该 API共享库提供的主版本号major与你编译应用所用的头文件主版本号一致共享库提供的次版本号minor大于或等于你编译应用所用的头文件次版本号。simple.cc 中演示了典型的版本比较模式以下代码块即原文档中的示例错误检查已省略#include tritonserver.h // Error checking removed for clarity... uint32_t api_version_major, api_version_minor; TRITONSERVER_ApiVersion(api_version_major, api_version_minor); if ((TRITONSERVER_API_VERSION_MAJOR ! api_version_major) || (TRITONSERVER_API_VERSION_MINOR api_version_minor)) { // Error, the shared library implementing the Server API is older than // the version of the Server API that you compiled against. }在 simple.cc 的实际代码中这一检查通过FAIL_IF_ERR与FAIL完成先调用TRITONSERVER_ApiVersion获取共享库版本一旦发现主版本不一致或编译时次版本大于运行时次版本即判定triton server API version mismatch并终止。非推理 API健康检查、模型信息与统计Server API 除了推理之外还包含一系列非推理功能检查服务器存活live与就绪ready状态TRITONSERVER_ServerIsLive、TRITONSERVER_ServerIsReady获取服务器元数据TRITONSERVER_ServerMetadata获取模型元数据与模型就绪状态TRITONSERVER_ServerModelMetadata、TRITONSERVER_ServerModelIsReady获取模型统计与指标、加载/卸载模型等。这些函数的使用非常直接在 simple.cc 中有部分演示。以健康检查为例simple.cc 在创建服务器后循环调用TRITONSERVER_ServerIsLive与TRITONSERVER_ServerIsReady直到两者都为true最多轮询 10 次、每次间隔 500ms才继续while (true) { bool live, ready; FAIL_IF_ERR( TRITONSERVER_ServerIsLive(server.get(), live), unable to get server liveness); FAIL_IF_ERR( TRITONSERVER_ServerIsReady(server.get(), ready), unable to get server readiness); if (live ready) { break; } ... std::this_thread::sleep_for(std::chrono::milliseconds(500)); }服务器不会在全部模型加载并准备就绪之前显示为 ready因此先等服务器 ready同时也就隐含了模型已就绪的语义。不过 simple.cc 仍额外演示了对特定模型simple模型、版本 1的就绪轮询先调用TRITONSERVER_ServerModelIsReady就绪后通过TRITONSERVER_ServerModelMetadata获取模型元数据消息。元数据服务器级与模型级都以抽象的TRITONSERVER_Message返回可通过TRITONSERVER_MessageSerializeToJson序列化为 JSON 字符串再用任意 JSON 解析器simple.cc 使用 rapidjson解析处理处理完毕后以TRITONSERVER_MessageDelete释放。这一机制也是动态读取模型输入输出信息、进而构造推理请求的常用手段——simple.cc 正是从模型元数据 JSON 中解析出输入输出数据类型仅支持 INT32/FP32与平台判断是否为pytorch_libtorch从而确定输出张量命名OUTPUT__0/OUTPUT__1还是OUTPUT0/OUTPUT1再据此生成请求。推理 API一次异步推理请求的完整流程执行一次推理请求需要用到多个 Server API 函数与对象。整体流程在 simple.cc 中有完整演示可归纳为四个阶段创建响应分配器 → 构建推理请求 → 异步提交 → 处理响应。阶段一创建 TRITONSERVER_ResponseAllocator调用TRITONSERVER_ResponseAllocatorNew创建响应分配器。当 Triton 产生输出张量时它需要一个内存缓冲区来存放张量内容而 Triton 会延迟这一分配动作转而调用你应用中的回调函数。你通过TRITONSERVER_ResponseAllocator对象把这两个回调告诉 Triton缓冲区分配回调类型TRITONSERVER_ResponseAllocatorAllocFn_t缓冲区释放回调类型TRITONSERVER_ResponseAllocatorReleaseFn_t。两个回调的签名都以tritonserver.h中的定义为准。在 simple.cc 中它们分别实现为ResponseAlloc与ResponseReleaseTRITONSERVER_ResponseAllocator* allocator nullptr; FAIL_IF_ERR( TRITONSERVER_ResponseAllocatorNew( allocator, ResponseAlloc, ResponseRelease, nullptr /* start_fn */), creating response allocator);ResponseAlloc的实现要点simple.cc展示了内存类型协商机制默认令实际内存类型与 ID 等于 Triton 偏好的内存类型preferred_memory_type/preferred_memory_type_id若byte_size 0直接返回buffer nullptr无需额外簿记根据内存类型分支分配TRITONSERVER_MEMORY_CPU使用malloc分配系统内存TRITONSERVER_MEMORY_CPU_PINNED先cudaSetDevice再以cudaHostAlloc(..., cudaHostAllocPortable)分配页锁定内存TRITONSERVER_MEMORY_GPU先cudaSetDevice再以cudaMalloc分配设备内存未知类型默认回退到 CPU 内存分配成功后通过*buffer与*buffer_userp返回缓冲区指针与用户数据示例中把张量名存于buffer_userp以便释放时打印。ResponseRelease则根据内存类型执行对应的释放操作free、cudaFreeHost或cudaFreesimple.cc。你可以让所有推理请求共用一个响应分配器也可以创建多个。这一设计意味着你可以完全自定义输出缓冲区的管理策略如内存池、共享缓冲区这正是 C API 进程内模式相对网络模式的灵活性优势之一。阶段二构建 TRITONSERVER_InferenceRequest推理请求对象TRITONSERVER_InferenceRequest用于指定要使用的模型、输入张量及其数值、希望返回的输出张量以及其他请求参数。创建与填充步骤如下用TRITONSERVER_InferenceRequestNew创建请求对象。在 simple.cc 中模型版本传-1表示由 Triton 决定版本TRITONSERVER_InferenceRequest* irequest nullptr; FAIL_IF_ERR( TRITONSERVER_InferenceRequestNew( irequest, server.get(), model_name.c_str(), -1 /* model_version */), creating inference request);用TRITONSERVER_InferenceRequestAddInput添加每个输入张量指定名称、数据类型TRITONSERVER_DataType与形状std::vectorint64_t input0_shape({1, 16}); FAIL_IF_ERR( TRITONSERVER_InferenceRequestAddInput( irequest, input0, datatype, input0_shape[0], input0_shape.size()), setting input 0 meta-data for the request);用TRITONSERVER_InferenceRequestAppendInputData或其变体为输入张量填充数据需要指定数据指针、字节数与内存类型及内存类型 IDFAIL_IF_ERR( TRITONSERVER_InferenceRequestAppendInputData( irequest, input0, input0_base, input0_size, requested_memory_type, 0 /* memory_type_id */), assigning INPUT0 data);默认情况下 Triton 会返回全部输出张量但你可以用TRITONSERVER_InferenceRequestAddRequestedOutput限定只返回部分输出。这些调用是可选的。必须用TRITONSERVER_InferenceRequestSetReleaseCallback设置一个释放回调。Triton 会在归还TRITONSERVER_InferenceRequest对象所有权时调用它。典型实现中你只需在其中调用TRITONSERVER_InferenceRequestDelete删除对象但如果要复用请求对象也可以实现不同的生命周期管理如使其回到可复用状态。可选地用TRITONSERVER_InferenceRequestSetId设置用户自定义 ID。该 ID 不被 Triton 使用但会随响应原样返回用于请求与响应的关联。请求对象可以复用一个已有的TRITONSERVER_InferenceRequest对象可以被重复用于新的推理请求。例如 simple.cc 中第二次推理直接在原地修改input0_data缓冲区内容后再次提交第三次推理则先用TRITONSERVER_InferenceRequestRemoveAllInputData移除 INPUT0 的既有数据再把 INPUT1 的数据缓冲区赋给 INPUT0从而演示了同一请求对象、不同输入数据的复用模式。每次复用前都必须等待上一次请求被释放通过request_release_future.get()同步否则在屏障析构后释放回调会触发段错误。阶段三以 TRITONSERVER_ServerInferAsync 异步提交用TRITONSERVER_ServerInferAsync请求 Triton 执行推理。这是一个异步调用立即返回推理响应通过你注册的回调交付在调用TRITONSERVER_ServerInferAsync之前先用TRITONSERVER_InferenceRequestSetResponseCallback注册响应回调simple.cc 中为InferResponseComplete同时传入之前创建的响应分配器所有权转移语义当TRITONSERVER_ServerInferAsync无错误返回时TRITONSERVER_InferenceRequest对象的所有权就交给了 Triton。在 Triton 通过TRITONSERVER_InferenceRequestSetReleaseCallback注册的回调把所有权归还给你之前你绝不能以任何方式访问该对象。simple.cc 中的典型提交代码auto p new std::promiseTRITONSERVER_InferenceResponse*(); std::futureTRITONSERVER_InferenceResponse* completed p-get_future(); FAIL_IF_ERR( TRITONSERVER_InferenceRequestSetResponseCallback( irequest, allocator, nullptr /* response_allocator_userp */, InferResponseComplete, reinterpret_castvoid*(p)), setting response callback); FAIL_IF_ERR( TRITONSERVER_ServerInferAsync( server.get(), irequest, nullptr /* trace */), running inference);阶段四处理 TRITONSERVER_InferenceResponse推理响应会交给你在响应回调中注册的函数回调收到的是一个TRITONSERVER_InferenceResponse对象。你的回调接管该对象的所有权不再需要时必须调用TRITONSERVER_InferenceResponseDelete释放。处理响应的第一步是用TRITONSERVER_InferenceResponseError判断响应携带的是错误还是有效结果若有效则用TRITONSERVER_InferenceResponseOutputCount遍历输出张量并用TRITONSERVER_InferenceResponseOutput获取每个输出张量的信息。TRITONSERVER_InferenceResponseOutput返回的信息simple.cc 中的Check函数展示了完整用法包括输出名称cname数据类型datatype可用TRITONSERVER_DataTypeString转字符串形状shape与维度数dim_count数据指针base与字节数byte_size内存类型与内存类型 IDmemory_type/memory_type_id。根据内存类型示例分别从系统内存、页锁定内存直接拷贝或对 GPU 内存执行cudaMemcpy(DeviceToHost)拷贝到主机simple.cc 的Check函数随后对输入输出做逐元素校验sum与difference的正确性检查。这同时也是一个很好的如何校验进程内推理结果的范例。关于同步与并发需要特别说明simple.cc 使用std::promise简单等待响应只是示例手法并不是必需的同步方式。你完全可以同时发起多个在途推理请求也可以从同一线程或多个不同线程发起推理请求。异步回调模型本身就是为了支持高并发场景而设计的。从 simple.cc 到生产实现可运行的完整参考simple.cc 是本仓库中 C API 的最小可运行示例其命令行参数设计值得完整记录Usage: simple [options] -m system|pinned|gpu Enforce the memory type for input and output tensors. If not specified, inputs will be in system memory and outputs will be based on the models preferred type. -v Enable verbose logging -r [model repository absolute path]-r必填指定模型仓库绝对路径-m system|pinned|gpu可选强制输入输出张量的内存类型system对应TRITONSERVER_MEMORY_CPUpinned对应TRITONSERVER_MEMORY_CPU_PINNEDgpu对应TRITONSERVER_MEMORY_GPU未指定时输入使用系统内存输出依据模型偏好类型-v开启详细日志verbose_level 1在非 GPU 构建下-m只能设为system否则直接报错退出simple.cc。在启用 GPU 且指定-m gpu/-m pinned时simple.cc 还会把输入数据拷贝到 CUDA 设备内存或页锁定内存通过cudaMalloc/cudaHostAlloccudaMemcpy并用自定义 deletercuda_data_deleter根据cudaPointerGetAttributes判断指针类型以正确释放展示了对齐真实 GPU 部署的输入数据放置方式。如果你需要更复杂的生产级参考直接阅读 http_server.cc 与 grpc_server.cc。以 http_server.cc 的 generate 端点为例其处理逻辑与 simple.cc 完全同构TRITONSERVER_InferenceRequestNew创建请求并用shared_ptr自定义 deleter 做 RAII 清理、TRITONSERVER_InferenceRequestSetReleaseCallback注册请求释放回调、TRITONSERVER_InferenceRequestSetResponseCallback注册响应回调、最后TRITONSERVER_ServerInferAsync提交异步推理。由此可以清晰地看到官方 HTTP/REST 与 gRPC 前端、以及任何基于 C API 的自研前端底层都是同一套 Server API 调用链。小结Triton Inference Server 的 C API 提供了不依赖网络协议、可直接内嵌进 C/C 应用的完整推理能力。核心要点可归纳为进程内模型通过链接libtritonserver.soDocker 镜像内位于/opt/tritonserver/lib把 Triton 核心逻辑直接嵌入应用通信走 Server API 而非 HTTP/gRPC统一入口TRITONSERVER_ServerNewTRITONSERVER_ServerOptions创建服务器对象健康检查、模型管理、元数据等非推理功能都有对应 API错误与所有权错误对象返回即转移所有权须用TRITONSERVER_ErrorDelete释放所有对象的生命周期规则以tritonserver.h文档为准异步推理四步曲创建TRITONSERVER_ResponseAllocator→ 构建TRITONSERVER_InferenceRequest含释放回调与响应回调→TRITONSERVER_ServerInferAsync异步提交 → 在响应回调中检查并处理TRITONSERVER_InferenceResponse版本兼容运行时 API 主版本须与编译时一致、次版本须大于等于编译时版本权威参考仓库内的 simple.cc 是最小示例http_server.cc 与 grpc_server.cc 是官方生产级示例common.h 提供官方推荐错误处理宏。对于希望在自有服务中复用 Triton 调度、批处理与后端能力、同时避免网络开销和独立进程运维成本的场景C API 进程内模式是一条被 Triton 官方前端本身验证过的成熟路径。赞分享模型推理服务AI 应用后端【免费下载链接】serverThe Triton Inference Server provides an optimized cloud and edge inferencing solution.项目地址https://gitcode.com/gh_mirrors/server117/server点击查看免费下载相关推荐Triton Inference Server 进程内 Server API 完全指南C/C、Python 与 Java 嵌入式集成实战Triton Inference Server 进程内 Server API 完全指南C/C、Python 与 Java 嵌入式集成实战 导读 Trito模型推理服务AI 应用后端嵌入式系统的AI加速革命Triton Inference Server C API实战指南嵌入式系统的AI加速革命Triton Inference Server C API实战指南 你是否还在为嵌入式设备上的AI模型部署头疼受限于资源的嵌入式系统模型推理服务AI 应用后端Triton Inference Server C API 嵌入式集成实战在 Jetson 上以共享库方式运行并发推理与动态批处理Triton Inference Server C API 嵌入式集成实战在 Jetson 上以共享库方式运行并发推理与动态批处理 导读 本文基于 docs/模型推理服务AI 应用后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考