/******************************************************************************* * * MIT License * * Copyright (C) 2022-2023 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. * *******************************************************************************/ #pragma once #include #include #include #include namespace TensileLite { /** * \ingroup SolutionLibrary */ template using LibraryMap = std::unordered_map>; /** * \ingroup SolutionLibrary * * Represents a set of solutions where each problem can map to only one * sub-library, as opposed to an `ExactLogicLibrary` where fall-through can * occur. * * Example: Problem type: Number of dimensions, transposes, etc. */ template struct ProblemMapLibrary : public SolutionLibrary { static std::string Type() { return "ProblemMap"; } virtual std::string type() const override { return Type(); } virtual std::string description() const override { if(property == nullptr) { return concatenate(type(), " (property: nullptr, ", map.size(), " rows)"); } else { return concatenate( type(), " (property: ", property->toString(), ", ", map.size(), " rows)"); } } LibraryEntry lookup(MyProblem const& problem, Hardware const& hardware) const { auto key = (*property)(problem); auto iter = map.find(key); bool debug = Debug::Instance().printPropertyEvaluation(); if(debug) { if(iter == map.end()) { std::cout << "[ProblemMap] No match for: " << key << std::endl; std::cout << " Available problem types:" << std::endl; for(auto const& pair : map) { std::cout << " - " << pair.first << std::endl; } } else { std::cout << "[ProblemMap] Matched: " << key << std::endl; } } if(iter == map.end()) return nullptr; return iter->second; } virtual std::shared_ptr getSolutionByIndex(MyProblem const& problem, Hardware const& hardware, const int index) const override { auto library = lookup(problem, hardware); if(library == nullptr) return std::shared_ptr(); return library->getSolutionByIndex(problem, hardware, index); } virtual std::shared_ptr findBestSolution(MyProblem const& problem, Hardware const& hardware, double* fitness = nullptr) const override { auto library = lookup(problem, hardware); if(library == nullptr) return std::shared_ptr(); return library->findBestSolution(problem, hardware, fitness); } virtual SolutionSet findAllSolutions(MyProblem const& problem, Hardware const& hardware, SolutionLibrarySearchType searchType = SolutionLibrarySearchType::DEFAULT) const override { if(searchType == SolutionLibrarySearchType::HARDWARE_ONLY) { auto result = SolutionSet(); for(auto& pair : map) { auto library = pair.second; if(library == nullptr) continue; auto solutions = library->findAllSolutions(problem, hardware, searchType); result.insert(solutions.begin(), solutions.end()); } return result; } auto library = lookup(problem, hardware); if(library == nullptr) return SolutionSet(); return library->findAllSolutions(problem, hardware, searchType); } virtual SolutionSet findAllSolutionsGroupedGemm(std::vector const& problems, Hardware const& hardware, SolutionLibrarySearchType searchType = SolutionLibrarySearchType::DEFAULT) const override { if(searchType == SolutionLibrarySearchType::HARDWARE_ONLY) { auto result = SolutionSet(); for(auto& pair : map) { auto library = pair.second; if(library == nullptr) continue; auto solutions = library->findAllSolutionsGroupedGemm(problems, hardware, searchType); result.insert(solutions.begin(), solutions.end()); } return result; } auto library = lookup(problems[0], hardware); if(library == nullptr) return SolutionSet(); return library->findAllSolutionsGroupedGemm(problems, hardware, searchType); } std::shared_ptr> property; LibraryMap map; mutable std::atomic lastFindTopRetAll = false; virtual SolutionVector findTopSolutions(MyProblem const& problem, Hardware const& hardware, int numSolutions) const override { // false in case of early return lastFindTopRetAll = false; auto library = lookup(problem, hardware); if(library == nullptr) return SolutionVector(); const auto& rv = library->findTopSolutions(problem, hardware, numSolutions); lastFindTopRetAll = library->lastFindTopAlreadyRetAll(); return rv; } virtual bool lastFindTopAlreadyRetAll() const override { return lastFindTopRetAll; } virtual SolutionVector findTopSolutionsGroupedGemm(std::vector const& problems, Hardware const& hardware, int numSolutions) const override { auto library = lookup(problems[0], hardware); if(library == nullptr) return SolutionVector(); return library->findTopSolutionsGroupedGemm(problems, hardware, numSolutions); } }; } // namespace TensileLite