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); } } }