From 02feea3829da7ed848ba0f0fb862731c77a41bbf Mon Sep 17 00:00:00 2001
From: Chester Liu <4710575+skyline75489@users.noreply.github.com>
Date: Fri, 22 Nov 2024 16:46:31 +0800
Subject: [PATCH] Fix C# Win-Cuda-x64 GHA pipeline (#1084)
The C# tests need to be run *after* python tests for the models to be
ready.
Also pick up the CUDA model instead of CPU one in C# test code.
---
.github/workflows/win-cuda-x64-build.yml | 11 +--
...Microsoft.ML.OnnxRuntimeGenAI.Tests.csproj | 8 ++
test/csharp/TestOnnxRuntimeGenAIAPI.cs | 90 ++++++++++++++++---
3 files changed, 90 insertions(+), 19 deletions(-)
diff --git a/.github/workflows/win-cuda-x64-build.yml b/.github/workflows/win-cuda-x64-build.yml
index 3bff048a7..5cda163d1 100644
--- a/.github/workflows/win-cuda-x64-build.yml
+++ b/.github/workflows/win-cuda-x64-build.yml
@@ -73,11 +73,6 @@ jobs:
run: |
echo "${{ env.cuda_dir }}\\v${{ env.cuda_version }}\\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- - name: Build the C# API and Run the C# Tests
- run: |
- cd test\csharp
- dotnet test /p:Configuration=release /p:NativeBuildOutputDir="$env:GITHUB_WORKSPACE\$env:binaryDir\Release" /p:OrtLibDir="$env:GITHUB_WORKSPACE\ort\lib"
-
- name: Install the Python Wheel and Test Dependencies
run: |
python -m pip install -r test\python\requirements.txt
@@ -100,6 +95,12 @@ jobs:
Get-ChildItem -Path $env:GITHUB_WORKSPACE\$env:binaryDir -Recurse
+ - name: Build the C# API and Run the C# Tests
+ run: |
+ $env:PATH = "${{ env.cuda_dir }}\\v${{ env.cuda_version }}\\bin;" + $env:PATH
+ cd test\csharp
+ dotnet test /p:Configuration=release /p:NativeBuildOutputDir="$env:GITHUB_WORKSPACE\$env:binaryDir\Release" /p:OrtLibDir="$env:GITHUB_WORKSPACE\ort\lib"
+
- name: Prepend CUDA to PATH and Run tests
run: |
$env:PATH = "${{ env.cuda_dir }}\\v${{ env.cuda_version }}\\bin;" + $env:PATH
diff --git a/test/csharp/Microsoft.ML.OnnxRuntimeGenAI.Tests.csproj b/test/csharp/Microsoft.ML.OnnxRuntimeGenAI.Tests.csproj
index cb43d91ba..159f80060 100644
--- a/test/csharp/Microsoft.ML.OnnxRuntimeGenAI.Tests.csproj
+++ b/test/csharp/Microsoft.ML.OnnxRuntimeGenAI.Tests.csproj
@@ -31,6 +31,10 @@
PreserveNewest
false
+
+ PreserveNewest
+ false
+
PreserveNewest
false
@@ -49,6 +53,10 @@
PreserveNewest
false
+
+ PreserveNewest
+ false
+
PreserveNewest
false
diff --git a/test/csharp/TestOnnxRuntimeGenAIAPI.cs b/test/csharp/TestOnnxRuntimeGenAIAPI.cs
index 3ea5fd663..8c916dbb1 100644
--- a/test/csharp/TestOnnxRuntimeGenAIAPI.cs
+++ b/test/csharp/TestOnnxRuntimeGenAIAPI.cs
@@ -38,8 +38,55 @@ private static string GetDirectoryInTreeThatContains(string currentDirectory, st
return null;
}
- private static readonly string _phi2Path = Path.Combine(
- GetDirectoryInTreeThatContains(Directory.GetCurrentDirectory(), "test"), "test_models", "phi-2", "int4", "cpu");
+ private static bool _useCudaModel = false;
+
+ private static Lazy _lazyPhi2Path = new Lazy(() =>
+ {
+ string cpuModelPath = Path.Combine(GetDirectoryInTreeThatContains(Directory.GetCurrentDirectory(), "test"),
+ "test_models", "phi-2", "int4", "cpu");
+ string cudaModelPath = Path.Combine(GetDirectoryInTreeThatContains(Directory.GetCurrentDirectory(), "test"),
+ "test_models", "phi-2", "int4", "cuda");
+ // Prefer CUDA model if available.
+ if (System.IO.Directory.Exists(cudaModelPath))
+ {
+ _useCudaModel = true;
+ return cudaModelPath;
+ }
+
+ _useCudaModel = false;
+ return cpuModelPath;
+ });
+
+ private static string _phi2Path => _lazyPhi2Path.Value;
+
+ private static Lazy _lazyTinyRandomGpt2ModelPath = new Lazy(() =>
+ {
+ string modelPath = Path.Combine(GetDirectoryInTreeThatContains(Directory.GetCurrentDirectory(), "test"),
+ "test_models", "hf-internal-testing", "tiny-random-gpt2-fp32");
+ if (System.IO.Directory.Exists(modelPath))
+ {
+ return modelPath;
+ }
+
+ return null;
+ });
+
+ private static string _tinyRandomGpt2ModelPath => _lazyTinyRandomGpt2ModelPath.Value;
+
+ private static Lazy _lazyAdaptersPath = new Lazy(() =>
+ {
+ string modelPath = Path.Combine(GetDirectoryInTreeThatContains(Directory.GetCurrentDirectory(), "test"),
+ "test_models", "adapters");
+ if (System.IO.Directory.Exists(modelPath))
+ {
+ return modelPath;
+ }
+
+ return null;
+ });
+
+ private static string _adaptersPath => _lazyAdaptersPath.Value;
+
public OnnxRuntimeGenAITests(ITestOutputHelper o)
{
@@ -63,7 +110,7 @@ public IgnoreOnModelAbsenceFact()
[Fact(DisplayName = "TestConfig")]
public void TestConfig()
{
- string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_models", "hf-internal-testing", "tiny-random-gpt2-fp32");
+ string modelPath = _tinyRandomGpt2ModelPath;
using (var config = new Config(modelPath))
{
config.ClearProviders();
@@ -87,7 +134,7 @@ public void TestGreedySearch()
var expectedOutput = new int[] { 0, 0, 0, 52, 204, 204, 204, 204, 204, 204,
0, 0, 195, 731, 731, 114, 114, 114, 114, 114 };
- string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_models", "hf-internal-testing", "tiny-random-gpt2-fp32");
+ string modelPath = _tinyRandomGpt2ModelPath;
using (var config = new Config(modelPath))
{
Assert.NotNull(config);
@@ -418,7 +465,7 @@ public void TestPhi2()
[Fact(DisplayName = "TestTensorAndAddExtraInput")]
public void TestTensorAndAddExtraInput()
{
- string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_models", "hf-internal-testing", "tiny-random-gpt2-fp32");
+ string modelPath = _tinyRandomGpt2ModelPath;
using var model = new Model(modelPath);
Assert.NotNull(model);
@@ -452,7 +499,7 @@ private class IgnoreOnAdaptersAbsentFact : FactAttribute
{
public IgnoreOnAdaptersAbsentFact()
{
- string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_models", "adapters");
+ string modelPath = _adaptersPath;
bool exists = System.IO.Directory.Exists(modelPath);
if (!System.IO.Directory.Exists(modelPath))
{
@@ -468,7 +515,7 @@ public IgnoreOnAdaptersAbsentFact()
[IgnoreOnAdaptersAbsentFact(DisplayName = "TestAdapters")]
public void TestAdapters()
{
- string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_models", "adapters");
+ string modelPath = _adaptersPath;
string adapterPath = Path.Combine(modelPath, "adapters.onnx_adapter");
using var model = new Model(modelPath);
@@ -489,7 +536,7 @@ public void TestAdapters()
Int64 outputSize = 0;
Int64[] output_shape;
- float[] base_output;
+ float[] base_output = [];
// Run base scenario
{
@@ -505,10 +552,18 @@ public void TestAdapters()
}
using var logits = generator.GetOutput("logits");
- Assert.Equal(ElementType.float32, logits.Type());
+ if (_useCudaModel)
+ {
+ Assert.Equal(ElementType.float16, logits.Type());
+ // TODO: GetData with float16?
+ }
+ else
+ {
+ Assert.Equal(ElementType.float32, logits.Type());
+ base_output = logits.GetData().ToArray();
+ }
output_shape = logits.Shape();
outputSize = logits.NumElements();
- base_output = logits.GetData().ToArray();
}
// Adapter scenario. The output must be affected
{
@@ -524,12 +579,19 @@ public void TestAdapters()
generator.GenerateNextToken();
}
using var logits = generator.GetOutput("logits");
- Assert.Equal(ElementType.float32, logits.Type());
+ if (_useCudaModel)
+ {
+ Assert.Equal(ElementType.float16, logits.Type());
+ // TODO: GetData with float16?
+ }
+ else
+ {
+ Assert.Equal(ElementType.float32, logits.Type());
+ var adapter_output = logits.GetData().ToArray();
+ Assert.NotEqual(base_output, adapter_output);
+ }
Assert.Equal(outputSize, logits.NumElements());
Assert.Equal(output_shape, logits.Shape());
-
- var adapter_output = logits.GetData().ToArray();
- Assert.NotEqual(base_output, adapter_output);
}
}
}