Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions csharp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/.vs/
/local_feed/
/Microsoft.ML.OnnxRuntime.EP.TensorRT/runtimes/**/native/*.dll
*.nupkg
*.snupkg
**/packages/*
!**/packages/build/
**/bin/*
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<Runtime Condition=" $([MSBuild]::IsOsPlatform('Windows')) AND '$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)' == 'X64' ">win-x64</Runtime>
<Runtime Condition=" $([MSBuild]::IsOsPlatform('Windows')) AND '$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)' == 'Arm64' ">win-arm64</Runtime>

<!-- Package info -->
<PackageId>Microsoft.ML.OnnxRuntime.EP.TensorRT</PackageId>
<Version>1.0.0</Version>
<Authors>ORT</Authors>
<Company>Microsoft</Company>
<Description>A package for a TensorRT plugin EP.</Description>
<PackageReadmeFile>readme.md</PackageReadmeFile>

<!-- License/Repository -->
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryUrl>https://github.com/microsoft/onnxruntime-inference-examples</RepositoryUrl>
<RepositoryType>git</RepositoryType>

<!-- Include symbols/source for better debugging experience -->
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>

<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
</PropertyGroup>

<ItemGroup>
<!-- Ensure README is included in the package -->
<None Include="readme.md" Pack="true" PackagePath="" />
</ItemGroup>

<!-- Copy EP DLL to output directory under runtimes/*/native/ -->
<ItemGroup Condition="'$(Runtime)' == 'win-x64'">
<None Include="runtimes\win-x64\native\tensorrt_plugin_ep.dll"
Pack="true"
PackagePath="runtimes/win-x64/native/tensorrt_plugin_ep.dll"
CopyToOutputDirectory="PreserveNewest"/>
</ItemGroup>

<ItemGroup Condition="'$(Runtime)' == 'win-arm64'">
<None Include="runtimes\win-arm64\native\tensorrt_plugin_ep.dll"
Pack="true"
PackagePath="runtimes/win-arm64/native/tensorrt_plugin_ep.dll"
CopyToOutputDirectory="PreserveNewest"/>
</ItemGroup>

</Project>
83 changes: 83 additions & 0 deletions csharp/Microsoft.ML.OnnxRuntime.EP.TensorRT/TensorRTEp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Microsoft.ML.OnnxRuntime.EP.TensorRT;

public static class TensorRTEp
{
/// <summary>
/// Returns the path to the plugin EP library DLL contained by this package.
/// Can be passed to OrtEnv::RegisterExecutionProviderLibrary().
///
/// Note: It is recommended that plugin EP packages provide this information to applications.
/// </summary>
/// <returns>EP library path</returns>
/// <exception cref="FileNotFoundException">If the EP DLL file path does not exist</exception>
public static string GetLibraryPath()
{
string rootDir = GetNativeDirectory();
string osArch = $"{GetOSTag()}-{GetArchTag()}";
string epDllPath = Path.GetFullPath(Path.Combine(rootDir, "runtimes", osArch,
"native", "tensorrt_plugin_ep.dll"));

if (!File.Exists(epDllPath))
{
// This indicates a packaging error.
throw new FileNotFoundException($"Did not find EP DLL file: {epDllPath}");
}

return epDllPath;
}

/// <summary>
/// Returns the names of the EPs created by the plugin EP library.
/// Can be used to select a OrtEpDevice from those returned by OrtEnv::GetEpDevices().
///
/// Note: It is recommended that plugin EP packages provide this information to applications.
/// </summary>
/// <returns>Array of EP names</returns>
public static string[] GetEpNames()
{
return ["TensorRTPluginExecutionProvider"];
}

/// <summary>
/// Returns the name of the one EP supported by this plugin EP library.
///
/// Note: This is a convenience function exposed by plugin EP packages that only have one EP name.
/// </summary>
/// <returns></returns>
public static string GetEpName()
{
return GetEpNames()[0];
}

private static string GetNativeDirectory()
{
var assemblyDir = Path.GetDirectoryName(typeof(TensorRTEp).Assembly.Location);

// Try returning where this assembly lives (works for framework-dependent)
if (!string.IsNullOrEmpty(assemblyDir) && Directory.Exists(assemblyDir))
return assemblyDir;

// Fallback to AppContext.BaseDirectory (works for single-file/self-contained)
return AppContext.BaseDirectory;
}

private static string GetOSTag()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return "win";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return "linux";
return "unknown";
}

private static string GetArchTag()
{
return RuntimeInformation.OSArchitecture switch
{
Architecture.X64 => "x64",
Architecture.Arm64 => "arm64",
_ => "unknown"
};
}
}
66 changes: 66 additions & 0 deletions csharp/SampleApp/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.IO;

using Microsoft.ML.OnnxRuntime.EP.TensorRT;
using Microsoft.ML.OnnxRuntime;

class Program
{
static void Main()
{
string epLibPath = TensorRTEp.GetLibraryPath();
string epName = TensorRTEp.GetEpName();
string epRegistrationName = epName;

var env = OrtEnv.Instance();
env.RegisterExecutionProviderLibrary(epRegistrationName, epLibPath);
Console.WriteLine($"Registered EP library: {epLibPath}");

try
{
// Find the OrtEpDevice for the EP
OrtEpDevice? epDevice = null;
foreach (var d in env.GetEpDevices())
{
if (string.Equals(epName, d.EpName, StringComparison.OrdinalIgnoreCase))
{
epDevice = d;
}
}

if (epDevice == null)
{
Console.Error.WriteLine($"ERROR: Unable to find OrtEpDevice with name {epName}");
return;
}
Console.WriteLine($"Found OrtEpDevice for EP: {epName}");

// Create session with EP
using var sessionOptions = new SessionOptions();
sessionOptions.AppendExecutionProvider(env, [epDevice], new Dictionary<string, string> { });
sessionOptions.AddSessionConfigEntry("session.disable_cpu_ep_fallback", "1"); // Don't run on CPU EP

string inputModelPath = Path.Combine(AppContext.BaseDirectory, "mul.onnx");
Console.WriteLine($"Loading model: {inputModelPath}");

using var session = new InferenceSession(inputModelPath, sessionOptions);

// Run model
float[] inputData = [1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f];
using var inputOrtValue = OrtValue.CreateTensorValueFromMemory<float>(inputData, [2, 3]);
var inputValues = new List<OrtValue> { inputOrtValue, inputOrtValue }.AsReadOnly();
var inputNames = new List<string> { "x", "y" }.AsReadOnly();
using var runOptions = new RunOptions();

using var outputs = session.Run(runOptions, inputNames, inputValues, session.OutputNames);

Console.WriteLine($"Input: {string.Join(", ", inputData)}");
Console.WriteLine($"Output: {string.Join(", ", outputs[0].GetTensorDataAsSpan<float>().ToArray())}");
}
finally
{
env.UnregisterExecutionProviderLibrary(epRegistrationName);
}
}
}
26 changes: 26 additions & 0 deletions csharp/SampleApp/SampleApp.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.ML.OnnxRuntime.EP.TensorRT" Version="1.0.0" />
<PackageReference Include="Microsoft.ML.OnnxRuntime" Version="1.24.1" />
</ItemGroup>

<ItemGroup>
<Content Include="mul.onnx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<!-- Consume nuget package via project reference during development to get live code changes -->
<!-- <ItemGroup>
<ProjectReference Include="..\Microsoft.ML.OnnxRuntime.EP.TensorRT\Microsoft.ML.OnnxRuntime.EP.TensorRT.csproj" />
</ItemGroup> -->

</Project>
Binary file added csharp/SampleApp/mul.onnx
Binary file not shown.
6 changes: 6 additions & 0 deletions csharp/nuget.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="local_feed" value="./local_feed" />
</packageSources>
</configuration>
34 changes: 34 additions & 0 deletions csharp/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# TensorRT Plugin Execution Provider with C#

## Contents
- `Microsoft.ML.OnnxRuntime.EP.TensorRT/`: Contains files for the TensorRT plugin EP C# NuGet package. `TensorRTEp.cs` provides helper functions to get the EP library path and the EP name.
- `SampleApp/`: Contains a sample C# application showing example usage of the TensorRT plugin EP C# NuGet package.
- `setup.bat`: Batch script to generate the NuGet package.

## Build Instructions
This example currently only supports Windows x64 and Windows ARM64.

### Build the native plugin EP library

Follow instructions [here](../README.md#build-instructions) to build the native library.

### Build the C\# NuGet Package

Set the environment variable `TENSORRT_PLUGIN_EP_LIBRARY_PATH` to the path to the native plugin EP shared library. E.g., `tensorrt_plugin_ep.dll`.

Run `setup.bat` from this directory. Pass the build configuration (e.g., Release or Debug) as an argument.

```
.\setup.bat Release
```

The generated NuGet package will be copied to the `./local_feed` directory.

## Build and run the sample application

Build and run the sample application.

```
dotnet build .\SampleApp\SampleApp.csproj -c Release
dotnet run --project .\SampleApp\SampleApp.csproj -c Release
```
63 changes: 63 additions & 0 deletions csharp/setup.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
@echo off

REM Builds NuGet package that wraps TensorRT plugin EP

IF "%~1"=="" (
echo ERROR: No build configuration specified.
echo Usage: .\setup.bat [Debug^|Release]
exit /b 1
)

SET "BUILD_CONFIG=%~1"

if "%TENSORRT_PLUGIN_EP_LIBRARY_PATH%"=="" (
echo ERROR: TENSORRT_PLUGIN_EP_LIBRARY_PATH environment variable is not set.
exit /b 1
)

if not exist "%TENSORRT_PLUGIN_EP_LIBRARY_PATH%" (
echo ERROR: EP library "%TENSORRT_PLUGIN_EP_LIBRARY_PATH%" not found.
exit /b 1
)

set "ARCH=%PROCESSOR_ARCHITECTURE%"
if defined PROCESSOR_ARCHITEW6432 set "ARCH=%PROCESSOR_ARCHITEW6432%"

if /i "%ARCH%"=="AMD64" (
set "DEST_EP_DLL_FOLDER=.\Microsoft.ML.OnnxRuntime.EP.TensorRT\runtimes\win-x64\native\"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we trying to create a nuget package that will be published, or just showing an example of how to create a nuget package?

if it's the former, would we want to support having both x64 and arm64 builds in one package?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are providing an example of how to create a nuget package at this moment.

We or others can update this setup.bat once there is a request for publishing a TensorRT plugin ep nuget package.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, if all we want to do is provide an example, why not refer to this one instead?
https://github.com/microsoft/onnxruntime-inference-examples/tree/main/plugin_execution_providers/basic/csharp

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eventually, the TensorRT plugin ep nuget package will be published either by us or Nvidia.
Let me add the support for x64 and arm64 builds.

) else if /i "%ARCH%"=="ARM64" (
set "DEST_EP_DLL_FOLDER=.\Microsoft.ML.OnnxRuntime.EP.TensorRT\runtimes\win-arm64\native\"
) else (
echo ERROR: Unknown architecture "%ARCH%"
exit /b 1
)

if not exist "%DEST_EP_DLL_FOLDER%" (
mkdir "%DEST_EP_DLL_FOLDER%" || (
echo ERROR: Failed to create "%DEST_EP_DLL_FOLDER%".
exit /b 1
)
)

echo Copying EP DLL to "%DEST_EP_DLL_FOLDER%"
copy /Y "%TENSORRT_PLUGIN_EP_LIBRARY_PATH%" "%DEST_EP_DLL_FOLDER%" >nul

if errorlevel 1 (
echo ERROR: Failed to copy EP library to "%DEST_EP_DLL_FOLDER%".
exit /b 1
)

echo Building NuGet package ("%BUILD_CONFIG%") ...
dotnet build .\Microsoft.ML.OnnxRuntime.EP.TensorRT\Microsoft.ML.OnnxRuntime.EP.TensorRT.csproj -c "%BUILD_CONFIG%"
dotnet pack .\Microsoft.ML.OnnxRuntime.EP.TensorRT\Microsoft.ML.OnnxRuntime.EP.TensorRT.csproj -c "%BUILD_CONFIG%"

set "LOCAL_FEED_FOLDER=local_feed"
if not exist "%LOCAL_FEED_FOLDER%" (
mkdir "%LOCAL_FEED_FOLDER%" || (
echo ERROR: Failed to create "%LOCAL_FEED_FOLDER%"
exit /b 1
)
)

copy /Y .\Microsoft.ML.OnnxRuntime.EP.TensorRT\bin\"%BUILD_CONFIG%"\Microsoft.ML.OnnxRuntime.EP.TensorRT.*.nupkg .\local_feed\
copy /Y .\Microsoft.ML.OnnxRuntime.EP.TensorRT\bin\"%BUILD_CONFIG%"\Microsoft.ML.OnnxRuntime.EP.TensorRT.*.snupkg .\local_feed\