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
627 lines
28 KiB
C++
627 lines
28 KiB
C++
// Copyright © Advanced Micro Devices, Inc., or its affiliates.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#include <string>
|
|
#include <tuple>
|
|
#include <unordered_map>
|
|
#include <utility>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
// batchnorm::ProblemDescription
|
|
#include <miopen/batchnorm/problem_description.hpp>
|
|
#if MIOPEN_ENABLE_FIN_INTERFACE
|
|
#include <miopen/fin/fin_interface.hpp>
|
|
#endif
|
|
|
|
#include "get_handle.hpp"
|
|
#include "unit_conv_solver.hpp"
|
|
|
|
namespace {
|
|
|
|
struct TestParams
|
|
{
|
|
friend std::ostream& operator<<(std::ostream& os, const TestParams& /*tp*/)
|
|
{
|
|
os << "none";
|
|
return os;
|
|
}
|
|
};
|
|
|
|
struct SolverInfo
|
|
{
|
|
[[maybe_unused]] SolverInfo() = default;
|
|
|
|
SolverInfo(uint64_t id_, bool dynamic_, bool tunable_)
|
|
: id(id_), dynamic(dynamic_), tunable(tunable_)
|
|
{
|
|
}
|
|
|
|
friend std::ostream& operator<<(std::ostream& os, const SolverInfo& info)
|
|
{
|
|
os << "(";
|
|
os << "id:" << info.id;
|
|
os << ", dynamic:" << info.dynamic;
|
|
os << ", tunable:" << info.tunable;
|
|
os << ")";
|
|
return os;
|
|
}
|
|
|
|
uint64_t id;
|
|
bool dynamic;
|
|
bool tunable;
|
|
};
|
|
|
|
struct ConvSolverInfo : SolverInfo
|
|
{
|
|
using SolverInfo::SolverInfo;
|
|
ConvSolverInfo(uint64_t id_, bool dynamic_, bool tunable_, std::string algo_)
|
|
: SolverInfo(id_, dynamic_, tunable_), algo(std::move(algo_))
|
|
{
|
|
}
|
|
|
|
friend std::ostream& operator<<(std::ostream& os, const ConvSolverInfo& info)
|
|
{
|
|
os << "(";
|
|
os << static_cast<const SolverInfo&>(info);
|
|
os << ", algo:" << info.algo;
|
|
os << ")";
|
|
return os;
|
|
}
|
|
|
|
std::string algo;
|
|
};
|
|
|
|
using BatchNormSolverInfo = SolverInfo;
|
|
|
|
struct SolverConfig
|
|
{
|
|
SolverConfig() : empty(true) {}
|
|
SolverConfig(bool empty_) : empty(empty_) {}
|
|
|
|
bool empty;
|
|
};
|
|
|
|
struct ConvSolverConfig : SolverConfig, private miopen::unit_tests::ConvTestCase
|
|
{
|
|
ConvSolverConfig(miopen::conv::Direction direction_,
|
|
miopen::unit_tests::TensorDescriptorParams&& x,
|
|
miopen::unit_tests::TensorDescriptorParams&& w,
|
|
miopenDataType_t type_y,
|
|
miopen::unit_tests::ConvolutionDescriptorParams&& conv)
|
|
: SolverConfig(false),
|
|
miopen::unit_tests::ConvTestCase(std::move(x), std::move(w), type_y, std::move(conv)),
|
|
direction(direction_)
|
|
{
|
|
}
|
|
|
|
[[maybe_unused]] auto GetProblemDescription() const { return GetProblemDescription(direction); }
|
|
|
|
friend std::ostream& operator<<(std::ostream& os, const ConvSolverConfig& config)
|
|
{
|
|
os << "(";
|
|
if(config.empty)
|
|
{
|
|
os << "empty";
|
|
}
|
|
else
|
|
{
|
|
os << "direction:" << static_cast<int>(config.direction);
|
|
os << ", " << static_cast<const miopen::unit_tests::ConvTestCase&>(config);
|
|
}
|
|
os << ")";
|
|
return os;
|
|
}
|
|
|
|
private:
|
|
miopen::conv::Direction direction;
|
|
|
|
using miopen::unit_tests::ConvTestCase::GetProblemDescription;
|
|
using SolverConfig::SolverConfig;
|
|
};
|
|
|
|
struct BatchNormSolverConfig : SolverConfig
|
|
{
|
|
BatchNormSolverConfig(int dummy) : SolverConfig(false) { std::ignore = dummy; }
|
|
|
|
[[maybe_unused]] auto GetProblemDescription() const
|
|
{
|
|
return miopen::batchnorm::ProblemDescription{{}, {}, {}, {}, {}, {}, {}, {}};
|
|
}
|
|
|
|
friend std::ostream& operator<<(std::ostream& os, const BatchNormSolverConfig& config)
|
|
{
|
|
os << "(";
|
|
if(config.empty)
|
|
os << "empty";
|
|
else
|
|
os << "none";
|
|
os << ")";
|
|
return os;
|
|
}
|
|
|
|
using SolverConfig::SolverConfig;
|
|
};
|
|
|
|
template <class Info, class SolverConfig>
|
|
struct TestCase
|
|
{
|
|
friend std::ostream& operator<<(std::ostream& os, const TestCase& tc)
|
|
{
|
|
os << "(";
|
|
os << "name:" << tc.name;
|
|
os << ", info:" << tc.info;
|
|
os << ", config:" << tc.config;
|
|
os << ")";
|
|
return os;
|
|
}
|
|
|
|
std::string name;
|
|
Info info;
|
|
SolverConfig config;
|
|
};
|
|
|
|
using ConvTestCase = TestCase<ConvSolverInfo, ConvSolverConfig>;
|
|
using BatchNormTestCase = TestCase<BatchNormSolverInfo, BatchNormSolverConfig>;
|
|
|
|
const auto& GetTestParams()
|
|
{
|
|
static const auto params = TestParams{};
|
|
return params;
|
|
}
|
|
|
|
template <class SolverInfo>
|
|
const auto& GetSolversInfo();
|
|
|
|
template <>
|
|
const auto& GetSolversInfo<ConvSolverInfo>()
|
|
{
|
|
/// \anchor fin_interface_solver_info_coverage
|
|
// This is the initial list of solvers for testing the interface. At the time of its creation,
|
|
// it included all the available solvers. This was necessary to verify that all solvers were
|
|
// correctly added to the solver registry. There is no need to keep it up to date by adding new
|
|
// solvers as all new solvers will be added to the registry according to the existing template,
|
|
// and it won't improve test coverage (and will only waste extra time).
|
|
static const std::unordered_map<std::string, ConvSolverInfo> solver_info = {
|
|
// clang-format off
|
|
{"ConvAsm3x3U", {1, false, true, "miopenConvolutionFwdAlgoDirect"}},
|
|
{"ConvAsm1x1U", {2, false, true, "miopenConvolutionFwdAlgoDirect"}},
|
|
{"ConvAsm1x1UV2", {3, false, true, "miopenConvolutionFwdAlgoDirect"}},
|
|
{"ConvAsm5x10u2v2f1", {5, false, false, "miopenConvolutionFwdAlgoDirect"}},
|
|
{"ConvAsm5x10u2v2b1", {6, false, false, "miopenConvolutionFwdAlgoDirect"}},
|
|
{"ConvAsm7x7c3h224w224k64u2v2p3q3f1", {7, false, false, "miopenConvolutionFwdAlgoDirect"}},
|
|
{"ConvHipDirectFwd11x11", {8, false, false, "miopenConvolutionFwdAlgoDirect"}},
|
|
{"ConvHipDirectFwd", {11, false, true, "miopenConvolutionFwdAlgoDirect"}},
|
|
{"ConvBinWinograd3x3U", {14, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvBinWinogradRxS", {15, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvAsmBwdWrW3x3", {16, false, true, "miopenConvolutionFwdAlgoDirect"}},
|
|
{"ConvAsmBwdWrW1x1", {17, false, true, "miopenConvolutionFwdAlgoDirect"}},
|
|
{"ConvOclBwdWrW53", {24, false, false, "miopenConvolutionFwdAlgoDirect"}},
|
|
{"ConvHipImplicitGemmV4R1Fwd", {26, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvHipImplicitGemmV4R1WrW", {31, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"fft", {34, false, false, "miopenConvolutionFwdAlgoFFT"}},
|
|
{"ConvWinograd3x3MultipassWrW<3-4>", {35, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvBinWinogradRxSf3x2", {37, true, true, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvWinograd3x3MultipassWrW<3-5>", {38, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvWinograd3x3MultipassWrW<3-6>", {39, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvWinograd3x3MultipassWrW<3-2>", {40, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvWinograd3x3MultipassWrW<3-3>", {41, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvWinograd3x3MultipassWrW<7-2>", {42, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvWinograd3x3MultipassWrW<7-3>", {43, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvWinograd3x3MultipassWrW<7-2-1-1>", {44, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvWinograd3x3MultipassWrW<7-3-1-1>", {45, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvWinograd3x3MultipassWrW<1-1-7-2>", {46, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvWinograd3x3MultipassWrW<1-1-7-3>", {47, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvWinograd3x3MultipassWrW<5-3>", {48, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvWinograd3x3MultipassWrW<5-4>", {49, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvBinWinogradRxSf2x3", {53, true, true, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvHipImplicitGemmV4R4Fwd", {54, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvHipImplicitGemmBwdDataV1R1", {55, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvHipImplicitGemmBwdDataV4R1", {56, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvHipImplicitGemmBwdDataV1R1Xdlops", {57, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvHipImplicitGemmBwdDataV4R1Xdlops", {60, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvHipImplicitGemmV4R4WrW", {61, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvAsmImplicitGemmV4R1DynamicFwd", {62, true, false, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvAsmImplicitGemmV4R1DynamicFwd_1x1", {63, true, false, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvHipImplicitGemmForwardV4R4Xdlops", {64, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvAsmImplicitGemmV4R1DynamicBwd", {65, true, false, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvAsmImplicitGemmV4R1DynamicWrw", {66, true, false, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvMPBidirectWinograd<2-3>", {67, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvMPBidirectWinograd<3-3>", {68, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvMPBidirectWinograd<4-3>", {69, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvMPBidirectWinograd<5-3>", {70, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvMPBidirectWinograd<6-3>", {71, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvAsmImplicitGemmGTCDynamicWrwXdlops", {72, true, false, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvHipImplicitGemmWrwV4R4Xdlops", {73, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvAsmImplicitGemmGTCDynamicFwdXdlops", {74, true, false, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvMPBidirectWinograd_xdlops<2-3>", {75, false, true, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvMPBidirectWinograd_xdlops<3-3>", {76, false, true, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvMPBidirectWinograd_xdlops<4-3>", {77, false, true, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvMPBidirectWinograd_xdlops<5-3>", {78, false, true, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvMPBidirectWinograd_xdlops<6-3>", {79, false, true, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvHipImplicitGemmForwardV4R5Xdlops", {80, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvHipImplicitGemmForwardV4R4Xdlops_Padded_Gemm", {81, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvAsmImplicitGemmGTCDynamicBwdXdlops", {82, true, false, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvHipImplicitGemmWrwV4R4Xdlops_Padded_Gemm", {83, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvBinWinogradRxSf2x3g1", {84, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvDirectNaiveConvFwd", {85, true, false, "miopenConvolutionFwdAlgoDirect"}},
|
|
{"ConvDirectNaiveConvBwd", {86, true, false, "miopenConvolutionFwdAlgoDirect"}},
|
|
{"ConvDirectNaiveConvWrw", {87, true, false, "miopenConvolutionFwdAlgoDirect"}},
|
|
{"GemmFwd1x1_0_1", {88, true, false, "miopenConvolutionFwdAlgoGEMM"}},
|
|
{"GemmFwd1x1_0_1_int8", {89, true, false, "miopenConvolutionFwdAlgoGEMM"}},
|
|
{"GemmFwd1x1_0_2", {90, true, false, "miopenConvolutionFwdAlgoGEMM"}},
|
|
{"GemmFwdRest", {91, true, false, "miopenConvolutionFwdAlgoGEMM"}},
|
|
{"GemmBwd1x1_stride2", {95, true, false, "miopenConvolutionFwdAlgoGEMM"}},
|
|
{"GemmBwd1x1_stride1", {96, true, false, "miopenConvolutionFwdAlgoGEMM"}},
|
|
{"GemmBwdRest", {97, true, false, "miopenConvolutionFwdAlgoGEMM"}},
|
|
{"ConvMlirIgemmFwd", {98, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvMlirIgemmBwd", {99, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvMlirIgemmWrW", {100, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"GemmWrw1x1_stride1", {101, true, false, "miopenConvolutionFwdAlgoGEMM"}},
|
|
{"GemmWrwUniversal", {102, true, false, "miopenConvolutionFwdAlgoGEMM"}},
|
|
{"ConvMlirIgemmFwdXdlops", {103, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvMlirIgemmBwdXdlops", {104, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvMlirIgemmWrWXdlops", {105, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvAsmImplicitGemmGTCDynamicFwdXdlopsNHWC", {107, true, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvAsmImplicitGemmGTCDynamicBwdXdlopsNHWC", {108, true, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvAsmImplicitGemmGTCDynamicWrwXdlopsNHWC", {110, true, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvCkIgemmFwdV6r1DlopsNchw", {114, false, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvAsmImplicitGemmGTCDynamicFwdDlopsNCHWC", {127, true, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvHipImplicitGemmGroupFwdXdlops", {137, true, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvHipImplicitGemm3DGroupFwdXdlops", {138, true, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvWinoFuryRxS<2-3>", {139, true, false, "miopenConvolutionFwdAlgoWinograd"}},
|
|
{"ConvHipImplicitGemm3DGroupWrwXdlops", {140, true, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvHipImplicitGemm3DGroupBwdXdlops", {141, true, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvHipImplicitGemmGroupBwdXdlops", {155, true, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
{"ConvHipImplicitGemmGroupWrwXdlops", {156, true, true, "miopenConvolutionFwdAlgoImplicitGEMM"}},
|
|
// clang-format on
|
|
};
|
|
|
|
return solver_info;
|
|
}
|
|
|
|
template <>
|
|
const auto& GetSolversInfo<BatchNormSolverInfo>()
|
|
{
|
|
/// \ref fin_interface_solver_info_coverage
|
|
static const std::unordered_map<std::string, BatchNormSolverInfo> solver_info = {
|
|
// clang-format off
|
|
// solver-name id, isDynamic, isTunable
|
|
{"BnFwdTrainingSpatial", {113, false, true}},
|
|
{"BnFwdTrainingPerActivation", {116, false, false}},
|
|
{"BnBwdTrainingSpatial", {117, false, true}},
|
|
{"BnBwdTrainingPerActivation", {119, false, false}},
|
|
{"BnFwdInference", {120, true, false}},
|
|
// clang-format on
|
|
};
|
|
|
|
return solver_info;
|
|
}
|
|
|
|
template <class SolverConfig>
|
|
const auto& GetSolverConfigs();
|
|
|
|
template <>
|
|
const auto& GetSolverConfigs<ConvSolverConfig>()
|
|
{
|
|
/// \anchor fin_interface_solver_config_coverage
|
|
// This list should include solvers that allow testing the core functionality, such as tunable
|
|
// and non-tunable solvers. There's no need to add all solvers here, as it won't improve test
|
|
// coverage (and will only waste extra time).
|
|
static const std::unordered_map<std::string, ConvSolverConfig> configs = {
|
|
// clang-format off
|
|
// Non-tunable solvers
|
|
{"ConvDirectNaiveConvFwd", {miopen::conv::Direction::Forward, {miopenFloat, {1, 16, 14, 14}}, {miopenFloat, {48, 16, 5, 5}}, miopenFloat, {{2, 2}, {1, 1}, {1, 1}}}},
|
|
{"ConvDirectNaiveConvBwd", {miopen::conv::Direction::BackwardData, {miopenFloat, {1, 16, 14, 14}}, {miopenFloat, {48, 16, 5, 5}}, miopenFloat, {{2, 2}, {1, 1}, {1, 1}}}},
|
|
{"ConvDirectNaiveConvWrw", {miopen::conv::Direction::BackwardWeights, {miopenFloat, {1, 16, 14, 14}}, {miopenFloat, {48, 16, 5, 5}}, miopenFloat, {{2, 2}, {1, 1}, {1, 1}}}},
|
|
// Tunable solvers
|
|
{"ConvBinWinogradRxSf3x2", {miopen::conv::Direction::Forward, {miopenFloat, {1, 20, 20, 20}}, {miopenFloat, {20, 20, 3, 3}}, miopenFloat, {{1, 1}, {1, 1}, {1, 1}}}},
|
|
{"ConvBinWinogradRxSf2x3", {miopen::conv::Direction::BackwardWeights, {miopenFloat, {1, 20, 20, 20}}, {miopenFloat, {20, 20, 3, 3}}, miopenFloat, {{1, 1}, {1, 1}, {1, 1}}}},
|
|
// clang-format on
|
|
};
|
|
|
|
return configs;
|
|
}
|
|
|
|
template <>
|
|
const auto& GetSolverConfigs<BatchNormSolverConfig>()
|
|
{
|
|
/// \ref fin_interface_solver_config_coverage
|
|
static const std::unordered_map<std::string, BatchNormSolverConfig> configs = {
|
|
// clang-format off
|
|
/// \todo add configs
|
|
{"DummySolver", {42}},
|
|
// clang-format on
|
|
};
|
|
|
|
return configs;
|
|
}
|
|
|
|
template <class TestCase>
|
|
const auto GetTestCases()
|
|
{
|
|
std::vector<TestCase> test_cases;
|
|
const auto& sinfo = GetSolversInfo<decltype(std::declval<TestCase>().info)>();
|
|
const auto& configs = GetSolverConfigs<decltype(std::declval<TestCase>().config)>();
|
|
test_cases.reserve(sinfo.size());
|
|
for(const auto& s : sinfo)
|
|
{
|
|
const auto& config = configs.find(s.first);
|
|
if(config == configs.end())
|
|
test_cases.emplace_back(TestCase{s.first, s.second, {}});
|
|
else
|
|
test_cases.emplace_back(TestCase{s.first, s.second, config->second});
|
|
}
|
|
return std::move(test_cases);
|
|
}
|
|
|
|
#if MIOPEN_ENABLE_FIN_INTERFACE
|
|
|
|
template <class SolverInfo>
|
|
const auto& GetSolverNames()
|
|
{
|
|
static const auto names = [] {
|
|
std::vector<std::string> names_;
|
|
const auto& sinfo = GetSolversInfo<SolverInfo>();
|
|
names_.reserve(sinfo.size());
|
|
for(const auto& s : sinfo)
|
|
names_.push_back(s.first);
|
|
return names_;
|
|
}();
|
|
return names;
|
|
}
|
|
|
|
// Context
|
|
template <class Problem>
|
|
auto GetContext(miopen::Handle* handle, const Problem& problem);
|
|
|
|
template <>
|
|
miopen::ExecutionContext GetContext(miopen::Handle* handle,
|
|
const miopen::conv::ProblemDescription& problem)
|
|
{
|
|
miopen::ExecutionContext tmp{handle};
|
|
problem.SetupFloats(tmp);
|
|
problem.SetupComputeType(tmp);
|
|
return tmp;
|
|
}
|
|
|
|
template <>
|
|
auto GetContext(miopen::Handle* handle, const miopen::batchnorm::ProblemDescription&)
|
|
{
|
|
auto tmp = miopen::ExecutionContext{handle};
|
|
return tmp;
|
|
}
|
|
|
|
// Checks
|
|
template <class Solver, class SolverInfo>
|
|
void CheckSolverInfo(const Solver& solver, const SolverInfo& info)
|
|
{
|
|
ASSERT_EQ(solver.GetId(), info.id);
|
|
ASSERT_EQ(solver.IsDynamic(), info.dynamic);
|
|
ASSERT_EQ(solver.IsTunable(), info.tunable);
|
|
if constexpr(std::is_same_v<Solver, miopen::fin_interface::ConvSolver>)
|
|
ASSERT_EQ(solver.GetAlgo(miopen::conv::Direction::Forward), info.algo);
|
|
}
|
|
|
|
template <class Solver, class SolverConfig>
|
|
void CheckSolverConfig(const Solver& solver, const SolverConfig& config)
|
|
{
|
|
auto&& handle = get_handle();
|
|
const auto problem = config.GetProblemDescription();
|
|
const auto ctx = GetContext(&handle, problem);
|
|
auto db = miopen::GetDb(ctx);
|
|
|
|
ASSERT_TRUE(solver.IsApplicable(ctx, problem));
|
|
std::ignore = solver.GetWorkspaceSize(ctx, problem);
|
|
|
|
/// \todo test FindSolution()
|
|
|
|
const auto solutions = solver.GetAllSolutions(ctx, problem);
|
|
ASSERT_GT(solutions.size(), 0);
|
|
|
|
const auto pcfg_params = solver.GetPerfCfgParams(ctx, problem, db);
|
|
ASSERT_NE(pcfg_params.empty(), solver.IsTunable());
|
|
|
|
ASSERT_EQ(solver.TestPerfCfgParams(ctx, problem, pcfg_params), solver.IsTunable());
|
|
}
|
|
|
|
template <class Solver, class TestCase>
|
|
void CheckSolver(const Solver& solver, const TestCase& test_case)
|
|
{
|
|
ASSERT_EQ(solver.GetName(), test_case.name);
|
|
ASSERT_EQ(solver.IsValid(), true);
|
|
ASSERT_NO_FATAL_FAILURE(CheckSolverInfo(solver, test_case.info));
|
|
if(!test_case.config.empty)
|
|
ASSERT_NO_FATAL_FAILURE(CheckSolverConfig(solver, test_case.config));
|
|
}
|
|
|
|
// GetAll*Solvers()
|
|
template <class TestCase>
|
|
const auto& InterfaceGetAllSolvers();
|
|
|
|
template <>
|
|
const auto& InterfaceGetAllSolvers<ConvTestCase>()
|
|
{
|
|
return miopen::fin_interface::GetAllConvSolvers();
|
|
}
|
|
|
|
template <>
|
|
const auto& InterfaceGetAllSolvers<BatchNormTestCase>()
|
|
{
|
|
return miopen::fin_interface::GetAllBatchNormSolvers();
|
|
}
|
|
|
|
// Get*Solvers(names)
|
|
template <class TestCase>
|
|
const auto InterfaceGetSolvers(const std::vector<std::string>& names);
|
|
|
|
template <>
|
|
const auto InterfaceGetSolvers<ConvTestCase>(const std::vector<std::string>& names)
|
|
{
|
|
return miopen::fin_interface::GetConvSolvers(names);
|
|
}
|
|
|
|
template <>
|
|
const auto InterfaceGetSolvers<BatchNormTestCase>(const std::vector<std::string>& names)
|
|
{
|
|
return miopen::fin_interface::GetBatchNormSolvers(names);
|
|
}
|
|
|
|
// Get*Solver(name)
|
|
template <class TestCase>
|
|
auto InterfaceGetSolver(const std::string& name);
|
|
|
|
template <>
|
|
auto InterfaceGetSolver<ConvTestCase>(const std::string& name)
|
|
{
|
|
return miopen::fin_interface::GetConvSolver(name);
|
|
}
|
|
|
|
template <>
|
|
auto InterfaceGetSolver<BatchNormTestCase>(const std::string& name)
|
|
{
|
|
return miopen::fin_interface::GetBatchNormSolver(name);
|
|
}
|
|
|
|
#endif // MIOPEN_ENABLE_FIN_INTERFACE
|
|
|
|
// Tests
|
|
template <class TestCase>
|
|
class TestGetAllSolvers : public ::testing::TestWithParam<TestParams>
|
|
{
|
|
public:
|
|
void RunTest()
|
|
{
|
|
#if MIOPEN_ENABLE_FIN_INTERFACE
|
|
const auto& solvers = InterfaceGetAllSolvers<TestCase>();
|
|
const auto& solvers_info = GetSolversInfo<decltype(std::declval<TestCase>().info)>();
|
|
|
|
std::size_t num_checked_solvers = 0;
|
|
for(const auto& solver : solvers)
|
|
{
|
|
const auto& name = solver.GetName();
|
|
const auto& solver_info = solvers_info.find(name);
|
|
if(solver_info == solvers_info.end())
|
|
continue;
|
|
ASSERT_NO_FATAL_FAILURE(CheckSolverInfo(solver, solver_info->second));
|
|
num_checked_solvers++;
|
|
}
|
|
ASSERT_EQ(num_checked_solvers, solvers_info.size());
|
|
#endif // MIOPEN_ENABLE_FIN_INTERFACE
|
|
}
|
|
|
|
protected:
|
|
void SetUp() override
|
|
{
|
|
#if !MIOPEN_ENABLE_FIN_INTERFACE
|
|
GTEST_SKIP();
|
|
#endif // !MIOPEN_ENABLE_FIN_INTERFACE
|
|
}
|
|
};
|
|
|
|
template <class TestCase>
|
|
class TestGetSolvers : public ::testing::TestWithParam<TestParams>
|
|
{
|
|
public:
|
|
void RunTest()
|
|
{
|
|
#if MIOPEN_ENABLE_FIN_INTERFACE
|
|
const auto& solvers_info = GetSolversInfo<decltype(std::declval<TestCase>().info)>();
|
|
const auto& names = GetSolverNames<decltype(std::declval<TestCase>().info)>();
|
|
const auto solvers = InterfaceGetSolvers<TestCase>(names);
|
|
|
|
ASSERT_EQ(solvers.size(), names.size());
|
|
for(const auto& solver : solvers)
|
|
{
|
|
const auto& name = solver.GetName();
|
|
const auto& solver_info = solvers_info.find(name);
|
|
if(solver_info == solvers_info.end())
|
|
{
|
|
const std::string error = name + " not found";
|
|
GTEST_FAIL() << error;
|
|
}
|
|
ASSERT_NO_FATAL_FAILURE(CheckSolver(solver, TestCase{name, solver_info->second, {}}));
|
|
}
|
|
#endif // MIOPEN_ENABLE_FIN_INTERFACE
|
|
}
|
|
|
|
protected:
|
|
void SetUp() override
|
|
{
|
|
#if !MIOPEN_ENABLE_FIN_INTERFACE
|
|
GTEST_SKIP();
|
|
#endif // !MIOPEN_ENABLE_FIN_INTERFACE
|
|
}
|
|
};
|
|
|
|
template <class TestCase>
|
|
class TestGetSolver : public ::testing::TestWithParam<std::tuple<TestParams, TestCase>>
|
|
{
|
|
public:
|
|
void RunTest()
|
|
{
|
|
#if MIOPEN_ENABLE_FIN_INTERFACE
|
|
TestCase test_case;
|
|
std::tie(std::ignore, test_case) = this->GetParam();
|
|
const auto solver = InterfaceGetSolver<TestCase>(test_case.name);
|
|
CheckSolver(solver, test_case);
|
|
#endif // MIOPEN_ENABLE_FIN_INTERFACE
|
|
}
|
|
|
|
protected:
|
|
void SetUp() override
|
|
{
|
|
#if !MIOPEN_ENABLE_FIN_INTERFACE
|
|
GTEST_SKIP();
|
|
#endif // !MIOPEN_ENABLE_FIN_INTERFACE
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
// Convolution
|
|
using CPU_FinInterfaceTestGetAllConvSolvers_NONE = TestGetAllSolvers<ConvTestCase>;
|
|
using CPU_FinInterfaceTestGetConvSolvers_NONE = TestGetSolvers<ConvTestCase>;
|
|
using GPU_FinInterfaceTestGetConvSolver_FP32 = TestGetSolver<ConvTestCase>;
|
|
|
|
TEST_P(CPU_FinInterfaceTestGetAllConvSolvers_NONE, FinInterface) { this->RunTest(); };
|
|
TEST_P(CPU_FinInterfaceTestGetConvSolvers_NONE, FinInterface) { this->RunTest(); };
|
|
TEST_P(GPU_FinInterfaceTestGetConvSolver_FP32, FinInterface) { this->RunTest(); };
|
|
|
|
INSTANTIATE_TEST_SUITE_P(Full,
|
|
CPU_FinInterfaceTestGetAllConvSolvers_NONE,
|
|
testing::Values(GetTestParams()));
|
|
|
|
INSTANTIATE_TEST_SUITE_P(Full,
|
|
CPU_FinInterfaceTestGetConvSolvers_NONE,
|
|
testing::Values(GetTestParams()));
|
|
|
|
INSTANTIATE_TEST_SUITE_P(Full,
|
|
GPU_FinInterfaceTestGetConvSolver_FP32,
|
|
testing::Combine(testing::Values(GetTestParams()),
|
|
testing::ValuesIn(GetTestCases<ConvTestCase>())));
|
|
|
|
// Batch normalization
|
|
using CPU_FinInterfaceTestGetAllBatchNormSolvers_NONE = TestGetAllSolvers<BatchNormTestCase>;
|
|
using CPU_FinInterfaceTestGetBatchNormSolvers_NONE = TestGetSolvers<BatchNormTestCase>;
|
|
using GPU_FinInterfaceTestGetBatchNormSolver_FP32 = TestGetSolver<BatchNormTestCase>;
|
|
|
|
TEST_P(CPU_FinInterfaceTestGetAllBatchNormSolvers_NONE, FinInterface) { this->RunTest(); };
|
|
TEST_P(CPU_FinInterfaceTestGetBatchNormSolvers_NONE, FinInterface) { this->RunTest(); };
|
|
TEST_P(GPU_FinInterfaceTestGetBatchNormSolver_FP32, FinInterface) { this->RunTest(); };
|
|
|
|
INSTANTIATE_TEST_SUITE_P(Full,
|
|
CPU_FinInterfaceTestGetAllBatchNormSolvers_NONE,
|
|
testing::Values(GetTestParams()));
|
|
|
|
INSTANTIATE_TEST_SUITE_P(Full,
|
|
CPU_FinInterfaceTestGetBatchNormSolvers_NONE,
|
|
testing::Values(GetTestParams()));
|
|
|
|
// clang-format off
|
|
INSTANTIATE_TEST_SUITE_P(Full,
|
|
GPU_FinInterfaceTestGetBatchNormSolver_FP32,
|
|
testing::Combine(testing::Values(GetTestParams()),
|
|
testing::ValuesIn(GetTestCases<BatchNormTestCase>())));
|
|
// clang-format on
|