news 2026/9/23 18:28:37

Triton Inference Server 共享内存扩展(Shared-Memory Extension)协议详解:系统共享内存与 CUDA 共享内存实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Triton Inference Server 共享内存扩展(Shared-Memory Extension)协议详解:系统共享内存与 CUDA 共享内存实战指南
  • 模型推理服务
  • AI 应用
  • 后端

【免费下载链接】server

The Triton Inference Server provides an optimized cloud and edge inferencing solution.

项目地址:https://gitcode.com/gh_mirrors/server117/server
点击查看免费下载

本篇技术指南以 Triton Inference Server 的官方协议文档 extension_shared_memory.md 为骨架,系统讲解其共享内存扩展(Shared-Memory Extension)的设计原理、通用参数语义,以及 HTTP/REST 与 gRPC 两套协议下 System Shared Memory 与 CUDA Shared Memory 完整的 Status / Register / Unregister API 与消息格式。读者阅读本文后,将能够在自己的客户端中创建、注册共享内存区域,并通过shared_memory_region等参数让输入/输出张量绕过网络序列化直接读写共享内存,从而在超大张量、高吞吐场景下显著降低推理链路的数据拷贝开销;同时可结合本仓库的 共享内存管理器实现 理解底层映射与校验逻辑。

为什么需要共享内存扩展:从协议层理解性能动机

在默认的推理流程中,客户端通过 HTTP/REST 或 gRPC 将张量数据(例如图像、embedding、大模型输入)序列化进请求体发送给服务端,推理完成后服务端再将输出张量序列化返回。对于 GB 级别的张量或高频小请求,序列化、网络传输与内存拷贝的开销可能占整个推理链路相当大的比重。

共享内存扩展提供了一条旁路:客户端与 Triton 服务端共享同一块内存区域,推理请求中不再携带张量二进制数据,只携带区域名称、偏移量与字节大小。服务端直接从映射好的内存地址读取输入、写入输出,从而获得显著的性能收益。由于该扩展同时支持系统内存(CPU 侧)与 CUDA 内存(GPU 侧),Triton 会在其 Server Metadata 的extensions字段中同时报告"system_shared_memory""cuda_shared_memory",客户端可以通过该字段探测服务端是否支持本扩展。

通用参数:三个贯穿所有接口的核心字段

无论使用何种协议,共享内存扩展都依赖一组通用参数来声明"某个输入/输出张量经由共享内存传输"。这三个参数同样出现在 HTTP/REST 的 JSON 请求字段与 gRPC 的ModelInferRequest消息参数中:

参数名类型必填语义
shared_memory_regionstring此前已注册的共享内存区域名称。注意:系统共享内存区域与 CUDA 共享内存区域共享同一个命名空间,区域名不能重复
shared_memory_offsetint64张量数据在区域内的起始字节偏移,默认值为 0
shared_memory_byte_sizeint64张量数据的字节大小

参数校验规则如下:

  • shared_memory_offset可选,缺省即 0;shared_memory_regionshared_memory_byte_size两个参数必须同时给出
  • 如果只提供了两个必填参数中的任意一个,Triton 将返回错误。
  • 在 HTTP/REST 中,当输入张量设置了上述共享内存参数时,$request_inputdata字段不得设置;一旦同时设置data字段,Triton 会返回错误。同理,当请求的输出设置了共享内存参数时,返回的$response_output不得包含data字段。
  • 在 gRPC 中,对应规则为:输入张量设置共享内存参数后,ModelInferRequest::InferInputTensorcontents字段不得设置;输出张量设置共享内存参数后,ModelInferResponse::InferOutputTensorcontents字段将不会被填充。

[!NOTE]前置条件:--allow-client-shm。客户端注册/注销共享内存区域以及使用共享内存区域,都要求服务端以--allow-client-shm=true启动,默认值为false。从命令行解析实现 command_line_parser.cc 可以看到该选项为布尔类型,默认关闭。当该选项关闭时,服务端会返回错误信息:"Client shared memory is disabled. Start the server with '--allow-client-shm=true' to enable."(定义见 common.h)。需要强调的是:该选项不影响后端(backend)内部使用的共享内存——例如 Python 后端内部创建的共享内存区域使用保留前缀triton_python_backend_shm_region_(见 common.h),不依赖此开关。

[!NOTE]Jetson 平台限制:在 Jetson 上仅支持系统共享内存,不支持 CUDA 共享内存

共享内存区域必须先由客户端创建,再通过 Register API 注册到 Triton,之后才能被shared_memory_region参数引用。系统共享内存与 CUDA 共享内存的注册 API 完全不同,下面分别展开。

HTTP/REST 接口

下文所有 JSON Schema 中,$number$string$boolean$object$array分别指代 JSON 的基础类型;#optional标记可选字段。

HTTP 路由的实际匹配逻辑见 http_server.cc 中定义的正则表达式:/v2/systemsharedmemory(?:/region/([^/]+))?/(status|register|unregister)/v2/cudasharedmemory(?:/region/([^/]+))?/(status|register|unregister)。其中regionaction两个分组随后被分发到 HandleSystemSharedMemory 与 HandleCudaSharedMemory 处理。也就是说,statusunregister请求可以省略/region/${REGION_NAME}(作用于全部区域),而register请求的 URL 中必须携带区域名。

系统共享内存(System Shared Memory)

系统共享内存扩展要求提供 Status、Register、Unregister 三类 API,URL 形态如下:

GET v2/systemsharedmemory[/region/${REGION_NAME}]/status POST v2/systemsharedmemory/region/${REGION_NAME}/register POST v2/systemsharedmemory[/region/${REGION_NAME}]/unregister
Status

以 HTTP GET 请求访问 status 端点。若 URL 中提供了REGION_NAME,响应只包含该区域的状态;未提供时返回所有已注册区域的状态。成功时 HTTP 状态码为 200,响应体为$system_shared_memory_status_response

$system_shared_memory_status_response = [ { "name" : $string, "key" : $string, "offset" : $number, "byte_size" : $number }, … ]

字段语义:

  • name:共享内存区域的名称。
  • key:底层内存对象(POSIX 共享内存对象)的键。
  • offset:底层内存对象内共享内存区域起始位置的字节偏移。
  • byte_size:共享内存区域的字节大小。

失败时返回 HTTP 错误状态码(通常为 400),响应体为$system_shared_memory_status_error_response

$system_shared_memory_status_error_response = { "error": $string }
  • error:描述性错误信息。

一个实际的状态查询示例:

# 查询全部区域 curl -i -X GET http://localhost:8000/v2/systemsharedmemory/status # 查询名为 input0_data 的区域 curl -i -X GET http://localhost:8000/v2/systemsharedmemory/region/input0_data/status
Register

以 HTTP POST 请求访问 register 端点,请求体必须携带$system_shared_memory_register_request

$system_shared_memory_register_request = { "key" : $string, "offset" : $number, "byte_size" : $number }
  • key:底层内存对象(POSIX 共享内存对象)的键。
  • offset:底层内存对象内共享内存区域起始位置的字节偏移。
  • byte_size:共享内存区域的字节大小。

成功时返回 200。失败时(通常为 400)返回$system_shared_memory_register_error_response

$system_shared_memory_register_error_response = { "error": $string }
  • error:描述性错误信息。

从源码 shared_memory_manager.cc 可以看到RegisterSystemSharedMemory的完整校验链路:首先校验共享内存 key 是否使用了 Triton 内部保留前缀;然后检查同名区域是否已注册(重复注册返回TRITONSERVER_ERROR_ALREADY_EXISTS);随后通过shm_open打开 POSIX 共享内存对象、fstat获取对象大小,并校验offset + byte_size不越界(越界返回TRITONSERVER_ERROR_INVALID_ARG);最后mmap映射到服务端进程地址空间并关闭文件描述符。也就是说,注册时服务端会立即打开并映射这块内存,因此客户端在注册前必须确保共享内存对象真实存在且大小足够。

register 请求示例:

curl -i -X POST \ -H "Content-Type: application/json" \ -d '{"key": "/input0_data", "offset": 0, "byte_size": 4096}' \ http://localhost:8000/v2/systemsharedmemory/region/input0_data/register
Unregister

以 HTTP POST 请求访问 unregister 端点,请求体必须为空。URL 中提供了REGION_NAME时只注销该区域;未提供时注销所有系统共享内存区域。成功时返回 200。失败时(通常为 400)返回$system_shared_memory_unregister_error_response

$system_shared_memory_unregister_error_response = { "error": $string }
  • error:描述性错误信息。
# 注销单个区域 curl -i -X POST http://localhost:8000/v2/systemsharedmemory/region/input0_data/unregister # 注销全部区域 curl -i -X POST http://localhost:8000/v2/systemsharedmemory/unregister

CUDA 共享内存(CUDA Shared Memory)

CUDA 共享内存扩展同样要求 Status、Register、Unregister 三类 API,URL 形态如下:

GET v2/cudasharedmemory[/region/${REGION_NAME}]/status POST v2/cudasharedmemory/region/${REGION_NAME}/register POST v2/cudasharedmemory[/region/${REGION_NAME}]/unregister
Status

以 HTTP GET 请求访问 status 端点,语义与系统共享内存一致(可指定区域或返回全部)。成功时 HTTP 状态码为 200,响应体为$cuda_shared_memory_status_response

$cuda_shared_memory_status_response = [ { "name" : $string, "device_id" : $number, "byte_size" : $number }, … ]

字段语义:

  • name:共享内存区域的名称。
  • device_id:创建 cudaIPC handle 所在的 GPU 设备 ID。
  • byte_size:共享内存区域的字节大小。

失败时(通常为 400)返回$cuda_shared_memory_status_error_response

$cuda_shared_memory_status_error_response = { "error": $string }
  • error:描述性错误信息。
Register

以 HTTP POST 请求访问 register 端点,请求体必须携带$cuda_shared_memory_register_request

$cuda_shared_memory_register_request = { "raw_handle" : { "b64" : $string }, "device_id" : $number, "byte_size" : $number }
  • raw_handle:序列化后的 cudaIPC handle,以 base64 编码。
  • device_id:创建 cudaIPC handle 所在的 GPU 设备 ID。
  • byte_size:共享内存区域的字节大小。

成功时返回 200。失败时(通常为 400)返回$cuda_shared_memory_register_error_response

$cuda_shared_memory_register_error_response = { "error": $string }
  • error:描述性错误信息。

从源码看,CUDA 区域的注册路径与系统共享内存不同:服务端通过cudaIpcOpenMemHandle打开客户端传来的 IPC handle 并取得 GPU 内存指针(见 shared_memory_manager.cc),随后通过 CUDA driver 的cuMemGetAddressRange获取该指针所属分配的内存范围,校验byte_size不越界(见 shared_memory_manager.cc)。注意 CUDA 区域没有offset概念,整个区域即为一个连续 GPU 内存块。

Unregister

以 HTTP POST 请求访问 unregister 端点,请求体必须为空。提供REGION_NAME时注销单个区域,否则注销所有CUDA 共享内存区域。成功返回 200。失败时(通常为 400)返回$cuda_shared_memory_unregister_error_response

$cuda_shared_memory_unregister_error_response = { "error": $string }
  • error:描述性错误信息。

gRPC 接口

在 gRPC 中,共享内存参数被设置在ModelInferRequest::InferInputTensorparameters字段(声明输入经由共享内存传输)或ModelInferRequest::InferRequestedOutputTensorparameters字段(请求输出写入共享内存)。规则与 HTTP/REST 对应:输入张量设置共享内存参数后不得再设置contents字段;输出张量设置共享内存参数后,ModelInferResponse::InferOutputTensorcontents字段将不会被填充。

共享内存区域同样必须先由客户端创建并注册。所有 gRPC 接口的错误统一通过google.rpc.Status返回:OK表示成功,其他状态码表示失败。在服务端实现中,这六个 RPC 由 grpc_server.cc 中CommonHandlerRegisterSystemSharedMemory*/RegisterCudaSharedMemory*系列方法注册到 gRPC 服务,执行时通过SharedMemoryManager完成实际操作。

系统共享内存(System Shared Memory)

系统共享内存扩展要求的 RPC 接口定义如下:

service GRPCInferenceService { … // Get the status of all registered system-shared-memory regions. rpc SystemSharedMemoryStatus(SystemSharedMemoryStatusRequest) returns (SystemSharedMemoryStatusResponse) {} // Register system-shared-memory region. rpc SystemSharedMemoryRegister(SystemSharedMemoryRegisterRequest) returns (SystemSharedMemoryRegisterResponse) {} // Unregister system-shared-memory region. rpc SystemSharedMemoryUnregister(SystemSharedMemoryUnregisterRequest) returns (SystemSharedMemoryUnregisterResponse) {} }
Status

SystemSharedMemoryStatus返回已注册系统共享内存区域的信息。请求与响应消息定义:

message SystemSharedMemoryStatusRequest { // The name of the region to get status for. If empty the // status is returned for all registered regions. string name = 1; } message SystemSharedMemoryStatusResponse { // Status for a shared memory region. message RegionStatus { // The name for the shared memory region. string name = 1; // The key of the underlying memory object that contains the // shared memory region. string key = 2; // Offset, in bytes, within the underlying memory object to // the start of the shared memory region. uint64 offset = 3; // Size of the shared memory region, in bytes. uint64 byte_size = 4; } // Status for each of the registered regions, indexed by region name. map<string, RegionStatus> regions = 1; }
Register

SystemSharedMemoryRegister用于向 Triton 注册新的系统共享内存区域,注册成功后即可在shared_memory_region参数中引用。请求与响应消息定义:

message SystemSharedMemoryRegisterRequest { // The name of the region to register. string name = 1; // The key of the underlying memory object that contains the // shared memory region. string key = 2; // Offset, in bytes, within the underlying memory object to // the start of the shared memory region. uint64 offset = 3; // Size of the shared memory region, in bytes. uint64 byte_size = 4; } message SystemSharedMemoryRegisterResponse { }
Unregister

SystemSharedMemoryUnregister用于注销已注册的系统共享内存区域,注销后该区域不能再用于传输张量数据。请求与响应消息定义:

message SystemSharedMemoryUnregisterRequest { // The name of the region to unregister. If empty all system shared-memory // regions are unregistered. string name = 1; } message SystemSharedMemoryUnregisterResponse { }

CUDA 共享内存(CUDA Shared Memory)

CUDA 共享内存扩展要求的 RPC 接口定义如下:

service GRPCInferenceService { … // Get the status of all registered CUDA-shared-memory regions. rpc CudaSharedMemoryStatus(CudaSharedMemoryStatusRequest) returns (CudaSharedMemoryStatusResponse) {} // Register CUDA-shared-memory region. rpc CudaSharedMemoryRegister(CudaSharedMemoryRegisterRequest) returns (CudaSharedMemoryRegisterResponse) {} // Unregister CUDA-shared-memory region. rpc CudaSharedMemorUnregister(CudaSharedMemoryUnregisterRequest) returns (CudaSharedMemoryUnregisterResponse) {} }
Status

CudaSharedMemoryStatus返回已注册 CUDA 共享内存区域的信息。请求与响应消息定义:

message CudaSharedMemoryStatusRequest { // The name of the region to get status for. If empty the // status is returned for all registered regions. string name = 1; } message CudaSharedMemoryStatusResponse { // Status for a shared memory region. message RegionStatus { // The name for the shared memory region. string name = 1; // The GPU device ID where the cudaIPC handle was created. uint64 device_id = 2; // Size of the shared memory region, in bytes. uint64 byte_size = 3; } // Status for each of the registered regions, indexed by region name. map<string, RegionStatus> regions = 1; }
Register

CudaSharedMemoryRegister用于注册新的 CUDA 共享内存区域,注册后即可在shared_memory_region参数中引用。请求与响应消息定义:

message CudaSharedMemoryRegisterRequest { // The name of the region to register. string name = 1; // The raw serialized cudaIPC handle. bytes raw_handle = 2; // The GPU device ID on which the cudaIPC handle was created. int64 device_id = 3; // Size of the shared memory region, in bytes. uint64 byte_size = 4; } message CudaSharedMemoryRegisterResponse { }
Unregister

CudaSharedMemoryUnregister用于注销已注册的 CUDA 共享内存区域。请求与响应消息定义:

message CudaSharedMemoryUnregisterRequest { // The name of the region to unregister. If empty all CUDA shared-memory // regions are unregistered. string name = 1; } message CudaSharedMemoryUnregisterResponse { }

端到端使用流程:客户端视角的完整示例

综合协议与测试用例 shared_memory_test.py 中的实际用法(其中大量使用tritonclient.utils.shared_memory辅助模块),一次完整的共享内存推理通常遵循以下步骤:

  1. --allow-client-shm=true启动 Triton 服务端

    tritonserver --model-repository=/path/to/model_repository --allow-client-shm=true
  2. 客户端创建系统共享内存区域并写入输入数据(Python + tritonclient):

    import numpy as np import tritonclient.http as httpclient from tritonclient.utils import shared_memory as shm client = httpclient.InferenceServerClient(url="localhost:8000") # 创建 4096 字节的 POSIX 共享内存对象 /input0_data shm_ip0_handle = shm.create_shared_memory_region( "input0_data", "/input0_data", 4096) # 将 numpy 数据拷入共享内存 input0_data = np.random.rand(1024).astype(np.float32) shm.set_shared_memory_region(shm_ip0_handle, [input0_data]) # 将区域注册到 Triton client.register_system_shared_memory( "input0_data", "/input0_data", 0, 4096)
  3. 构造推理请求,用shared_memory_region代替data

    inputs = [httpclient.InferInput("INPUT0", [1024], "FP32")] inputs[0].set_shared_memory("input0_data", 0, 4096) outputs = [httpclient.InferRequestedOutput("OUTPUT0")] outputs[0].set_shared_memory("output0_data", 0, 4096) results = client.infer("model_name", inputs, outputs=outputs)
  4. 推理结束后注销并销毁区域

    client.unregister_system_shared_memory("input0_data") client.unregister_system_shared_memory("output0_data") shm.destroy_shared_memory_region(shm_ip0_handle)

从测试 shared_memory_test.py 可以看到,上述流程(创建 → 写入 → 注册 → 推理 → 注销 → 销毁)正是 QA 套件验证的核心路径;测试同时覆盖了重复注册报错、使用非法 key、不存在的区域注销失败等异常分支(见 shared_memory_test.py),这些行为与 shared_memory_manager.cc 中ALREADY_EXISTSNOT_FOUNDINVALID_ARG等错误返回一一对应。

底层原理与边界校验

从实现层面看,共享内存扩展的枢纽是 SharedMemoryManager 类:

  • 内部以std::map<std::string, std::shared_ptr<SharedMemoryInfo>>维护区域名到区域信息的映射,并用互斥锁保护并发访问;SharedMemoryInfo记录区域名、底层 key、偏移、字节大小、映射地址、内存类型(CPU/GPU)与设备 ID。
  • 系统共享内存区域:注册时shm_open+mmap映射;推理时通过GetMemoryInfo根据区域名、offset、byte_size 返回映射地址与内存类型,服务端可直接读写该地址。
  • CUDA 共享内存区域:注册时通过cudaIpcOpenMemHandle打开句柄;CUDASharedMemoryInfo额外保存cudaIpcMemHandle_t
  • 关键边界校验(见 shared_memory_manager.cc):GetMemoryInfo会拒绝offset >= 区域大小的请求、检测offset + byte_size的整数溢出,并校验offset + byte_size不超出区域大小,防止越界读写。
  • 区域注销采用引用计数保护:GetMemoryInfo返回的shm_info引用会阻止正在被推理使用的区域被注销,引用释放后才允许真正卸载(见 shared_memory_manager.h)。
  • 服务端退出时,析构函数会自动注销全部 CPU 与 GPU 区域(见 shared_memory_manager.cc)。
  • 需要注意,当服务端以进程内 Python 前端(tritonfrontend)方式启动时没有SharedMemoryManager,此时共享内存相关请求会返回"Shared memory is not supported in this server configuration"错误(见 common.h 与 grpc_server.cc),应改用tritonserver可执行文件方式启动以使用共享内存。

总结与注意事项

  • 性能收益的前提:共享内存适合张量数据大、请求频率高的场景;它消除了序列化/反序列化与网络拷贝,但要求客户端与服务端位于同一主机(或共享同一套内存/GPU 资源),并承担显式的内存生命周期管理。
  • 开关默认关闭--allow-client-shm默认值为false,使用前必须显式开启;该开关只影响客户端注册与使用,不影响后端内部共享内存。
  • 命名空间唯一:系统与 CUDA 区域共享同一命名空间,重名注册会被拒绝。
  • 参数完整性shared_memory_regionshared_memory_byte_size必须成对出现,shared_memory_offset可选;输入/输出的data/contents与共享内存参数互斥。
  • 平台差异:Jetson 仅支持系统共享内存,CUDA 共享内存不可用。
  • 错误语义:HTTP 侧错误通常以 400 状态码返回 JSONerror字段;gRPC 侧通过google.rpc.Status表达,非OK码即失败。

如需进一步深入,可继续阅读本仓库中的协议原文 extension_shared_memory.md、服务端实现 shared_memory_manager.h 与 shared_memory_manager.cc、HTTP 处理器 http_server.cc、gRPC 处理器 grpc_server.cc,以及端到端验证用例 shared_memory_test.py。

  • 模型推理服务
  • AI 应用
  • 后端

【免费下载链接】server

The Triton Inference Server provides an optimized cloud and edge inferencing solution.

项目地址:https://gitcode.com/gh_mirrors/server117/server
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 18:18:33

爱立信4G/5G Moshell排障指令实战地图

简介&#xff1a;本资源是一份面向通信网络运维工程师、爱立信设备初/中级维护人员的4G/5G指令速查手册&#xff0c;聚焦实际网管操作场景&#xff0c;系统梳理Moshell环境下高频使用的九类核心指令及其典型应用。内容涵盖MOM对象管理、MO-read/mo-write参数读写、PM性能采集、…

作者头像 李华
网站建设 2026/9/23 18:18:26

SpringBoot+Vue健康饮食系统:营养计算闭环与实时校验实现

简介&#xff1a;本资源是一套面向计算机专业本科生的Java毕业设计实战项目&#xff0c;聚焦智能健康饮食管理场景&#xff0c;适用于毕设开发、课程设计及Java全栈能力进阶学习。项目采用SpringBootVue前后端分离架构&#xff0c;基于JDK1.8、MySQL 5.7与MyBatis构建&#xff…

作者头像 李华
网站建设 2026/9/23 18:16:42

行人实例分割数据集实战:YOLO格式解析与YOLOv8训练避坑指南

简介&#xff1a;行人实例分割数据集面向计算机视觉开发者、算法工程师及高校研究人员&#xff0c;聚焦行人目标的精细化识别与轮廓分割任务。资源共2000个文件&#xff0c;以1226个txt标注文件、772张jpg图像为主&#xff0c;另含1个yaml配置文件与1份docx说明文档&#xff0c…

作者头像 李华
网站建设 2026/9/23 18:09:36

Python机器学习天气预测源码:LSTM与MLP模型对比及GUI实现

简介&#xff1a;这是一套面向计算机相关专业学生与项目实战学习者的机器学习天气预测完整项目包&#xff0c;适用于期末大作业、毕业设计及课程实践场景&#xff0c;难度适中&#xff0c;可帮助读者快速理解从数据获取到模型训练与可视化展示的全流程。压缩包共38个文件&#…

作者头像 李华
网站建设 2026/9/23 18:09:02

YOLO工业指针仪表检测数据集:1000张真实场景图与三格式标签实战

简介&#xff1a;本资源面向工业视觉检测方向的算法工程师与深度学习学习者&#xff0c;提供一套可直接用于YOLO系列目标检测训练的工业指针仪表数据集&#xff0c;帮助解决真实产线场景下仪表读数识别样本不足、标注格式不统一的问题。压缩包共2000个文件&#xff0c;约427.86…

作者头像 李华
网站建设 2026/9/23 18:08:55

SSM+JSP+Layui电影系统:解决Tab状态丢失、连接池泄漏与路由冲突

简介&#xff1a;这是一套基于SSM框架开发的电影在线观看系统完整源码&#xff0c;面向Java Web初学者与课程设计实践者&#xff0c;帮助掌握MVC分层架构、前后端交互及数据库操作等核心技能。资源包含322个文件&#xff0c;涵盖35个Java业务类、31个XML配置与映射文件、29个JS…

作者头像 李华