deepstream-nvinferserver

本文探讨了nvinferserver的开源版本中,插件层与底层库在处理output_host_buffers和output_device_buffers的区别,重点介绍了内存分配和复制机制,以及nvinferserver如何强制转换输出类型到hostCPU。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

nvinferserver的插件和底层库在DS6.3上开源了。这样nvinferserver和nvinfer推理就都开源了,有什么问题,可以直接调代码。

NvDsInferTensorMeta{

  /** Array of pointers to the output host buffers for the batch / frame / object. */

  void **out_buf_ptrs_host;

  /** Array of pointers to the output device buffers for the batch / frame / object. */

  void **out_buf_ptrs_dev;

  /** GPU device ID on which the device buffers have been allocated. */

}

问题1, out_buf_ptrs_host和out_buf_ptrs_dev在nvinfer和nvinferserver中有什么区别呢?

可以从插件层往底层查这个问题,在nvinfer中,赋值的地方是:

attach_tensor_output_meta{

    meta->out_buf_ptrs_host = new void *[meta->num_output_layers];

    meta->out_buf_ptrs_dev = new void *[meta->num_output_layers];

。。。。。。

      meta->out_buf_ptrs_dev[i] =

          (uint8_t *) batch_output->outputDeviceBuffers[i] +

          info.inferDims.numElements * get_element_size (info.dataType) * j;

      meta->out_buf_ptrs_host[i] =

          (uint8_t *) batch_output->hostBuffers[info.bindingIndex] +

          info.inferDims.numElements * get_element_size (info.dataType) * j;

。。。。。。

}

那就得去底层找outputDeviceBuffers和hostBuffers。

在InferPostprocessor::postProcessHost中,可以看到outputDeviceBuffers指向GPU的buffer。

        batchOutput.outputDeviceBuffers[i] =

            batch.m_DeviceBuffers[m_OutputLayerInfo[i].bindingIndex];

在InferPostprocessor::postProcessHost中,可以看到hostBuffers指向m_HostBuffers,那m_HostBuffers从哪里来?

        batchOutput.hostBuffers[i] =

            batch.m_HostBuffers[i] ? batch.m_HostBuffers[i]->ptr() : nullptr;

在InferPostprocessor::copyBuffersToHostMemory中,因为needOutputCopyB4Processing一直是true,所以必然进入如下判断,从m_DeviceBuffers中拷贝数据到m_HostBuffers。

if (!info.isInput && needOutputCopyB4Processing())

{

cudaMemcpyAsync(batch.m_HostBuffers[info.bindingIndex]->ptr(),

                    batch.m_DeviceBuffers[info.bindingIndex],

 } 

在nvinferserver中,逻辑是不一样的,在插件的attachTensorOutputMeta中,out_buf_ptrs_dev赋的空,只有out_buf_ptrs_host可用。

{

        void *bufPtr = buf->getBufPtr(batchIdx);

        meta->out_buf_ptrs_host[i] = bufPtr;

        meta->out_buf_ptrs_dev[i] = nullptr;

}

以为nvinferserver的CAPI为例,nvinferserver在做推理的时候,需要指定输出的回调函数,也就是TrtISBackend::allocateResponseBuf,在nvdsinferserver_common.proto中,可以找到输出buffer的支持的类型, triton默认输出gpubuffer类型。

/** Tensor memory type
 */
enum MemoryType {
  MEMORY_TYPE_DEFAULT = 0;
  MEMORY_TYPE_CPU = 1;
  MEMORY_TYPE_GPU = 2;
}

在memTypeFromDsProto中,会将配置转为内部类型。

memTypeFromDsProto(ic::MemoryType t)

{

    static const std::unordered_map<ic::MemoryType, InferMemType> sTypes{

        {ic::MEMORY_TYPE_DEFAULT, InferMemType::kNone},

        {ic::MEMORY_TYPE_CPU, InferMemType::kCpuCuda},

        {ic::MEMORY_TYPE_GPU, InferMemType::kGpuCuda},

    };

}

nvinerserver会强行想triton的返回值转成hostcpu类型,在InferCudaContext::acquireTensorHostBuf中创建hostbuffer, 在Postprocessor::postCudaImpl中,通过 cudaMemcpyAsync(outBufPtr, inBufPtr把gpubuffer拷贝到cpubuffer。

因为out_buf_ptrs_host指向的是hostcpu类型的buffer。

### 部署YOLO模型到NVIDIA Jetson Nano #### 准备环境和工具 为了成功在NVIDIA Jetson Nano上部署YOLO模型,需要先安装必要的软件包以及配置开发环境。这包括但不限于Python库、CUDA Toolkit、cuDNN以及其他依赖项[^1]。 #### 获取并准备YOLOv5模型 下载官方发布的预训练权重文件或是自行训练得到的特定场景下的YOLOv5权重。对于Jetson Nano而言,建议采用较小版本如`yolov5s.pt`来减少资源占用并提高推理速度。完成下载后需转换此PyTorch格式(.pt)至ONNX格式以便后续优化处理。 ```bash # 下载 yolov5 模型仓库 git clone https://github.com/ultralytics/yolov5.git cd yolov5 # 安装需求 pip install -r requirements.txt # 导出 ONNX 文件 (假设使用的是 yolov5s 版本) python export.py --weights yolov5s.pt --include onnx ``` #### 使用TensorRT加速YOLOv5 通过将上述获得的`.onnx`文件进一步转化为适用于TensorRT引擎运行的形式——即`.engine`文件,可以显著提升性能表现。具体操作可通过调用`trtexec`命令行工具实现,该工具位于CUDA安装目录下。 ```bash # 转换 .onnx 至 TensorRT engine (.engine) /path/to/trtexec --onnx=yolov5s.onnx --saveEngine=yolov5s.engine \ --explicitBatch --workspace=256 --fp16 ``` #### 整合DeepStream SDK进行视频流分析 利用NVIDIA提供的DeepStream SDK框架能够方便快捷地接入摄像头或其他媒体源作为输入,并实现实时图像处理功能。创建一个新的GStreamer管道定义文件(`pipeline.config`)用于描述数据流动路径;编写应用程序代码读取生成好的`.engine`文件加载入内存执行推断任务。 ```c++ // C++ 示例:初始化 DeepStream 并加载 TensorRT Engine 进行预测 #include <gst/gst.h> ... std::string model_path = "/path/to/yolov5s.engine"; nvinfer1::ICudaEngine* load_engine(const std::string& path); void init_deepstream_pipeline(); ... int main() { GstElement *pipeline; // 初始化 GStreamer 和 DeepStream 组件 gst_init(NULL, NULL); pipeline = gst_parse_launch("filesrc location=test.mp4 ! qtdemux ! h264parse ! nvv4l2decoder ! nvvidconv ! queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 ! nvinferserver config-file-path=pipeline.config batch-size=1 ! fakesink", NULL); // 加载 TensorRT 推理引擎 auto trt_engine = load_engine(model_path.c_str()); // 启动流水线 gst_element_set_state(pipeline, GST_STATE_PLAYING); } ``` #### 测试与验证 最后一步是对整个系统进行全面测试以确认各部分工作正常无误。可以通过播放一段本地存储的视频片段或者连接USB摄像机来进行实际效果评估。观察输出日志中的FPS指标判断是否达到了预期水平,必要时调整参数重新编译直至满意为止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山西茄子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值