Files
TheRock/rocm-libraries/projects/miopen/test/gtest/naive_disable_if_alt.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

183 lines
7.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
// SPDX-License-Identifier: MIT
// Tests for MIOPEN_NAIVE_DISABLE_IF_ALT behavior in the find path.
//
// Paths through EvaluateInvokers naive-deferring logic (solver_finders.cpp):
//
// Path naive_disable defer_naive non_naive_succeeded Outcome
// ---- ------------- ----------- ------------------- -------------------------
// A false - - naive evaluated (flag off)
// B true false - naive evaluated (no non-naive exists)
// C true true false naive evaluated (non-naive all failed)
// D true true true naive SKIPPED (intended fast path)
//
// Tests cover paths A, B, and D. Path C is not exercised:
// Path C: requires fault injection into the invoker execution path at runtime.
//
// Path B uses MIOPEN_DEBUG_FIND_ONLY_SOLVER=ConvDirectNaiveConvFwd to restrict the candidate
// set to the naive solver only. GetEnvFindOnlySolver() re-evaluates the env var on every call
// under MIOPEN_BUILD_TESTING (no static cache) so ScopedEnvironment takes effect.
//
// Tests assert presence/absence of naive solvers rather than which solver wins by timing,
// so results are not sensitive to GPU performance variation.
//
// Each GPU test uses ScopedFindDb to disable miopen::debug::testing_find_db_enabled for the
// duration of the test, ensuring TryLoad always calls the regenerator (FindCore / EvaluateInvokers)
// rather than returning a cached find DB entry.
#include <gtest/gtest.h>
#include <miopen/miopen.h>
#include <miopen/convolution.hpp>
#include <miopen/find_db.hpp>
#include <miopen/solver_id.hpp>
#include "get_handle.hpp"
#include "gtest_common.hpp"
#include "../tensor_holder.hpp"
MIOPEN_LIB_ENV_VAR(MIOPEN_NAIVE_DISABLE_IF_ALT)
namespace {
// RAII: disables the user find DB for the duration of the test so FindCore /
// EvaluateInvokers always runs rather than returning a cached result.
// miopen::debug::testing_find_db_enabled is declared in <miopen/find_db.hpp> and
// checked in TryLoad: when false, construct_db() returns null → in_sync=false →
// regenerator() (FindCore) is always called. Saves and restores the previous value
// so tests that run before or after us with find DB disabled are not disturbed.
struct ScopedFindDb
{
ScopedFindDb() : prev_(miopen::debug::testing_find_db_enabled)
{
miopen::debug::testing_find_db_enabled = false;
}
~ScopedFindDb() { miopen::debug::testing_find_db_enabled = prev_; }
bool prev_;
};
// Returns solver names (fastest first) from miopenFindSolutions for a small NCHW FP32 forward
// convolution: 1×64×14×14 input, 64×3×3 filter, pad=1, stride=1.
// This shape attracts ImplicitGEMM/Winograd on all supported GPUs, ensuring a non-naive winner.
std::vector<std::string> RunFind(miopenHandle_t handle, size_t max_solutions = 8)
{
tensor<float> x{1, 64, 14, 14};
tensor<float> w{64, 64, 3, 3};
miopen::ConvolutionDescriptor conv{
2, miopenConvolution, miopenPaddingDefault, {1, 1}, {1, 1}, {1, 1}};
tensor<float> y{conv.GetForwardOutputTensor(x.desc, w.desc)};
miopenProblem_t problem = nullptr;
EXPECT_EQ(miopenCreateConvProblem(&problem, &conv, miopenProblemDirectionForward),
miopenStatusSuccess);
EXPECT_EQ(miopenSetProblemTensorDescriptor(problem, miopenTensorConvolutionX, &x.desc),
miopenStatusSuccess);
EXPECT_EQ(miopenSetProblemTensorDescriptor(problem, miopenTensorConvolutionW, &w.desc),
miopenStatusSuccess);
EXPECT_EQ(miopenSetProblemTensorDescriptor(problem, miopenTensorConvolutionY, &y.desc),
miopenStatusSuccess);
std::vector<miopenSolution_t> solutions(max_solutions);
size_t num_found = 0;
EXPECT_EQ(
miopenFindSolutions(handle, problem, nullptr, solutions.data(), &num_found, max_solutions),
miopenStatusSuccess);
solutions.resize(num_found);
std::vector<std::string> names;
for(auto sol : solutions)
{
uint64_t solver_id = 0;
EXPECT_EQ(miopenGetSolutionSolverId(sol, &solver_id), miopenStatusSuccess);
names.push_back(miopen::solver::Id{solver_id}.ToString());
miopenDestroySolution(sol);
}
miopenDestroyProblem(problem);
return names;
}
bool IsNaive(const std::string& name) { return name.find("Naive") != std::string::npos; }
} // namespace
// With MIOPEN_NAIVE_DISABLE_IF_ALT=1, no naive solver should appear anywhere in the results
// for a shape that has non-naive alternatives.
TEST(GPU_NaiveDisableIfAlt_FP32, NaiveAbsentFromAllResultsWhenDisabled)
{
auto& handle_ref = get_handle();
miopenHandle_t handle = &handle_ref;
ScopedFindDb no_cache; // disables find DB so FindCore / EvaluateInvokers always runs
ScopedEnvironment<bool> guard_naive(MIOPEN_NAIVE_DISABLE_IF_ALT, true);
auto solvers = RunFind(handle);
ASSERT_FALSE(solvers.empty()) << "miopenFindSolutions returned no results";
for(const auto& s : solvers)
{
EXPECT_FALSE(IsNaive(s))
<< "Naive solver found in results with MIOPEN_NAIVE_DISABLE_IF_ALT=1: " << s;
}
}
// With MIOPEN_NAIVE_DISABLE_IF_ALT=0 (opt-out), a naive solver must appear somewhere in the
// results, confirming that the skip logic in EvaluateInvokers did not fire.
// This tests the opt-out code path directly without depending on which solver wins by timing.
TEST(GPU_NaiveDisableIfAlt_FP32, NaivePresentInResultsWhenAllowed)
{
auto& handle_ref = get_handle();
miopenHandle_t handle = &handle_ref;
ScopedFindDb no_cache; // disables find DB so FindCore / EvaluateInvokers always runs
ScopedEnvironment<bool> guard_naive(MIOPEN_NAIVE_DISABLE_IF_ALT, false);
auto solvers = RunFind(handle);
ASSERT_FALSE(solvers.empty()) << "miopenFindSolutions returned no results";
const bool any_naive = std::any_of(solvers.begin(), solvers.end(), IsNaive);
std::string all_names;
for(const auto& s : solvers)
all_names += (all_names.empty() ? "" : ", ") + s;
EXPECT_TRUE(any_naive)
<< "Expected at least one naive solver in results with MIOPEN_NAIVE_DISABLE_IF_ALT=0"
<< "; got: [" << all_names << "]";
}
// With MIOPEN_NAIVE_DISABLE_IF_ALT=1 and MIOPEN_DEBUG_FIND_ONLY_SOLVER restricting the candidate
// set to ConvDirectNaiveConvFwd, there are no non-naive solutions so defer_naive=false and the
// skip guard cannot fire (path B). Find must return a naive result rather than nothing.
TEST(GPU_NaiveDisableIfAlt_FP32, NaiveNotSuppressedWhenOnlySolver)
{
auto& handle_ref = get_handle();
miopenHandle_t handle = &handle_ref;
ScopedFindDb no_cache;
ScopedEnvironment<bool> guard_naive(MIOPEN_NAIVE_DISABLE_IF_ALT, true);
ScopedEnvironment<std::string> only_naive(MIOPEN_DEBUG_FIND_ONLY_SOLVER,
std::string{"ConvDirectNaiveConvFwd"});
auto solvers = RunFind(handle);
ASSERT_FALSE(solvers.empty())
<< "miopenFindSolutions returned no results: naive must not be suppressed when it is the "
"only applicable solver (path B)";
const bool all_naive = std::all_of(solvers.begin(), solvers.end(), IsNaive);
EXPECT_TRUE(all_naive)
<< "Expected only naive solvers when MIOPEN_DEBUG_FIND_ONLY_SOLVER=ConvDirectNaiveConvFwd";
}
// CPU-only: verify that MIOPEN_NAIVE_DISABLE_IF_ALT can be set and read back via the debug
// registry (the same path ScopedEnvironment uses in the GPU tests).
TEST(CPU_NaiveDisableIfAlt_NONE, EnvVarRoundTrips)
{
{
ScopedEnvironment<bool> guard(MIOPEN_NAIVE_DISABLE_IF_ALT, true);
EXPECT_TRUE(lib_env::value<bool>(MIOPEN_NAIVE_DISABLE_IF_ALT));
}
{
ScopedEnvironment<bool> guard(MIOPEN_NAIVE_DISABLE_IF_ALT, false);
EXPECT_FALSE(lib_env::value<bool>(MIOPEN_NAIVE_DISABLE_IF_ALT));
}
}