Fix post merge jobs pipeline build issues (#14346)

- Fix debug node inputs outputs nullptr dereference with ONNX optional types.
- Fix model test memory leak.
- Convert jobs to stages in post-merge-jobs.yml to allow a subset of builds to be enabled when running manually.
- Fix buffer overrun in CumSum op exposed by Mimalloc build.
This commit is contained in:
Edward Chen 2023-01-19 11:16:42 -08:00 committed by GitHub
parent ea7bbd667d
commit ae0e090c7b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 204 additions and 179 deletions

View file

@ -478,23 +478,26 @@ void DumpNodeInputs(
if (type) {
if (type->IsTensorType()) {
const auto& tensor = *context.Input<Tensor>(i);
const auto& shape = tensor.Shape();
if (const auto* tensor = context.Input<Tensor>(i); tensor != nullptr) {
const auto& shape = tensor->Shape();
const bool is_shape_set = (dump_options.dump_flags & NodeDumpOptions::DumpFlags::Shape) != 0;
PrintIf(is_shape_set, MakeString(" Shape: ", shape, "\n"));
const bool is_shape_set = (dump_options.dump_flags & NodeDumpOptions::DumpFlags::Shape) != 0;
PrintIf(is_shape_set, MakeString(" Shape: ", shape, "\n"));
if ((dump_options.dump_flags & NodeDumpOptions::DumpFlags::InputData) != 0) {
tensor_metadata.name = input_defs[i]->Name();
tensor_metadata.step = dump_context.iteration;
tensor_metadata.consumer = node.Name() + ":" + std::to_string(i);
DumpTensor(dump_options, tensor, tensor_metadata, session_state);
if ((dump_options.dump_flags & NodeDumpOptions::DumpFlags::InputData) != 0) {
tensor_metadata.name = input_defs[i]->Name();
tensor_metadata.step = dump_context.iteration;
tensor_metadata.consumer = node.Name() + ":" + std::to_string(i);
DumpTensor(dump_options, *tensor, tensor_metadata, session_state);
}
} else {
std::cout << " is empty optional tensor.\n";
}
} else {
std::cout << " is non-tensor type.\n";
}
} else {
// should never happen...
// this could happen with an empty Optional input
std::cout << " was missing data type\n";
}
} else {
@ -546,23 +549,26 @@ void DumpNodeOutputs(
const auto* type = context.OutputType(i);
if (type) {
if (type->IsTensorType()) {
const auto& tensor = *context.Output<Tensor>(i);
const auto& shape = tensor.Shape();
if (const auto* tensor = context.Output<Tensor>(i); tensor != nullptr) {
const auto& shape = tensor->Shape();
const bool is_shape_set = (dump_options.dump_flags & NodeDumpOptions::DumpFlags::Shape) != 0;
PrintIf(is_shape_set, MakeString(" Shape: ", shape, "\n"));
const bool is_shape_set = (dump_options.dump_flags & NodeDumpOptions::DumpFlags::Shape) != 0;
PrintIf(is_shape_set, MakeString(" Shape: ", shape, "\n"));
if ((dump_options.dump_flags & NodeDumpOptions::DumpFlags::OutputData) != 0) {
tensor_metadata.name = output_defs[i]->Name();
tensor_metadata.step = dump_context.iteration;
tensor_metadata.producer = node.Name() + ":" + std::to_string(i);
DumpTensor(dump_options, tensor, tensor_metadata, session_state);
if ((dump_options.dump_flags & NodeDumpOptions::DumpFlags::OutputData) != 0) {
tensor_metadata.name = output_defs[i]->Name();
tensor_metadata.step = dump_context.iteration;
tensor_metadata.producer = node.Name() + ":" + std::to_string(i);
DumpTensor(dump_options, *tensor, tensor_metadata, session_state);
}
} else {
std::cout << " is empty optional tensor.\n";
}
} else {
std::cout << " is non-tensor type.\n";
}
} else {
// should never happen...
// should never happen in a successful run
std::cout << "missing data type\n";
}
} else {

View file

@ -170,6 +170,13 @@ Memory_LeakCheck::Memory_LeakCheck() noexcept {
g_heap = HeapCreate(0, 0, 0);
}
// print message to debug output and stdout
// no trailing newline will be added
static void DebugPrint(const char* message) {
OutputDebugStringA(message);
std::cout << "memleakdbg: " << message;
}
Memory_LeakCheck::~Memory_LeakCheck() {
SymbolHelper symbols;
@ -219,17 +226,17 @@ Memory_LeakCheck::~Memory_LeakCheck() {
string.find("testing::internal::ThreadLocalRegistryImpl::GetThreadLocalsMapLocked") == std::string::npos &&
string.find("testing::internal::ThreadLocalRegistryImpl::GetValueOnCurrentThread") == std::string::npos) {
if (leaked_bytes == 0)
OutputDebugStringA("\n-----Starting Heap Trace-----\n\n");
DebugPrint("\n-----Starting Heap Trace-----\n\n");
leak_count++;
leaked_bytes += entry.cbData - sizeof(MemoryBlock);
OutputDebugStringA(string.c_str());
OutputDebugStringA("\n");
DebugPrint(string.c_str());
DebugPrint("\n");
}
}
if (leaked_bytes) {
OutputDebugStringA("-----Ending Heap Trace-----\n\n");
DebugPrint("-----Ending Heap Trace-----\n\n");
std::string string;
char buffer[1024];
@ -242,7 +249,7 @@ Memory_LeakCheck::~Memory_LeakCheck() {
}
} else {
OutputDebugStringA("\n----- No memory leaks detected -----\n\n");
DebugPrint("\n----- No memory leaks detected -----\n\n");
}
HeapDestroy(heap);

View file

@ -215,7 +215,8 @@ Status CumSum<T>::Compute(OpKernelContext* ctx) const {
::ZeroOutSliceAtIndex<T>(output_tensor, rank, axis, index, slice_dims, steps, slice_size);
++index;
}
{
if (index < dim) {
// The next slice is a copy of the input (if exclusive == false then this is the first slice)
auto input_starts(::GetStarts(rank, axis, 0));
auto output_starts(::GetStarts(rank, axis, index));

View file

@ -673,25 +673,24 @@ TEST_P(ModelTest, Run) {
for (bool is_single_thread : use_single_thread) {
for (ExecutionMode execution_mode : execution_modes) {
OrtSessionOptions* ortso;
ASSERT_ORT_STATUS_OK(OrtApis::CreateSessionOptions(&ortso));
Ort::SessionOptions ortso{};
if (!is_single_thread) {
ASSERT_ORT_STATUS_OK(OrtApis::DisablePerSessionThreads(ortso));
ortso.DisablePerSessionThreads();
} else {
ASSERT_ORT_STATUS_OK(OrtApis::SetIntraOpNumThreads(ortso, 1));
ortso.SetIntraOpNumThreads(1);
}
ASSERT_ORT_STATUS_OK(OrtApis::SetSessionExecutionMode(ortso, execution_mode));
ASSERT_ORT_STATUS_OK(OrtApis::SetSessionLogId(ortso, ToUTF8String(test_case_name).c_str()));
ASSERT_ORT_STATUS_OK(OrtApis::SetSessionLogSeverityLevel(ortso, ORT_LOGGING_LEVEL_ERROR));
ortso.SetExecutionMode(execution_mode);
ortso.SetLogId(ToUTF8String(test_case_name).c_str());
ortso.SetLogSeverityLevel(ORT_LOGGING_LEVEL_ERROR);
if (provider_name == "cuda") {
OrtCUDAProviderOptionsV2* cuda_options = nullptr;
ASSERT_ORT_STATUS_OK(OrtApis::CreateCUDAProviderOptions(&cuda_options));
std::unique_ptr<OrtCUDAProviderOptionsV2, decltype(&OrtApis::ReleaseCUDAProviderOptions)> rel_cuda_options(
cuda_options, &OrtApis::ReleaseCUDAProviderOptions);
ASSERT_ORT_STATUS_OK(OrtApis::SessionOptionsAppendExecutionProvider_CUDA_V2(ortso, cuda_options));
ortso.AppendExecutionProvider_CUDA_V2(*cuda_options);
} else if (provider_name == "rocm") {
OrtROCMProviderOptions ep_options;
ASSERT_ORT_STATUS_OK(OrtApis::SessionOptionsAppendExecutionProvider_ROCM(ortso, &ep_options));
ortso.AppendExecutionProvider_ROCM(ep_options);
}
#ifdef USE_DNNL
else if (provider_name == "dnnl") {
@ -703,26 +702,26 @@ TEST_P(ModelTest, Run) {
OrtTensorRTProviderOptionsV2 params{0, 0, nullptr, 1000, 1, 1 << 30,
1, // enable fp16
0, nullptr, 0, 0, 0, 0, 0, nullptr, 0, nullptr, 0, 0, 0};
ASSERT_ORT_STATUS_OK(OrtApis::SessionOptionsAppendExecutionProvider_TensorRT_V2(ortso, &params));
ortso.AppendExecutionProvider_TensorRT_V2(params);
} else {
OrtTensorRTProviderOptionsV2* ep_option;
OrtTensorRTProviderOptionsV2* ep_option = nullptr;
ASSERT_ORT_STATUS_OK(OrtApis::CreateTensorRTProviderOptions(&ep_option));
std::unique_ptr<OrtTensorRTProviderOptionsV2, decltype(&OrtApis::ReleaseTensorRTProviderOptions)>
rel_cuda_options(ep_option, &OrtApis::ReleaseTensorRTProviderOptions);
ASSERT_ORT_STATUS_OK(OrtApis::SessionOptionsAppendExecutionProvider_TensorRT_V2(ortso, ep_option));
ortso.AppendExecutionProvider_TensorRT_V2(*ep_option);
}
// Enable CUDA fallback
OrtCUDAProviderOptionsV2* cuda_options = nullptr;
ASSERT_ORT_STATUS_OK(OrtApis::CreateCUDAProviderOptions(&cuda_options));
std::unique_ptr<OrtCUDAProviderOptionsV2, decltype(&OrtApis::ReleaseCUDAProviderOptions)> rel_cuda_options(
cuda_options, &OrtApis::ReleaseCUDAProviderOptions);
ASSERT_ORT_STATUS_OK(OrtApis::SessionOptionsAppendExecutionProvider_CUDA_V2(ortso, cuda_options));
ortso.AppendExecutionProvider_CUDA_V2(*cuda_options);
} else if (provider_name == "migraphx") {
OrtMIGraphXProviderOptions ep_options;
ASSERT_ORT_STATUS_OK(OrtApis::SessionOptionsAppendExecutionProvider_MIGraphX(ortso, &ep_options));
ortso.AppendExecutionProvider_MIGraphX(ep_options);
} else if (provider_name == "openvino") {
OrtOpenVINOProviderOptions ep_options;
ASSERT_ORT_STATUS_OK(OrtApis::SessionOptionsAppendExecutionProvider_OpenVINO(ortso, &ep_options));
ortso.AppendExecutionProvider_OpenVINO(ep_options);
}
#ifdef USE_NNAPI
else if (provider_name == "nnapi") {
@ -760,8 +759,7 @@ TEST_P(ModelTest, Run) {
#ifndef USE_DNNL // potential crash for DNNL pipeline
if (data_count > 1 && tests_run_parallel.find(l->GetTestCaseName()) != tests_run_parallel.end()) {
LOGS_DEFAULT(ERROR) << "Parallel test for " << l->GetTestCaseName(); // TODO(leca): change level to INFO or even delete the log once verified parallel test working
Ort::SessionOptions ort_session_options(ortso);
std::shared_ptr<TestCaseResult> results = TestCaseRequestContext::Run(tp.get(), *l, *ort_env, ort_session_options, data_count, 1 /*repeat_count*/);
std::shared_ptr<TestCaseResult> results = TestCaseRequestContext::Run(tp.get(), *l, *ort_env, ortso, data_count, 1 /*repeat_count*/);
for (EXECUTE_RESULT res : results->GetExcutionResult()) {
EXPECT_EQ(res, EXECUTE_RESULT::SUCCESS) << "is_single_thread:" << is_single_thread << ", execution_mode:" << execution_mode << ", provider_name:"
<< provider_name << ", test name:" << results->GetName() << ", result: " << res;
@ -769,8 +767,6 @@ TEST_P(ModelTest, Run) {
continue;
}
#endif // !USE_DNNL
std::unique_ptr<OrtSessionOptions, decltype(&OrtApis::ReleaseSessionOptions)> rel_ort_session_option(
ortso, &OrtApis::ReleaseSessionOptions);
// TODO(leca): leverage TestCaseRequestContext::Run() to make it short
auto default_allocator = std::make_unique<MockedOrtAllocator>();

View file

@ -1,143 +1,158 @@
jobs:
- template: templates/win-ci-vs-2019.yml
parameters:
BuildConfig: 'Debug'
EnvSetupScript: setup_env.bat
buildArch: x64
additionalBuildFlags: --disable_memleak_checker --use_mimalloc
msbuildPlatform: x64
isX86: false
job_name_suffix: x64_mimalloc
RunOnnxRuntimeTests: true
RunStaticCodeAnalysis: false
isTraining: false
ORT_EP_NAME: CPU
GenerateDocumentation: false
EnablePython: false
MachinePool: 'Win-CPU-2021'
stages:
- stage: Mimalloc
dependsOn: []
jobs:
- template: templates/win-ci-vs-2019.yml
parameters:
BuildConfig: 'Debug'
EnvSetupScript: setup_env.bat
buildArch: x64
additionalBuildFlags: --disable_memleak_checker --use_mimalloc
msbuildPlatform: x64
isX86: false
job_name_suffix: x64_mimalloc
RunOnnxRuntimeTests: true
RunStaticCodeAnalysis: false
isTraining: false
ORT_EP_NAME: CPU
GenerateDocumentation: false
EnablePython: false
MachinePool: 'Win-CPU-2021'
- template: templates/win-ci-vs-2019.yml
parameters:
BuildConfig: 'Debug'
EnvSetupScript: setup_env.bat
buildArch: x64
additionalBuildFlags: --cmake_extra_defines onnxruntime_DISABLE_ABSEIL=ON
msbuildPlatform: x64
isX86: false
job_name_suffix: x64_no_absl
RunOnnxRuntimeTests: true
RunStaticCodeAnalysis: false
isTraining: false
ORT_EP_NAME: CPU
GenerateDocumentation: false
EnablePython: false
MachinePool: 'Win-CPU-2021'
- stage: NoAbseil
dependsOn: []
jobs:
- template: templates/win-ci-vs-2019.yml
parameters:
BuildConfig: 'Debug'
EnvSetupScript: setup_env.bat
buildArch: x64
additionalBuildFlags: --cmake_extra_defines onnxruntime_DISABLE_ABSEIL=ON
msbuildPlatform: x64
isX86: false
job_name_suffix: x64_no_absl
RunOnnxRuntimeTests: true
RunStaticCodeAnalysis: false
isTraining: false
ORT_EP_NAME: CPU
GenerateDocumentation: false
EnablePython: false
MachinePool: 'Win-CPU-2021'
- template: templates/win-ci-vs-2019.yml
parameters:
BuildConfig: 'Debug'
EnvSetupScript: setup_env.bat
buildArch: x64
additionalBuildFlags: --build_shared_lib --minimal_build --disable_exceptions
msbuildPlatform: x64
isX86: false
job_name_suffix: x64_minimal_no_exception
RunOnnxRuntimeTests: true
RunStaticCodeAnalysis: false
isTraining: false
ORT_EP_NAME: CPU
GenerateDocumentation: false
EnablePython: false
MachinePool: 'Win-CPU-2021'
- stage: MinimalBuildWithNoExceptions
dependsOn: []
jobs:
- template: templates/win-ci-vs-2019.yml
parameters:
BuildConfig: 'Debug'
EnvSetupScript: setup_env.bat
buildArch: x64
additionalBuildFlags: --build_shared_lib --minimal_build --disable_exceptions
msbuildPlatform: x64
isX86: false
job_name_suffix: x64_minimal_no_exception
RunOnnxRuntimeTests: true
RunStaticCodeAnalysis: false
isTraining: false
ORT_EP_NAME: CPU
GenerateDocumentation: false
EnablePython: false
MachinePool: 'Win-CPU-2021'
- template: templates/win-ci-vs-2019.yml
parameters:
BuildConfig: 'Debug'
EnvSetupScript: setup_env.bat
buildArch: x64
additionalBuildFlags: --build_shared_lib --cmake_extra_defines onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS=ON
msbuildPlatform: x64
isX86: false
job_name_suffix: x64_debug_node_input_output
RunOnnxRuntimeTests: true
RunStaticCodeAnalysis: false
isTraining: false
ORT_EP_NAME: CPU
GenerateDocumentation: false
EnablePython: false
MachinePool: 'Win-CPU-2021'
- stage: DebugNodeInputsOutputs
dependsOn: []
jobs:
- template: templates/win-ci-vs-2019.yml
parameters:
BuildConfig: 'Debug'
EnvSetupScript: setup_env.bat
buildArch: x64
additionalBuildFlags: --build_shared_lib --cmake_extra_defines onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS=ON
msbuildPlatform: x64
isX86: false
job_name_suffix: x64_debug_node_input_output
RunOnnxRuntimeTests: true
RunStaticCodeAnalysis: false
isTraining: false
ORT_EP_NAME: CPU
GenerateDocumentation: false
EnablePython: false
MachinePool: 'Win-CPU-2021'
- job: CodeCoverage
workspace:
clean: all
timeoutInMinutes: 150
variables:
skipComponentGovernanceDetection: true
pool: 'Linux-CPU'
steps:
- template: templates/set-version-number-variables-step.yml
- stage: CodeCoverage
dependsOn: []
jobs:
- job: CodeCoverage
workspace:
clean: all
timeoutInMinutes: 150
variables:
skipComponentGovernanceDetection: true
pool: 'Linux-CPU'
steps:
- template: templates/set-version-number-variables-step.yml
- task: CmdLine@2
- task: CmdLine@2
inputs:
script: |
set -e
ln -s /data/models .
#Build onnxruntime and run the instrumented program(unitests)
LLVM_PROFILE_FILE="%p.profraw" CFLAGS="-g -fprofile-instr-generate -fcoverage-mapping" CXXFLAGS="-g -fprofile-instr-generate -fcoverage-mapping" CC=clang CXX=clang++ python3 $(Build.SourcesDirectory)/tools/ci_build/build.py --build_dir=$(Build.BinariesDirectory) --config Debug --parallel --skip_submodule_sync --build_shared_lib --enable_onnx_tests --cmake_extra_defines RUN_MODELTEST_IN_DEBUG_MODE=ON
cd Debug
./onnxruntime_mlas_test
#Merge the mulitple prof data into a single indexed profile data file
llvm-profdata merge -sparse -o ort.profdata *.profraw
#Create coverage report, output the result to 'report.json'
llvm-cov export -summary-only -instr-profile=ort.profdata onnxruntime_test_all -object onnxruntime_mlas_test -object onnxruntime_api_tests_without_env -object onnx_test_runner -object onnxruntime_shared_lib_test -object onnxruntime_global_thread_pools_test -object onnxruntime_api_tests_without_env $(Build.SourcesDirectory)/include/onnxruntime $(Build.SourcesDirectory)/onnxruntime/core $(Build.SourcesDirectory)/onnxruntime/contrib_ops > $(Build.BinariesDirectory)/report.json
llvm-cov show -instr-profile=ort.profdata onnxruntime_test_all -object onnxruntime_mlas_test -object onnxruntime_api_tests_without_env -object onnx_test_runner -object onnxruntime_shared_lib_test -object onnxruntime_global_thread_pools_test -object onnxruntime_api_tests_without_env $(Build.SourcesDirectory)/include/onnxruntime $(Build.SourcesDirectory)/onnxruntime/core $(Build.SourcesDirectory)/onnxruntime/contrib_ops --format=html -output-dir=$(Build.ArtifactStagingDirectory)
workingDirectory: $(Build.BinariesDirectory)
- task: AzureCLI@2
displayName: 'Azure CLI'
inputs:
azureSubscription: AIInfraBuildOnnxRuntimeOSS
scriptType: bash
scriptPath: $(Build.SourcesDirectory)/tools/ci_build/github/linux/upload_code_coverage_data.sh
arguments: '"$(Build.BinariesDirectory)/report.json" "https://aiinfra.visualstudio.com/Lotus/_build/results?buildId=$(Build.BuildId)" x64 linux default'
workingDirectory: '$(Build.BinariesDirectory)'
- task: PublishPipelineArtifact@1
displayName: 'Publish Pipeline Artifact'
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)'
artifact: html
- job: Upload
workspace:
clean: all
pool: 'Win-CPU-2021'
variables:
- name: runCodesignValidationInjection
value: false
- name: skipComponentGovernanceDetection
value: true
dependsOn:
- CodeCoverage
condition: and (succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
steps:
- checkout: self
submodules: false
- task: DownloadPipelineArtifact@2
displayName: 'Download Pipeline Artifact'
inputs:
script: |
set -e
ln -s /data/models .
#Build onnxruntime and run the instrumented program(unitests)
LLVM_PROFILE_FILE="%p.profraw" CFLAGS="-g -fprofile-instr-generate -fcoverage-mapping" CXXFLAGS="-g -fprofile-instr-generate -fcoverage-mapping" CC=clang CXX=clang++ python3 $(Build.SourcesDirectory)/tools/ci_build/build.py --build_dir=$(Build.BinariesDirectory) --config Debug --parallel --skip_submodule_sync --build_shared_lib --enable_onnx_tests --cmake_extra_defines RUN_MODELTEST_IN_DEBUG_MODE=ON
buildType: 'current'
artifactName: 'html'
targetPath: '$(Build.BinariesDirectory)'
cd Debug
./onnxruntime_mlas_test
#Merge the mulitple prof data into a single indexed profile data file
llvm-profdata merge -sparse -o ort.profdata *.profraw
#Create coverage report, output the result to 'report.json'
llvm-cov export -summary-only -instr-profile=ort.profdata onnxruntime_test_all -object onnxruntime_mlas_test -object onnxruntime_api_tests_without_env -object onnx_test_runner -object onnxruntime_shared_lib_test -object onnxruntime_global_thread_pools_test -object onnxruntime_api_tests_without_env $(Build.SourcesDirectory)/include/onnxruntime $(Build.SourcesDirectory)/onnxruntime/core $(Build.SourcesDirectory)/onnxruntime/contrib_ops > $(Build.BinariesDirectory)/report.json
llvm-cov show -instr-profile=ort.profdata onnxruntime_test_all -object onnxruntime_mlas_test -object onnxruntime_api_tests_without_env -object onnx_test_runner -object onnxruntime_shared_lib_test -object onnxruntime_global_thread_pools_test -object onnxruntime_api_tests_without_env $(Build.SourcesDirectory)/include/onnxruntime $(Build.SourcesDirectory)/onnxruntime/core $(Build.SourcesDirectory)/onnxruntime/contrib_ops --format=html -output-dir=$(Build.ArtifactStagingDirectory)
workingDirectory: $(Build.BinariesDirectory)
- task: AzureCLI@2
displayName: 'Azure CLI'
- task: AzureFileCopy@4
displayName: 'AzureBlob File Copy'
inputs:
SourcePath: '$(Build.BinariesDirectory)\*'
azureSubscription: AIInfraBuildOnnxRuntimeOSS
scriptType: bash
scriptPath: $(Build.SourcesDirectory)/tools/ci_build/github/linux/upload_code_coverage_data.sh
arguments: '"$(Build.BinariesDirectory)/report.json" "https://aiinfra.visualstudio.com/Lotus/_build/results?buildId=$(Build.BuildId)" x64 linux default'
workingDirectory: '$(Build.BinariesDirectory)'
- task: PublishPipelineArtifact@1
displayName: 'Publish Pipeline Artifact'
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)'
artifact: html
- job: Upload
workspace:
clean: all
pool: 'Win-CPU-2021'
variables:
- name: runCodesignValidationInjection
value: false
- name: skipComponentGovernanceDetection
value: true
dependsOn:
- CodeCoverage
condition: and (succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
steps:
- checkout: self
submodules: false
- task: DownloadPipelineArtifact@2
displayName: 'Download Pipeline Artifact'
inputs:
buildType: 'current'
artifactName: 'html'
targetPath: '$(Build.BinariesDirectory)'
- task: AzureFileCopy@4
displayName: 'AzureBlob File Copy'
inputs:
SourcePath: '$(Build.BinariesDirectory)\*'
azureSubscription: AIInfraBuildOnnxRuntimeOSS
Destination: AzureBlob
storage: onnxruntime
ContainerName: '$web'
Destination: AzureBlob
storage: onnxruntime
ContainerName: '$web'