TensorRT C# API 項目更新 (1):支持動態Bath輸入模型推理

来源:https://www.cnblogs.com/guojin-blogs/p/18125829
-Advertisement-
Play Games

開發了TensorRT C# API 2.0版本,該版本在開發時充分考慮了上一版本應用時出現的問題,併進行了改進。為了更加方便開發者使用,在本次更新中增加了對動態輸入模型的支持,將在本技術文中詳細介紹本次更新內容以及應用案例。 ...


1. 項目介紹

   NVIDIA® TensorRT™ 是一款用於高性能深度學習推理的 SDK,包括深度學習推理優化器和運行時,可為推理應用程式提供低延遲和高吞吐量。基於 NVIDIA TensorRT 的應用程式在推理過程中的執行速度比純 CPU 平臺快 36 倍,使您能夠優化在所有主要框架上訓練的神經網路模型,以高精度校準低精度,並部署到超大規模數據中心、嵌入式平臺或汽車產品平臺。

  TensorRT 基於 NVIDIA CUDA® 並行編程模型構建,使您能夠在 NVIDIA GPU 上使用量化、層和張量融合、內核調整等技術來優化推理。TensorRT 提供 INT8 使用量化感知訓練和訓練後量化和浮點 16 (FP16) 優化,用於部署深度學習推理應用程式,例如視頻流、推薦、欺詐檢測和自然語言處理。低精度推理可顯著降低延遲,這是許多實時服務以及自主和嵌入式應用所必需的。TensorRT 與 PyTorch 和 TensorFlow 集成,因此只需一行代碼即可實現 6 倍的推理速度。TensorRT 提供了一個 ONNX 解析器,因此您可以輕鬆地將 ONNX 模型從常用框架導入 TensorRT。它還與 ONNX 運行時集成,提供了一種以 ONNX 格式實現高性能推理的簡單方法。

  基於這些優勢,TensorRT目前在深度模型部署應用越來越廣泛。但是TensorRT目前只提供了C++與Python介面,對於跨語言使用十分不便。目前C#語言已經成為當前編程語言排行榜上前五的語言,也被廣泛應用工業軟體開發中。為了能夠實現在C#中調用TensorRT部署深度學習模型,我們在之前的開發中開發了TensorRT C# API。雖然實現了該介面,但由於數據傳輸存在問題,當時開發的版本在應用時存在較大的問題。

  基於此,我們開發了TensorRT C# API 2.0版本,該版本在開發時充分考慮了上一版本應用時出現的問題,併進行了改進。為了更加方便開發者使用,在本次更新中增加了對動態輸入模型的支持,將在本技術文中詳細介紹本次更新內容以及應用案例。

  • TensorRT C# API 項目源碼:
https://github.com/guojin-yan/TensorRT-CSharp-API.git
  • TensorRT C# API 項目應用源碼:
https://github.com/guojin-yan/TensorRT-CSharp-API-Samples.git

2. 更新回顧

  由於該項目目前還沒有完全開發完成,為了更好的方便大家使用,因此會在最新更新後提供給大家最新的資訊。如果大家在使用時有任何疑問,可以閱讀之前發佈的技術博客:

3. 動態輸入模型支持

  在上一版本中,支持了多Bath推理,單其實現方式是導出的推理模型是多Bath的,因此模型推理的Bath是不可更改的。但是目前TensorRT已經支持了動態模型輸入,所以更新了對動態輸入模型的支持。下麵將對更新的API介面以及推理流程進行簡單的介紹:

3.1 新增API

  • public static void OnnxToEngine(string modelPath, int memorySize, string nodeName, Dims minShapes, Dims optShapes, Dims maxShapes)

    • 模型轉換介面:可以調用封裝的TensorRT中的ONNX 解釋器,對ONNX模型進行轉換,並根據本機設備信息,編譯本地模型,將模型轉換為TensorRT 支持的engine格式,該介面支持動態輸入模型。
    • string modelPath: 本地ONNX模型地址,只支持ONNX格式,且ONNX模型必須為確定的輸入輸出,暫不支持動態輸入。
    • int memorySize: 模型轉換時分配的記憶體大小。
    • string nodeName: 模型輸入節點名稱,該節點維度確定但是形狀是動態的,一般為: [-1, 3 640, 640],某一維度或其中幾個維度大小為“-1”。
    • Dims minShapes: 動態尺寸的最小允許值
    • Dims optShapes: 優化(內核選擇)中使用的值、動態尺寸的最優值
    • Dims maxShapes: 動態尺寸等的最大允許值
  • public Nvinfer(string modelPath, int maxBatahSize)

    • Nvinfer 初始化介面: 初始化Nvinfer類,主要初始化封裝的推理引擎,該推理引擎中封裝了比較重要的一些類和指針。

    • string modelPath: engine模型路徑。

    • int maxBatahSize: 推理推理支持的最大的Bath。

  • public void SetBindingDimensions(int index, Dims dims)/SetBindingDimensions(string nodeName, Dims dims)

    • 設置節點維度介面: 通過埠編號或者埠名稱,獲取綁定的埠的形狀信息。
    • int index: 綁定埠的編號。
    • string nodeName: 綁定埠的名稱。
    • Dims dims: 需要設置綁定埠的維度。

3.2 推理流程

  對於固定輸入模型的推理流程,主要包括以下四個步驟:

  • Nvinfer初始化
  • 載入推理數據
  • 模型推理
  • 獲取推理結果

  而當我們使用動態輸入模型時,其推理流程發生了變化,如下圖所示:

  當部署動態輸入模型時,推理流程為:

  • Nvinfer初始化
  • 設置本次推理模型輸入大小
  • 載入推理數據
  • 模型推理
  • 獲取推理結果

  與常規的規定輸入模型的推理流程相比,主要是增加了設置本次推理模型輸入大小這一步,其他步驟並未發生較大的變化。此外,如果下一次推理輸入數據形狀大小發生了改變,就需要重新進行設置,如果輸入形狀大小並未對發生變化,則無需進行再次設置。

4. 介面應用

  關於該項目的調用方式在上一篇文章中已經進行了詳細介紹,具體使用可以參考《最新發佈!TensorRT C# API :基於C#與TensorRT部署深度學習模型》,下麵結合Yolov8-cls模型詳細介紹一下更新的介面使用方法。

4.1 創建並配置C#項目

  首先創建一個簡單的C#項目,然後添加項目配置。

  首先是添加TensorRT C# API 項目引用,如下圖所示,添加上文中C#項目生成的dll文件即可。

  接下來添加OpenCvSharp,此處通過NuGet Package安裝即可,此處主要安裝以下兩個程式包即可:

  配置好項目後,項目的配置文件如下所示:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <RootNamespace>TensorRT_CSharp_API_demo</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="OpenCvSharp4.Extensions" Version="4.9.0.20240103" />
    <PackageReference Include="OpenCvSharp4.Windows" Version="4.9.0.20240103" />
  </ItemGroup>

  <ItemGroup>
    <Reference Include="TensorRtSharp">
      <HintPath>E:\GitSpace\TensorRT-CSharp-API\src\TensorRtSharp\bin\Release\net6.0\TensorRtSharp.dll</HintPath>
    </Reference>
  </ItemGroup>

</Project>

4.2 添加推理代碼

  此處演示一個簡單的圖像分類項目,以Yolov8-cls項目為例:

(1) 轉換engine模型

  動態輸入的模型在進行格式轉換時,需要指定模型推理形狀至此的範圍,minShapes表示模型推理支持的最小形狀,optShapes表示模型推理支持的最佳形狀,maxShapes表示模型推理支持的最大形狀,模型轉換需要消耗較多時間,最終轉換成功後會在模型同級目錄下生成相同名字的.engine文件。

Dims minShapes = new Dims(1, 3, 224, 224);
Dims optShapes = new Dims(10, 3, 224, 224);
Dims maxShapes = new Dims(20, 3, 224, 224);
Nvinfer.OnnxToEngine(onnxPath, 20, "images", minShapes, optShapes, maxShapes);

(2) 定義模型預測方法

  下麵代碼是定義的Yolov8-cls模型的預測方法,該方法支持動態Bath輸入模型推理,可以根據用戶輸入圖片數量,自動設置輸入Bath,然後進行推理。

  下麵代碼與上一篇文章中的代碼差異主要是增加了predictor.SetBindingDimensions("images", new Dims(batchNum, 3, 224, 224));這一句代碼。同時在初始化時,設置最大支持20Bath,這與上文模型轉換時設置的一致。

public class Yolov8Cls
{
    public Dims InputDims;
    public int BatchNum;
    private Nvinfer predictor;
    public Yolov8Cls(string enginePath)
    {
        predictor = new Nvinfer(enginePath, 20);
        InputDims = predictor.GetBindingDimensions("images");
    }
    public void Predict(List<Mat> images)
    {
        BatchNum = images.Count;
        for (int begImgNo = 0; begImgNo < images.Count; begImgNo += BatchNum)
        {
            DateTime start = DateTime.Now;
            int endImgNo = Math.Min(images.Count, begImgNo + BatchNum);
            int batchNum = endImgNo - begImgNo;
            List<Mat> normImgBatch = new List<Mat>();
            int imageLen = 3 * 224 * 224;
            float[] inputData = new float[BatchNum * imageLen];
            for (int ino = begImgNo; ino < endImgNo; ino++)
            {
                Mat input_mat = CvDnn.BlobFromImage(images[ino], 1.0 / 255.0, new OpenCvSharp.Size(224, 224), 0, true, false);
                float[] data = new float[imageLen];
                Marshal.Copy(input_mat.Ptr(0), data, 0, imageLen);
                Array.Copy(data, 0, inputData, ino * imageLen, imageLen);
            }
            predictor.SetBindingDimensions("images", new Dims(batchNum, 3, 224, 224));
            predictor.LoadInferenceData("images", inputData);
            DateTime end = DateTime.Now;
            Console.WriteLine("[ INFO ] Input image data processing time: " + (end - start).TotalMilliseconds + " ms.");
            predictor.infer();
            start = DateTime.Now;
            predictor.infer();
            end = DateTime.Now;
            Console.WriteLine("[ INFO ] Model inference time: " + (end - start).TotalMilliseconds + " ms.");
            start = DateTime.Now;

            float[] outputData = predictor.GetInferenceResult("output0");
            for (int i = 0; i < batchNum; ++i)
            {
                Console.WriteLine(string.Format("[ INFO ] Classification Top {0} result : ", 2));
                float[] data = new float[1000];
                Array.Copy(outputData, i * 1000, data, 0, 1000);
                List<int> sortResult = Argsort(new List<float>(data));
                for (int j = 0; j < 2; ++j)
                {
                    string msg = "";
                    msg += ("index: " + sortResult[j] + "\t");
                    msg += ("score: " + data[sortResult[j]] + "\t");
                    Console.WriteLine("[ INFO ] " + msg);
                }
            }
            end = DateTime.Now;
            Console.WriteLine("[ INFO ] Inference result processing time: " + (end - start).TotalMilliseconds + " ms.\n");
        }
    }
    public static List<int> Argsort(List<float> array)
    {
        int arrayLen = array.Count;
        List<float[]> newArray = new List<float[]> { };
        for (int i = 0; i < arrayLen; i++)
        {
            newArray.Add(new float[] { array[i], i });
        }
        newArray.Sort((a, b) => b[0].CompareTo(a[0]));
        List<int> arrayIndex = new List<int>();
        foreach (float[] item in newArray)
        {
            arrayIndex.Add((int)item[1]);
        }
        return arrayIndex;
    }
}

(3) 預測方法調用

  下麵是上述定義的預測方法,為了測試不同Bath性能,此處讀取了多張圖片,並分別預測不同張數圖片,如下所示:

Yolov8Cls yolov8Cls = new Yolov8Cls("E:\\Model\\yolov8\\yolov8s-cls_b.engine");
Mat image1 = Cv2.ImRead("E:\\ModelData\\image\\demo_4.jpg");
Mat image2 = Cv2.ImRead("E:\\ModelData\\image\\demo_5.jpg");
Mat image3 = Cv2.ImRead("E:\\ModelData\\image\\demo_6.jpg");
Mat image4 = Cv2.ImRead("E:\\ModelData\\image\\demo_7.jpg");
Mat image5 = Cv2.ImRead("E:\\ModelData\\image\\demo_8.jpg");

yolov8Cls.Predict(new List<Mat> { image1, image2 });

yolov8Cls.Predict(new List<Mat> { image1, image2, image3 });

yolov8Cls.Predict(new List<Mat> { image1, image2, image3, image4 });

yolov8Cls.Predict(new List<Mat> { image1, image2, image3, image4, image5 });

4.3 項目演示

  配置好項目並編寫好代碼後,運行該項目,項目輸出如下所示:

[ INFO ] Input image data processing time: 5.5277 ms.
[ INFO ] Model inference time: 1.3685 ms.
[ INFO ] Classification Top 2 result :
[ INFO ] index: 386     score: 0.8754883
[ INFO ] index: 385     score: 0.08013916
[ INFO ] Classification Top 2 result :
[ INFO ] index: 293     score: 0.89160156
[ INFO ] index: 276     score: 0.05480957
[ INFO ] Inference result processing time: 3.0823 ms.

[ INFO ] Input image data processing time: 2.7356 ms.
[ INFO ] Model inference time: 1.4435 ms.
[ INFO ] Classification Top 2 result :
[ INFO ] index: 386     score: 0.8754883
[ INFO ] index: 385     score: 0.08013916
[ INFO ] Classification Top 2 result :
[ INFO ] index: 293     score: 0.89160156
[ INFO ] index: 276     score: 0.05480957
[ INFO ] Classification Top 2 result :
[ INFO ] index: 14      score: 0.99853516
[ INFO ] index: 88      score: 0.0006980896
[ INFO ] Inference result processing time: 1.5137 ms.

[ INFO ] Input image data processing time: 3.7277 ms.
[ INFO ] Model inference time: 1.5285 ms.
[ INFO ] Classification Top 2 result :
[ INFO ] index: 386     score: 0.8754883
[ INFO ] index: 385     score: 0.08013916
[ INFO ] Classification Top 2 result :
[ INFO ] index: 293     score: 0.89160156
[ INFO ] index: 276     score: 0.05480957
[ INFO ] Classification Top 2 result :
[ INFO ] index: 14      score: 0.99853516
[ INFO ] index: 88      score: 0.0006980896
[ INFO ] Classification Top 2 result :
[ INFO ] index: 294     score: 0.96533203
[ INFO ] index: 269     score: 0.0124435425
[ INFO ] Inference result processing time: 2.7328 ms.

[ INFO ] Input image data processing time: 4.063 ms.
[ INFO ] Model inference time: 1.6947 ms.
[ INFO ] Classification Top 2 result :
[ INFO ] index: 386     score: 0.8754883
[ INFO ] index: 385     score: 0.08013916
[ INFO ] Classification Top 2 result :
[ INFO ] index: 293     score: 0.89160156
[ INFO ] index: 276     score: 0.05480957
[ INFO ] Classification Top 2 result :
[ INFO ] index: 14      score: 0.99853516
[ INFO ] index: 88      score: 0.0006980896
[ INFO ] Classification Top 2 result :
[ INFO ] index: 294     score: 0.96533203
[ INFO ] index: 269     score: 0.0124435425
[ INFO ] Classification Top 2 result :
[ INFO ] index: 127     score: 0.9008789
[ INFO ] index: 128     score: 0.07745361
[ INFO ] Inference result processing time: 3.5664 ms.

  通過上面輸出可以看出,不同Bath模型推理時間在1.3685~1.6947ms,大大提升了模型的推理速度。

5. 總結

  在本項目中,我們擴展了TensorRT C# API 介面,使其支持動態輸入模型。並結合分類模型部署流程向大家展示了TensorRT C# API 的使用方式,方便大家快速上手使用。

  為了方便各位開發者使用,此處開發了配套的演示項目,主要是基於Yolov8開發的目標檢測、目標分割、人體關鍵點識別、圖像分類以及旋轉目標識別,並且支持動態輸入模型,用戶可以同時推理任意張圖像。

  • Yolov8 Det 目標檢測項目源碼:
https://github.com/guojin-yan/TensorRT-CSharp-API-Samples/blob/master/model_samples/yolov8_custom_dynamic/Yolov8Det.cs
  • Yolov8 Seg 目標分割項目源碼:
https://github.com/guojin-yan/TensorRT-CSharp-API-Samples/blob/master/model_samples/yolov8_custom_dynamic/Yolov8Seg.cs
  • Yolov8 Pose 人體關鍵點識別項目源碼:
https://github.com/guojin-yan/TensorRT-CSharp-API-Samples/blob/master/model_samples/yolov8_custom_dynamic/Yolov8Pose.cs
  • Yolov8 Cls 圖像分類項目源碼:
https://github.com/guojin-yan/TensorRT-CSharp-API-Samples/blob/master/model_samples/yolov8_custom_dynamic/Yolov8Cls.cs
  • Yolov8 Obb 旋轉目標識別項目源碼:
https://github.com/guojin-yan/TensorRT-CSharp-API-Samples/blob/master/model_samples/yolov8_custom_dynamic/Yolov8Obb.cs

  同時對本項目開發的案例進行了時間測試,以下時間只是程式運行一次的時間,測試環境為:

  • CPU:i7-165G7

  • CUDA型號:12.2

  • Cudnn:8.9.3

  • TensorRT:8.6.1.6

Model Batch 數據預處理 (ms) 模型推理 (ms) 結果後處理 (ms)
Yolov8s-Det 1 16.6 4.6 13.1
4 38.0 12.4 32.4
8 70.5 23.0 80.1
Yolov8s-Obb 1 28.7 8.9 17.7
4 81.7 25.9 67.4
8 148.4 44.6 153.0
Yolov8s-Seg 1 15.4 5.4 67.4
4 37.3 15.5 220.6
8 78.7 26.9 433.6
Yolov8s-Pose 1 15.1 5.2 8.7
4 39.2 13.2 14.3
8 67.8 23.1 27.7
Yolov8s-Cls 1 9.9 1.3 1.9
4 14.7 1.5 2.3
8 22.6 2.0 2.9

  最後如果各位開發者在使用中有任何問題,歡迎大家與我聯繫。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 目錄簡介源碼函數說明arv_camera_newarv_camera_acquisitionarv_camera_get_model_namearv_buffer_get_image_widtharv_buffer_get_image_height 簡介 本文針對官方常式中的第一個常式:single ...
  • DDD 領域驅動設計理解(Domain Driven Design) 目錄DDD 領域驅動設計理解(Domain Driven Design)概念核心目標 概念 領域驅動設計事實上是1針對OOAD的一個擴展和延申。DDD基於面向對象分析與設計技術。 對技術架構進行了分層規劃。 對每個類進行了策略和劃 ...
  • Spring Boot 允許你將配置外部化,以便可以在不同的環境中使用相同的應用程式代碼。可以使用屬性文件、YAML文件、環境變數和命令行參數將配置外部化。屬性值可以通過使用 @Value 註解直接註入 bean,可以通過 Spring 的 Environment 抽象訪問,也可以通過 @Confi... ...
  • 永久激活支持全家桶所有軟體,包括 Pycharm、IDEA、WebStorm、Phpstorm、Datagrip、RubyMine、CLion、AppCode 下麵以 Intellij IDEA 作為演示。 準備工作:下載插件包 https://qweree.cn/index.php/259/(如果 ...
  • 本文介紹基於Python中ArcPy模塊,實現Excel數據讀取並生成矢量圖層,同時進行IDW插值與批量掩膜的方法。 1 任務需求 首先,我們來明確一下本文所需實現的需求。 現有一個記錄有北京市部分PM2.5濃度監測站點在2019年05月18日00時至23時(其中不含19時)等23個逐小時PM2.5 ...
  • (適用於.NET/.NET Core/.NET Framework) 【目錄】0.前言1.第一個AOP程式2.Aspect橫切麵編程3.一個橫切麵程式攔截多個主程式4.多個橫切麵程式攔截一個主程式5.AOP的泛型處理(擴充)6.AOP的非同步處理(擴充)7.優勢總結8.展望 0.前言 AOP(Aspe ...
  • 使用 Quartz.NET,你可以很容易地安排任務在應用程式啟動時運行,或者每天、每周、每月的特定時間運行,甚至可以基於更複雜的調度規則。 官網:http://www.quartz-scheduler.net/ 實現任務類 創建一個實現了 IJob 介面的類(MailJobTest),該介面包含一個 ...
  • Avalonia是一個跨平臺的.NET UI框架,它允許開發者使用C#和XAML來創建豐富的桌面應用程式。在Avalonia中,Alignment、Margin和Padding是非常重要的佈局屬性,它們與Panel元素一起使用,可以構建出各種複雜的用戶界面。 Alignment、Margin 和 P ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...