/******************************************************************************* * * MIT License * * Copyright (C) 2019-2022 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * *******************************************************************************/ #include #include #include #include #include #include #include #include using namespace Tensile; TEST(ContractionSelectionLibraryTest, Single) { std::shared_ptr hardware = std::make_shared( AMDGPU::Processor::gfx900, 64, 0, "AMD Radeon Vega Frontier Edition"); SingleContractionLibrary lib; lib.solution = std::make_shared(); auto problem = std::make_shared(); EXPECT_EQ(lib.findBestSolution(*problem, *hardware), lib.solution); } TEST(ContractionSelectionLibraryTest, GPUSelection) { std::shared_ptr v10 = std::make_shared( AMDGPU::Processor::gfx900, 64, 0, "AMD Radeon Vega Frontier Edition"); std::shared_ptr v20 = std::make_shared(AMDGPU::Processor::gfx906, 60, 0, "AMD Radeon Vega 7"); std::shared_ptr v20_64CU = std::make_shared(AMDGPU::Processor::gfx906, 64, 0, "AMD Radeon Vega 7"); // Create solutions auto v20Solution = std::make_shared(); auto v20Solution_64CU = std::make_shared(); auto genericSolution = std::make_shared(); // Create libraries std::shared_ptr v20Lib = std::make_shared(v20Solution); std::shared_ptr v20Lib_64CU = std::make_shared(v20Solution_64CU); auto genericLib = std::make_shared(genericSolution); // Create hardware predicate for a generic "V20" auto isV20 = std::make_shared(AMDGPU::Processor::gfx906); std::shared_ptr> isAMDGPUV20 = std::make_shared>(isV20); HardwarePredicate hardwareIsAMDGPUV20(isAMDGPUV20); // Create hardware predicate for a "V20" with 64 CU std::shared_ptr> isV20Proc = std::make_shared(AMDGPU::Processor::gfx906); std::shared_ptr> is64CU = std::make_shared(64); std::shared_ptr> isAMDGPUV20_64CU = std::make_shared>( std::initializer_list>>{isV20Proc, is64CU}); HardwarePredicate hardwareIsAMDGPUV20_64CU( std::make_shared>(isAMDGPUV20_64CU)); // Create hierarchy for hardware selection ContractionHardwareSelectionLibrary::Row v20Row(hardwareIsAMDGPUV20, v20Lib); ContractionHardwareSelectionLibrary::Row v20Row_64CU(hardwareIsAMDGPUV20_64CU, v20Lib_64CU); ContractionHardwareSelectionLibrary lib({v20Row_64CU, v20Row}); auto problem = std::make_shared(); EXPECT_EQ(lib.findBestSolution(*problem, *v20), v20Solution); EXPECT_EQ(lib.findBestSolution(*problem, *v20_64CU), v20Solution_64CU); EXPECT_EQ(lib.findBestSolution(*problem, *v10), std::shared_ptr()); HardwarePredicate allHardware(std::make_shared>()); lib.rows.push_back(std::make_pair(allHardware, genericLib)); EXPECT_EQ(lib.findBestSolution(*problem, *v20), v20Solution); EXPECT_EQ(lib.findBestSolution(*problem, *v20_64CU), v20Solution_64CU); EXPECT_EQ(lib.findBestSolution(*problem, *v10), genericSolution); } TEST(ContractionSelectionLibraryTest, RegionSelection) { // Create solutions auto region1Solution = std::make_shared(); auto region2Solution = std::make_shared(); auto genericSolution = std::make_shared(); // Create libraries auto region1Lib = std::make_shared(region1Solution); auto region2Lib = std::make_shared(region2Solution); auto genericLib = std::make_shared(genericSolution); // Create region predicate for (6000 <= M < 8000), (0 <= N < 7000) using Predicate = Predicates::Predicate; using SizeInRange = Predicates::Contraction::SizeInRange; using Range = Predicates::Contraction::Range; using And = Predicates::And; size_t max_size = std::numeric_limits::max(); std::shared_ptr regionM = std::make_shared(0, Range{6000, 8000}); std::shared_ptr regionN1 = std::make_shared(1, Range{0, 7000}); std::shared_ptr regionN2 = std::make_shared(1, Range{7000, max_size}); // Create region predicate for (6000 <= M < 8000), (0 <= N < 7000) auto preds1 = {regionM, regionN1}; auto isRegion1 = std::make_shared(preds1); // Create region predicate for (6000 <= M < 8000), (7000 <= N < max) auto preds2 = {regionM, regionN2}; auto isRegion2 = std::make_shared(preds2); // Create fallthrough predicate (i.e. default) ContractionProblemPredicate allProbs(std::make_shared>()); // Create hierarchy for region selection ContractionProblemSelectionLibrary::Row Region1Row(isRegion1, region1Lib); ContractionProblemSelectionLibrary::Row Region2Row(isRegion2, region2Lib); ContractionProblemSelectionLibrary::Row GenericRow(allProbs, genericLib); ContractionProblemSelectionLibrary lib({Region1Row, Region2Row, GenericRow}); auto Region1Problem = ContractionProblem::GEMM(false, false, 7000, 6500, 1000, 7000, 1000, 7000, 1.0, false, 1); auto Region2Problem = ContractionProblem::GEMM(false, false, 7000, 7500, 1000, 7000, 1000, 7000, 1.0, false, 1); auto OutRegionProblem = ContractionProblem::GEMM(false, false, 5000, 2000, 1000, 5000, 1000, 5000, 1.0, false, 1); AMDGPU gpu; EXPECT_EQ(lib.findBestSolution(Region1Problem, gpu), region1Solution); EXPECT_EQ(lib.findBestSolution(Region2Problem, gpu), region2Solution); EXPECT_EQ(lib.findBestSolution(OutRegionProblem, gpu), genericSolution); } TEST(ContractionSelectionLibraryTest, TransposeSelection) { auto NNSolution = std::make_shared(); auto NTSolution = std::make_shared(); auto TNSolution = std::make_shared(); auto TTSolution = std::make_shared(); NNSolution->index = 0; NTSolution->index = 1; TNSolution->index = 2; TTSolution->index = 3; SolutionMap map( {{0, NNSolution}, {1, NTSolution}, {2, TNSolution}, {3, TTSolution}}); std::shared_ptr NNLibrary = std::make_shared(NNSolution); std::shared_ptr NTLibrary = std::make_shared(NTSolution); std::shared_ptr TNLibrary = std::make_shared(TNSolution); std::shared_ptr TTLibrary = std::make_shared(TTSolution); auto lib = std::make_shared(); lib->property = std::make_shared(); lib->map["Contraction_l_Ailk_Bljk_Cijk_Dijk"] = NNLibrary; lib->map["Contraction_l_Ailk_Bjlk_Cijk_Dijk"] = NTLibrary; lib->map["Contraction_l_Alik_Bljk_Cijk_Dijk"] = TNLibrary; lib->map["Contraction_l_Alik_Bjlk_Cijk_Dijk"] = TTLibrary; AMDGPU gpu; auto NNProblem = ContractionProblem::GEMM(false, false, 4, 4, 4, 4, 4, 4, 1.2, false, 1); auto NTProblem = ContractionProblem::GEMM(false, true, 4, 4, 4, 4, 4, 4, 1.2, false, 1); auto TNProblem = ContractionProblem::GEMM(true, false, 4, 4, 4, 4, 4, 4, 1.2, false, 1); auto TTProblem = ContractionProblem::GEMM(true, true, 4, 4, 4, 4, 4, 4, 1.2, false, 1); // auto WeirdProblemC = ContractionProblem::FromBLAS( true, true, 4,4,4, // 4,4,4, false, false, 1); WeirdProblemC.c.transpose(0,1); // auto WeirdProblemD = ContractionProblem::FromBLAS( true, true, 4,4,4, // 4,4,4, false, false, 1); WeirdProblemD.d.transpose(0,1); EXPECT_EQ(lib->findBestSolution(NNProblem, gpu), NNSolution); EXPECT_EQ(lib->findBestSolution(NTProblem, gpu), NTSolution); EXPECT_EQ(lib->findBestSolution(TNProblem, gpu), TNSolution); EXPECT_EQ(lib->findBestSolution(TTProblem, gpu), TTSolution); // EXPECT_EQ(lib->findBestSolution(WeirdProblemC, gpu), nullptr); // EXPECT_EQ(lib->findBestSolution(WeirdProblemD, gpu), nullptr); MasterContractionLibrary mlib; mlib.solutions = map; mlib.library = lib; }