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
3189 lines
119 KiB
C++
Executable File
3189 lines
119 KiB
C++
Executable File
/*******************************************************************************
|
|
*
|
|
* MIT License
|
|
*
|
|
* Copyright (C) 2022-2026 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 <Tensile/ContractionProblem.hpp>
|
|
#include <Tensile/ContractionSolution.hpp>
|
|
#include <Tensile/KernelLanguageTypes.hpp>
|
|
#include <Tensile/PredicateDebugger.hpp>
|
|
#include <Tensile/Predicates.hpp>
|
|
|
|
#include <Tensile/AMDGPU.hpp>
|
|
#include <Tensile/hip/HipHardware.hpp>
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <cmath>
|
|
#include <cstddef>
|
|
#include <limits>
|
|
#include <sstream>
|
|
#include <vector>
|
|
|
|
#include <tensilelitehost/export.h>
|
|
|
|
namespace TensileLite
|
|
{
|
|
namespace Predicates
|
|
{
|
|
/**
|
|
* \addtogroup Predicates
|
|
* @{
|
|
*/
|
|
/**
|
|
* @brief ContractionProblemGemm predicates
|
|
*/
|
|
namespace Contraction
|
|
{
|
|
struct Free0SizeMultiple
|
|
: public Predicate_CRTP<Free0SizeMultiple, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
size_t value;
|
|
|
|
Free0SizeMultiple() = default;
|
|
Free0SizeMultiple(size_t index, size_t value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "Free0SizeMultiple";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return (!problem.transposeC01() ? problem.freeSizeA(index)
|
|
: problem.freeSizeB(index))
|
|
% value
|
|
== 0;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
int freeSize = !problem.transposeC01() ? problem.freeSizeA(index)
|
|
: problem.freeSizeB(index);
|
|
return debugEvalCmp(problem, stream, "prob", freeSize, "%", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct Free1SizeMultiple
|
|
: public Predicate_CRTP<Free1SizeMultiple, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
size_t value;
|
|
|
|
Free1SizeMultiple() = default;
|
|
Free1SizeMultiple(size_t index, size_t value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "Free1SizeMultiple";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return (!problem.transposeC01() ? problem.freeSizeB(index)
|
|
: problem.freeSizeA(index))
|
|
% value
|
|
== 0;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
int freeSize = !problem.transposeC01() ? problem.freeSizeB(index)
|
|
: problem.freeSizeA(index);
|
|
return debugEvalCmp(problem, stream, "prob", freeSize, "%", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct BatchSizeMultiple
|
|
: public Predicate_CRTP<BatchSizeMultiple, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
size_t value;
|
|
|
|
BatchSizeMultiple() = default;
|
|
BatchSizeMultiple(size_t index, size_t value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "BatchSizeMultiple";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.batchSize(index) % value == 0;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.batchSize(index), "%", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct BatchSizeEqual : public Predicate_CRTP<BatchSizeEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
size_t value;
|
|
|
|
BatchSizeEqual() = default;
|
|
BatchSizeEqual(size_t index, size_t value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "BatchSizeEqual";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.batchSize(index) == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.batchSize(index), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct SynchronizerSizeCheck
|
|
: public Predicate_CRTP<SynchronizerSizeCheck, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
std::array<int, 6> value;
|
|
|
|
SynchronizerSizeCheck() = default;
|
|
SynchronizerSizeCheck(size_t index, std::array<int, 6> value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "SynchronizerSizeCheck";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
int16_t gsu = problem.getParams().gsu() != 0 ? problem.getParams().gsu() : value[5];
|
|
if(gsu == -1 || gsu == 1)
|
|
return 1;
|
|
|
|
// WorkGroup numbers x number of global write instruction x Wave numbers
|
|
// M/MT0 x N/MT1 x NumElementsPerThread/StoreVectorWidth x x Wavenumbers x batch
|
|
uint32_t synchronizerUsage = (std::ceil(static_cast<float>(problem.freeSizeA(0)) / value[0])
|
|
* std::ceil(static_cast<float>(problem.freeSizeB(0)) / value[1]))
|
|
* value[2] * value[4] * value[3] * problem.d().sizes()[2];
|
|
|
|
if(problem.groupedGemm())
|
|
return synchronizerUsage <= 409600 * 16 / problem.groupedGemmCount();
|
|
else
|
|
return synchronizerUsage <= 409600 * 16;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
uint32_t synchronizerSize = 409600 * 16;
|
|
if(problem.groupedGemm())
|
|
synchronizerSize /= problem.groupedGemmCount();
|
|
|
|
return debugEvalCmp(
|
|
problem,
|
|
stream,
|
|
"prob",
|
|
(std::ceil(static_cast<float>(problem.freeSizeA(0)) / value[0])
|
|
* std::ceil(static_cast<float>(problem.freeSizeB(0)) / value[1]))
|
|
* (value[2]) * (value[4]) * value[3] * problem.d().sizes()[2],
|
|
">=",
|
|
"limit",
|
|
synchronizerSize);
|
|
}
|
|
};
|
|
|
|
struct BoundSizeMultiple
|
|
: public Predicate_CRTP<BoundSizeMultiple, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
int64_t index;
|
|
size_t value;
|
|
|
|
BoundSizeMultiple() = default;
|
|
BoundSizeMultiple(size_t index, size_t value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "BoundSizeMultiple";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
if(index < 0)
|
|
return problem.boundSize(problem.boundIndices().size() + index) % value
|
|
== 0;
|
|
else
|
|
return problem.boundSize(index) % value == 0;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
int index_mod = index < 0 ? problem.boundIndices().size() + index : index;
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.boundSize(index_mod), "%", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct ProblemSizeEqual
|
|
: public Predicate_CRTP<ProblemSizeEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
size_t value;
|
|
|
|
ProblemSizeEqual() = default;
|
|
ProblemSizeEqual(size_t index, size_t value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "ProblemSizeEqual";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.problemSizes()[index] == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.problemSizes()[index], "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct MaxProblemSizeGreaterThan
|
|
: public Predicate_CRTP<MaxProblemSizeGreaterThan, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
size_t value;
|
|
|
|
MaxProblemSizeGreaterThan() = default;
|
|
MaxProblemSizeGreaterThan(size_t value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "MaxProblemSizeGreaterThan";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.maxProblemSize() > value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.maxProblemSize(), ">", "sol", value);
|
|
}
|
|
};
|
|
|
|
// If the tensor contains no free dimensions, then the first batch dimension
|
|
// serves as the leading free size
|
|
struct LeadingFree0SizesGreaterOrEqual
|
|
: public Predicate_CRTP<LeadingFree0SizesGreaterOrEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
size_t value;
|
|
|
|
LeadingFree0SizesGreaterOrEqual() = default;
|
|
LeadingFree0SizesGreaterOrEqual(size_t value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "LeadingFree0SizesGreaterOrEqual";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
assert(problem.batchIndices().size() <= 1);
|
|
// TODO: this is not quite right since it assumes batchSize(0) is lowest
|
|
// order in index assignments
|
|
// If tensor contains multiple batch dims this may not be true.
|
|
// Really should modify Contractions.py to select SizeN >= value, based on
|
|
// desired index requirement
|
|
return (problem.freeIndicesA().size() ? problem.freeSizeA(0) >= value
|
|
: problem.batchSize(0) >= value);
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
int size = problem.freeIndicesA().size() ? problem.freeSizeA(0)
|
|
: problem.batchSize(0);
|
|
return debugEvalCmp(problem, stream, "prob", size, ">=", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct LeadingFree1SizesGreaterOrEqual
|
|
: public Predicate_CRTP<LeadingFree1SizesGreaterOrEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
size_t value;
|
|
|
|
LeadingFree1SizesGreaterOrEqual() = default;
|
|
LeadingFree1SizesGreaterOrEqual(size_t value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "LeadingFree1SizesGreaterOrEqual";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
assert(problem.batchIndices().size() <= 1);
|
|
// TODO: this is not quite right since it assumes batchSize(0) is lowest
|
|
// order in index assignments
|
|
// If tensor contains multiple batch dims this may not be true.
|
|
// Really should modify Contractions.py to select SizeN >= value, based on
|
|
// desired index requirement
|
|
if(problem.groupedGemm())
|
|
return (problem.freeIndicesB().size()
|
|
? problem.freeSizeB(0) >= value || problem.freeSizeB(0) == 0
|
|
: problem.batchSize(0) >= value || problem.freeSizeB(0) == 0);
|
|
return (problem.freeIndicesB().size() ? problem.freeSizeB(0) >= value
|
|
: problem.batchSize(0) >= value);
|
|
}
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
int size = problem.freeIndicesB().size() ? problem.freeSizeB(0)
|
|
: problem.batchSize(0);
|
|
return debugEvalCmp(problem, stream, "prob", size, ">=", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct SizeEqual : public Predicate_CRTP<SizeEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
size_t value;
|
|
|
|
SizeEqual() = default;
|
|
SizeEqual(size_t index, size_t value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "SizeEqual";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.size(index) == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.size(index), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct SizeGreaterThan : public Predicate_CRTP<SizeGreaterThan, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
size_t value;
|
|
|
|
SizeGreaterThan() = default;
|
|
SizeGreaterThan(size_t index, size_t value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "SizeGreaterThan";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return (problem.size(index) > value);
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.size(index), ">", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct SizeLessThan : public Predicate_CRTP<SizeLessThan, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
size_t value;
|
|
|
|
SizeLessThan() = default;
|
|
SizeLessThan(size_t index, size_t value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "SizeLessThan";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return (problem.size(index) < value);
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.size(index), "<", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct SizeMultiple : public Predicate_CRTP<SizeMultiple, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
size_t value;
|
|
|
|
SizeMultiple() = default;
|
|
SizeMultiple(size_t index, size_t value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "SizeMultiple";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return ((problem.size(index) % value) == 0);
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.size(index), "%", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct Range
|
|
{
|
|
size_t min = 0;
|
|
size_t max = std::numeric_limits<size_t>::max();
|
|
};
|
|
|
|
inline std::ostream& operator<<(std::ostream& stream, Range const& range)
|
|
{
|
|
return stream << "min: " << range.min << ", max: " << range.max;
|
|
}
|
|
|
|
struct SizeInRange : public Predicate_CRTP<SizeInRange, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
Range value;
|
|
|
|
SizeInRange() = default;
|
|
SizeInRange(size_t index, Range value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "SizeInRange";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return (problem.size(index) >= value.min) && (problem.size(index) < value.max);
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(problem,
|
|
stream,
|
|
"prob_low",
|
|
problem.size(index),
|
|
">=",
|
|
"sol_low",
|
|
value.min,
|
|
"prob_high",
|
|
problem.size(index),
|
|
"<",
|
|
"sol_high",
|
|
value.max);
|
|
}
|
|
};
|
|
|
|
struct StrideAEqual : public Predicate_CRTP<StrideAEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
size_t value;
|
|
|
|
StrideAEqual() = default;
|
|
StrideAEqual(size_t index, size_t value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "StrideAEqual";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.a().strides()[index] == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.a().strides()[index], "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct StrideBEqual : public Predicate_CRTP<StrideBEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
size_t value;
|
|
|
|
StrideBEqual() = default;
|
|
StrideBEqual(size_t index, size_t value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "StrideBEqual";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.b().strides()[index] == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.b().strides()[index], "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct StrideCEqual : public Predicate_CRTP<StrideCEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
size_t value;
|
|
|
|
StrideCEqual() = default;
|
|
StrideCEqual(size_t index, size_t value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "StrideCEqual";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.c().strides()[index] == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.c().strides()[index], "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct StrideDEqual : public Predicate_CRTP<StrideDEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
size_t value;
|
|
|
|
StrideDEqual() = default;
|
|
StrideDEqual(size_t index, size_t value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "StrideDEqual";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.d().strides()[index] == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.d().strides()[index], "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct LDCEqualsLDD : public Predicate_CRTP<LDCEqualsLDD, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = false
|
|
};
|
|
static std::string Type()
|
|
{
|
|
return "LDCEqualsLDD";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.c().strides()[1] == problem.d().strides()[1];
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(problem,
|
|
stream,
|
|
"prob_c_stride",
|
|
problem.c().strides()[1],
|
|
"==",
|
|
"prob_d_stride",
|
|
problem.d().strides()[1]);
|
|
}
|
|
};
|
|
|
|
struct CEqualsD : public Predicate_CRTP<CEqualsD, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = false
|
|
};
|
|
static std::string Type()
|
|
{
|
|
return "CEqualsD";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.cEqualsD();
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.cEqualsD(), "==", "sol", true);
|
|
}
|
|
};
|
|
|
|
struct AmaxDCheck : public Predicate_CRTP<AmaxDCheck, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
bool value;
|
|
|
|
AmaxDCheck() = default;
|
|
AmaxDCheck(bool value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "AmaxDCheck";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
bool amaxDStatusEqual = (problem.outputAmaxD() == value);
|
|
|
|
// if value is true, then we also need to check gsu
|
|
// otherwise we just check outputAmaxD
|
|
if(value)
|
|
return amaxDStatusEqual && (problem.getParams().gsu() == 0 || problem.getParams().gsu() == 1);
|
|
else
|
|
return amaxDStatusEqual;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
std::ostringstream details;
|
|
details << "prob_amaxD=" << problem.outputAmaxD() << " == sol_amaxD=" << value;
|
|
if(value)
|
|
details << ", prob_gsu=" << problem.getParams().gsu() << " (must be 0 or 1)";
|
|
PredicateDebugger::printRow(stream, rv, this->type(), details.str());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct BetaZero : public Predicate_CRTP<BetaZero, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = false
|
|
};
|
|
BetaZero() = default;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "BetaZero";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.beta() == 0.0;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(problem, stream, "prob", problem.beta(), "==", "sol", 0.0);
|
|
}
|
|
};
|
|
|
|
struct BetaOne : public Predicate_CRTP<BetaOne, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = false
|
|
};
|
|
BetaOne() = default;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "BetaOne";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.beta() == 1.0;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(problem, stream, "prob", problem.beta(), "==", "sol", 1.0);
|
|
}
|
|
};
|
|
|
|
struct HighPrecisionAccumulateEqual
|
|
: public Predicate_CRTP<HighPrecisionAccumulateEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
bool value;
|
|
|
|
HighPrecisionAccumulateEqual() = default;
|
|
HighPrecisionAccumulateEqual(bool value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "HighPrecisionAccumulate";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.highPrecisionAccumulate() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(problem,
|
|
stream,
|
|
"prob",
|
|
problem.highPrecisionAccumulate(),
|
|
"==",
|
|
"sol",
|
|
value);
|
|
}
|
|
};
|
|
|
|
struct KernelLanguageCompatible
|
|
: public Predicate_CRTP<KernelLanguageCompatible, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
KernelLanguage value;
|
|
|
|
KernelLanguageCompatible() = default;
|
|
KernelLanguageCompatible(KernelLanguage value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "KernelLanguageCompatible";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.kernelLanguage() == value
|
|
|| problem.kernelLanguage() == KernelLanguage::Any;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(problem,
|
|
stream,
|
|
"prob",
|
|
problem.kernelLanguage(),
|
|
"==",
|
|
"sol",
|
|
value,
|
|
"prob",
|
|
problem.kernelLanguage(),
|
|
"==",
|
|
"sol_any",
|
|
KernelLanguage::Any);
|
|
}
|
|
};
|
|
|
|
struct DeterministicModeEqual
|
|
: public Predicate_CRTP<DeterministicModeEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
bool value;
|
|
|
|
DeterministicModeEqual() = default;
|
|
DeterministicModeEqual(bool value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "DeterministicMode";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.deterministicMode() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.deterministicMode(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct AIGreaterThanEqual
|
|
: public Predicate_CRTP<AIGreaterThanEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
|
|
double value;
|
|
|
|
AIGreaterThanEqual() = default;
|
|
AIGreaterThanEqual(double value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "AIGreaterThanEqual";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.arithmeticIntensity() >= value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(problem, stream, "prob", problem.arithmeticIntensity(), ">=", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct AILessThanEqual : public Predicate_CRTP<AILessThanEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
|
|
double value;
|
|
|
|
AILessThanEqual() = default;
|
|
AILessThanEqual(double value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "AILessThanEqual";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.arithmeticIntensity() <= value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(problem, stream, "prob", problem.arithmeticIntensity(), "<=", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct AlphaValue : public Predicate_CRTP<AlphaValue, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
|
|
ScalarValue value;
|
|
|
|
AlphaValue() = default;
|
|
AlphaValue(ScalarValue value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "AlphaValue";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.alphaRestriction() == value || value == ScalarValue::Any;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(problem,
|
|
stream,
|
|
"prob",
|
|
problem.alphaRestriction(),
|
|
"==",
|
|
"sol",
|
|
value,
|
|
"sol",
|
|
value,
|
|
"==",
|
|
"sol_any",
|
|
ScalarValue::Any);
|
|
}
|
|
};
|
|
|
|
struct BetaValue : public Predicate_CRTP<BetaValue, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
|
|
ScalarValue value;
|
|
|
|
BetaValue() = default;
|
|
BetaValue(ScalarValue value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "BetaValue";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.betaRestriction() == value || value == ScalarValue::Any;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(problem,
|
|
stream,
|
|
"prob",
|
|
problem.betaRestriction(),
|
|
"==",
|
|
"sol",
|
|
value,
|
|
"sol",
|
|
value,
|
|
"==",
|
|
"sol_any",
|
|
ScalarValue::Any);
|
|
}
|
|
};
|
|
|
|
struct TypesEqual : public Predicate_CRTP<TypesEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
TypesEqual() = default;
|
|
|
|
std::array<rocisa::DataType, 6> value;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "TypesEqual";
|
|
}
|
|
|
|
// This function checks if the computeInputType of a problem matches the computeInputType of a
|
|
// solution. Because for Float8{_fnuz}/BFloat8{_fnuz}, the computeInputTypeA and computeInputTypeB
|
|
// might be concatenated like this: computeInputTypeAcomputeInputTypeB{_fnuz}, this function
|
|
// includes special logic to inspect types at the concatenation position.
|
|
//
|
|
bool validateComputeType(rocisa::DataType const& problemComputeInputType, bool const isComputeInputTypeA) const
|
|
{
|
|
using ArrType = std::array<std::pair<rocisa::DataType, rocisa::DataType>, 4>;
|
|
|
|
// computeInputTypeA corresponds to the first type in the concatenated type
|
|
ArrType const computeInputTypeAMapping =
|
|
{{
|
|
{rocisa::DataType::BFloat8_fnuz, rocisa::DataType::BFloat8Float8_fnuz},
|
|
{rocisa::DataType::Float8_fnuz, rocisa::DataType::Float8BFloat8_fnuz},
|
|
{rocisa::DataType::BFloat8, rocisa::DataType::BFloat8Float8},
|
|
{rocisa::DataType::Float8, rocisa::DataType::Float8BFloat8}
|
|
}};
|
|
|
|
// computeInputTypeB corresponds to the second type in the concatenated type
|
|
ArrType const computeInputTypeBMapping =
|
|
{{
|
|
{rocisa::DataType::Float8_fnuz, rocisa::DataType::BFloat8Float8_fnuz},
|
|
{rocisa::DataType::BFloat8_fnuz, rocisa::DataType::Float8BFloat8_fnuz},
|
|
{rocisa::DataType::Float8, rocisa::DataType::BFloat8Float8},
|
|
{rocisa::DataType::BFloat8, rocisa::DataType::Float8BFloat8}
|
|
}};
|
|
|
|
auto validate = [](ArrType const& arr,
|
|
rocisa::DataType const& t1, rocisa::DataType const& t2){
|
|
if(t1 == t2)
|
|
return true;
|
|
return std::any_of(arr.begin(), arr.end(), [&](const auto& p){
|
|
return (p == std::make_pair(t1, t2)) or (p == std::make_pair(t2, t1));
|
|
});
|
|
};
|
|
|
|
if(isComputeInputTypeA)
|
|
{
|
|
// value[4] is computeInputTypeA
|
|
return
|
|
validate(computeInputTypeAMapping, problemComputeInputType, value[4]);
|
|
}
|
|
else
|
|
{
|
|
// value[5] is computeInputTypeB
|
|
return
|
|
validate(computeInputTypeBMapping, problemComputeInputType, value[5]);
|
|
}
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.a().dataType() == value[0] && problem.b().dataType() == value[1]
|
|
&& problem.c().dataType() == value[2]
|
|
&& problem.d().dataType() == value[3]
|
|
&& problem.computeInputTypeA() == value[4]
|
|
&& problem.computeInputTypeB() == value[5];
|
|
}
|
|
|
|
virtual std::string toString() const override
|
|
{
|
|
return concatenate(this->type(),
|
|
"(a:",
|
|
value[0],
|
|
", b:",
|
|
value[1],
|
|
", c:",
|
|
value[2],
|
|
", d:",
|
|
value[3],
|
|
", compute input typeA:",
|
|
value[4],
|
|
", compute input typeB:",
|
|
value[5]);
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(problem,
|
|
stream,
|
|
"prob_a",
|
|
problem.a().dataType(),
|
|
"==",
|
|
"sol_a",
|
|
value[0],
|
|
"prob_b",
|
|
problem.b().dataType(),
|
|
"==",
|
|
"sol_b",
|
|
value[1],
|
|
"prob_c",
|
|
problem.c().dataType(),
|
|
"==",
|
|
"sol_c",
|
|
value[2],
|
|
"prob_d",
|
|
problem.d().dataType(),
|
|
"==",
|
|
"sol_d",
|
|
value[3],
|
|
"prob_compute_a",
|
|
problem.computeInputTypeA(),
|
|
"==",
|
|
"sol_compute_a",
|
|
value[4],
|
|
"prob_compute_b",
|
|
problem.computeInputTypeB(),
|
|
"==",
|
|
"sol_compute_b",
|
|
value[5]);
|
|
}
|
|
};
|
|
|
|
struct OperationIdentifierEqual
|
|
: public Predicate_CRTP<OperationIdentifierEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
OperationIdentifierEqual() = default;
|
|
|
|
std::string value;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "OperationIdentifierEqual";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.operationIdentifier() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.operationIdentifier(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct BufferLoadOffsetLimitCheck
|
|
: public Predicate_CRTP<BufferLoadOffsetLimitCheck, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
BufferLoadCheckPacket value;
|
|
|
|
BufferLoadOffsetLimitCheck() = default;
|
|
BufferLoadOffsetLimitCheck(BufferLoadCheckPacket value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "BufferLoadOffsetLimitCheck";
|
|
}
|
|
|
|
// The min operator is used to handle cases where size_M/size_K is smaller than the value.depthUorMT0
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
const uint64_t TWO_POW_32 = 4294967296;
|
|
return multiplyElementSize((problem.a().strides()[1] * std::min(value.depthUorMT0, problem.a().sizes()[1]) + value.shiftPtrElemA),
|
|
problem.a().elementBytes())
|
|
< TWO_POW_32
|
|
&& multiplyElementSize((problem.b().strides()[1] * std::min(value.depthUorMT1, problem.b().sizes()[1]) + value.shiftPtrElemB)
|
|
,problem.b().elementBytes())
|
|
< TWO_POW_32;
|
|
}
|
|
|
|
virtual std::string toString() const override
|
|
{
|
|
return concatenate(this->type(),
|
|
"(DU/MT0:",
|
|
value.depthUorMT0,
|
|
", DU/MT1:",
|
|
value.depthUorMT1,
|
|
", ShiftPtrPadElementA:",
|
|
value.shiftPtrElemA,
|
|
", ShiftPtrPadElementB:",
|
|
value.shiftPtrElemB,
|
|
")");
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
std::ostringstream details;
|
|
details << "A:(" << problem.a().strides()[1] << "*" << value.depthUorMT0 << "+"
|
|
<< value.shiftPtrElemA << ")*" << problem.a().elementBytes()
|
|
<< "<2^32, B:(" << problem.b().strides()[1] << "*" << value.depthUorMT1
|
|
<< "+" << value.shiftPtrElemB << ")*" << problem.b().elementBytes()
|
|
<< "<2^32";
|
|
PredicateDebugger::printRow(stream, rv, this->type(), details.str());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct BufferLoadOffsetLimitCheck_Beta
|
|
: public Predicate_CRTP<BufferLoadOffsetLimitCheck_Beta, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
size_t value;
|
|
|
|
BufferLoadOffsetLimitCheck_Beta() = default;
|
|
BufferLoadOffsetLimitCheck_Beta(size_t value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "BufferLoadOffsetLimitCheck_Beta";
|
|
}
|
|
|
|
// The min operator is used to handle cases where size_N is smaller than the value(usually is MacroTile1)
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
if(problem.c().empty() || problem.beta() == 0)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
const uint64_t TWO_POW_32 = 4294967296;
|
|
return multiplyElementSize(problem.c().strides()[1] * std::min(value, problem.c().sizes()[1]), problem.c().elementBytes())
|
|
< TWO_POW_32;
|
|
}
|
|
}
|
|
|
|
virtual std::string toString() const override
|
|
{
|
|
return concatenate(this->type(), "(MT1:", value, ")");
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
std::ostringstream details;
|
|
details << "C:" << problem.c().strides()[1] << "*"
|
|
<< problem.c().elementBytes() << "*" << value << "<2^32";
|
|
PredicateDebugger::printRow(stream, rv, this->type(), details.str());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct BufferStoreOffsetLimitCheck
|
|
: public Predicate_CRTP<BufferStoreOffsetLimitCheck, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
size_t value;
|
|
|
|
BufferStoreOffsetLimitCheck() = default;
|
|
BufferStoreOffsetLimitCheck(size_t value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "BufferStoreOffsetLimitCheck";
|
|
}
|
|
|
|
// The min operator is used to handle cases where size_N is smaller than the value(usually is MacroTile1)
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
const uint64_t TWO_POW_32 = 4294967296;
|
|
return multiplyElementSize(problem.d().strides()[1] * std::min(value, problem.d().sizes()[1]), problem.d().elementBytes())
|
|
< TWO_POW_32;
|
|
}
|
|
|
|
virtual std::string toString() const override
|
|
{
|
|
return concatenate(this->type(), "(MT1:", value, ")");
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
std::ostringstream details;
|
|
details << "D:" << problem.d().strides()[1] << "*"
|
|
<< problem.d().elementBytes() << "*" << value << "<2^32";
|
|
PredicateDebugger::printRow(stream, rv, this->type(), details.str());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct WorkgroupNumberCheck
|
|
: public Predicate_CRTP<WorkgroupNumberCheck, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = true,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
std::array<int, 3> value;
|
|
|
|
WorkgroupNumberCheck() = default;
|
|
WorkgroupNumberCheck(size_t index, std::array<int, 3> value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
// If the number is larger than 2^24, it may lose precision when converted into fp32.
|
|
// TODO: REMOVE custom kernel, then REMOVE the behavior that compressed 3 DIM workgroups into 1 DIM
|
|
#define MAX_WORKGROUP_NUMBER 16777216
|
|
static std::string Type()
|
|
{
|
|
return "WorkgroupNumberCheck";
|
|
}
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
int16_t gsu = problem.getParams().gsu() != 0 ? problem.getParams().gsu() : value[2];
|
|
// auto gsu will consider workgroup number, so bypassed
|
|
if(gsu == -1)
|
|
return 1;
|
|
|
|
gsu = gsu > 1 ? gsu : 1;
|
|
return (std::ceil(static_cast<float>(problem.freeSizeA(0)) / value[0])
|
|
* std::ceil(static_cast<float>(problem.freeSizeB(0)) / value[1]) * gsu
|
|
* problem.batchSize(0))
|
|
<= MAX_WORKGROUP_NUMBER;
|
|
}
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
int16_t gsu = problem.getParams().gsu() != 0 ? problem.getParams().gsu() : value[2];
|
|
if(gsu == -1)
|
|
{
|
|
bool rv = (*this)(problem);
|
|
PredicateDebugger::printRow(stream, rv, this->type(), "auto gsu (bypassed)");
|
|
return rv;
|
|
}
|
|
gsu = gsu > 1 ? gsu : 1;
|
|
int workgroupNumber = std::ceil(static_cast<float>(problem.freeSizeA(0)) / value[0])
|
|
* std::ceil(static_cast<float>(problem.freeSizeB(0)) / value[1])
|
|
* gsu * problem.batchSize(0);
|
|
return debugEvalCmp(problem, stream, "wg_num", workgroupNumber, "<=", "max", MAX_WORKGROUP_NUMBER);
|
|
}
|
|
};
|
|
|
|
struct PersistentKernelCheck
|
|
: public Predicate_CRTP<PersistentKernelCheck, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = false
|
|
};
|
|
PersistentKernelCheck() = default;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "PersistentKernelCheck";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.getPersistentKernelEligibility();
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
PredicateDebugger::printRow(
|
|
stream, rv, this->type(), rv ? "eligible" : "not eligible");
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct GlobalSplitUCheckMinK
|
|
: public Predicate_CRTP<GlobalSplitUCheckMinK, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
|
|
std::array<int, 2> value;
|
|
|
|
GlobalSplitUCheckMinK() = default;
|
|
GlobalSplitUCheckMinK(std::array<int, 2> value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "GlobalSplitUCheckMinK";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
size_t minK
|
|
= (problem.getParams().gsu() != 0 ? problem.getParams().gsu() : value[1]);
|
|
// auto gsu will consider MinK, so bypassed
|
|
if(minK == -1)
|
|
return 1;
|
|
if(minK == 1)
|
|
minK = 0;
|
|
minK *= value[0];
|
|
return problem.boundSize(0) >= minK;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
size_t gsu = (problem.getParams().gsu() != 0 ? problem.getParams().gsu() : value[1]);
|
|
if(gsu == static_cast<size_t>(-1))
|
|
{
|
|
bool rv = (*this)(problem);
|
|
PredicateDebugger::printRow(stream, rv, this->type(), "auto gsu (bypassed)");
|
|
return rv;
|
|
}
|
|
size_t minK = (gsu == 1) ? 0 : gsu * value[0];
|
|
return debugEvalCmp(problem, stream, "prob", problem.boundSize(0), ">=", "sol", minK);
|
|
}
|
|
};
|
|
|
|
struct CDStridesEqual : public Predicate_CRTP<CDStridesEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = false
|
|
};
|
|
|
|
CDStridesEqual() = default;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "CDStridesEqual";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.c().strides() == problem.d().strides();
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(problem,
|
|
stream,
|
|
"prob_c_stride",
|
|
problem.c().strides(),
|
|
"==",
|
|
"prob_d_stride",
|
|
problem.d().strides());
|
|
}
|
|
};
|
|
|
|
struct StridedBatchedEqual
|
|
: public Predicate_CRTP<StridedBatchedEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
bool value;
|
|
|
|
StridedBatchedEqual() = default;
|
|
StridedBatchedEqual(bool value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "StridedBatched";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.stridedBatched() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.stridedBatched(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct GroupedGemmEqual
|
|
: public Predicate_CRTP<GroupedGemmEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
bool value;
|
|
|
|
GroupedGemmEqual() = default;
|
|
GroupedGemmEqual(bool value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "GroupedGemm";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.groupedGemm() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.groupedGemm(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct CUEfficiency : public Predicate_CRTP<CUEfficiency, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = false
|
|
};
|
|
|
|
CUEfficiency() = default;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "CUEfficiency";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
if(problem.performanceMetric() == PerformanceMetric::CUEfficiency)
|
|
{
|
|
return true;
|
|
}
|
|
else if(problem.performanceMetric() == PerformanceMetric::Auto)
|
|
{
|
|
// True if total flops below a constant threshold
|
|
// Current threshold chosen naively as the flops for a
|
|
// 1500x1500 square matrix multiply
|
|
return problem.flopCount() < size_t(1500ll * 1500ll * 1500ll * 2);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
std::ostringstream details;
|
|
if(problem.performanceMetric() == PerformanceMetric::CUEfficiency)
|
|
details << "metric=CUEfficiency";
|
|
else if(problem.performanceMetric() == PerformanceMetric::Auto)
|
|
details << "metric=Auto, flopCount=" << problem.flopCount();
|
|
else
|
|
details << "metric=other (not CUEfficiency or Auto)";
|
|
PredicateDebugger::printRow(stream, rv, this->type(), details.str());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct ExperimentalStreamK
|
|
: public Predicate_CRTP<ExperimentalStreamK, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = false
|
|
};
|
|
|
|
ExperimentalStreamK() = default;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "ExperimentalStreamK";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return (problem.performanceMetric() == PerformanceMetric::ExperimentalStreamK);
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(problem,
|
|
stream,
|
|
"prob",
|
|
problem.performanceMetric(),
|
|
"==",
|
|
"sol: PerformanceMetric::ExperimentalStreamK",
|
|
PerformanceMetric::ExperimentalStreamK);
|
|
}
|
|
};
|
|
|
|
struct ExperimentalMLP : public Predicate_CRTP<ExperimentalMLP, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = false
|
|
};
|
|
ExperimentalMLP() = default;
|
|
static std::string Type()
|
|
{
|
|
return "ExperimentalMLP";
|
|
}
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return (problem.performanceMetric() == PerformanceMetric::ExperimentalMLP);
|
|
}
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(problem,
|
|
stream,
|
|
"prob",
|
|
problem.performanceMetric(),
|
|
"==",
|
|
"sol: PerformanceMetric::ExperimentalMLP",
|
|
PerformanceMetric::ExperimentalMLP);
|
|
}
|
|
};
|
|
|
|
struct EqualityMatching
|
|
: public Predicate_CRTP<EqualityMatching, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = false
|
|
};
|
|
|
|
EqualityMatching() = default;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "EqualityMatching";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
stream << "Searching " << this->type() << " Library..." << std::endl;
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct RangeMatching
|
|
: public Predicate_CRTP<RangeMatching, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = false
|
|
};
|
|
|
|
RangeMatching() = default;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "RangeMatching";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
stream << "Searching " << this->type() << " Library..." << std::endl;
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
|
|
struct FreeSizeMatching
|
|
: public Predicate_CRTP<FreeSizeMatching, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = false
|
|
};
|
|
|
|
FreeSizeMatching() = default;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "FreeSizeMatching";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
stream << "Searching " << this->type() << " Library..." << std::endl;
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct PredictionMatching : public Predicate_CRTP<PredictionMatching, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = false
|
|
};
|
|
|
|
PredictionMatching() = default;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "PredictionMatching";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
PredicateDebugger::printRow(stream, rv, this->type());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct GridBasedMatching
|
|
: public Predicate_CRTP<GridBasedMatching, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = false
|
|
};
|
|
|
|
GridBasedMatching() = default;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "GridBasedMatching";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
PredicateDebugger::printRow(stream, rv, this->type());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct UseGradientEqual
|
|
: public Predicate_CRTP<UseGradientEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
bool value;
|
|
|
|
UseGradientEqual() = default;
|
|
UseGradientEqual(bool value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "UseGradient";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.useGradient() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.useGradient(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
// Activation
|
|
struct ActivationCheck : public Predicate_CRTP<ActivationCheck, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
ActivationType value;
|
|
|
|
ActivationCheck() = default;
|
|
ActivationCheck(ActivationType value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "Activation";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
if(value == ActivationType::All)
|
|
return true;
|
|
if(problem.activationType() == value
|
|
|| problem.activationType() == ActivationType::None)
|
|
return true;
|
|
if(value == ActivationType::Hipblaslt_all
|
|
&& (problem.activationType() == ActivationType::DGelu
|
|
|| problem.activationType() == ActivationType::DRelu
|
|
|| problem.activationType() == ActivationType::Gelu
|
|
|| problem.activationType() == ActivationType::Relu
|
|
|| problem.activationType() == ActivationType::Silu
|
|
|| problem.activationType() == ActivationType::Clamp))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.activationType(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct ActivationEnumWhiteList
|
|
: public Predicate_CRTP<ActivationEnumWhiteList, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
ActivationEnumWhiteList() = default;
|
|
|
|
std::vector<ActivationType> value;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "ActivationEnumWhiteList";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
if(problem.activationType() == ActivationType::All
|
|
|| problem.activationType() == ActivationType::Hipblaslt_all)
|
|
{
|
|
for(size_t i = 0; i < value.size(); i++)
|
|
{
|
|
if(value[i] == problem.getParams().activationEnum())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
std::ostringstream details;
|
|
details << "supported=[";
|
|
for(size_t i = 0; i < value.size(); i++)
|
|
{
|
|
details << ToString(value[i]);
|
|
if(i < value.size() - 1)
|
|
details << ", ";
|
|
}
|
|
details << "], prob=" << ToString(problem.getParams().activationEnum());
|
|
PredicateDebugger::printRow(stream, rv, this->type(), details.str());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct ActivationComputeTypeEqual
|
|
: public Predicate_CRTP<ActivationComputeTypeEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
rocisa::DataType value;
|
|
|
|
ActivationComputeTypeEqual() = default;
|
|
ActivationComputeTypeEqual(rocisa::DataType value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "ActivationComputeType";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
if(problem.activationType() == ActivationType::None)
|
|
return true;
|
|
return problem.activationComputeType() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
if(problem.activationType() != ActivationType::None)
|
|
return debugEvalCmp(problem,
|
|
stream,
|
|
"prob",
|
|
problem.activationComputeType(),
|
|
"==",
|
|
"sol",
|
|
value);
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct ActivationNoGuardEqual
|
|
: public Predicate_CRTP<ActivationNoGuardEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
bool value;
|
|
|
|
ActivationNoGuardEqual() = default;
|
|
ActivationNoGuardEqual(bool value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "ActivationNoGuard";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.activationNoGuard() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.activationNoGuard(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct UseBiasCheck : public Predicate_CRTP<UseBiasCheck, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
int value;
|
|
|
|
UseBiasCheck() = default;
|
|
UseBiasCheck(int value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "UseBias";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return !problem.useBias() || value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
std::ostringstream details;
|
|
details << "prob=" << problem.useBias() << ", sol_supports=" << value;
|
|
PredicateDebugger::printRow(stream, rv, this->type(), details.str());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct UseGateResidualEqual
|
|
: public Predicate_CRTP<UseGateResidualEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
bool value;
|
|
|
|
UseGateResidualEqual() = default;
|
|
UseGateResidualEqual(bool value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "UseGateResidual";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.useGateResidual() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
std::ostringstream details;
|
|
details << "prob=" << problem.useGateResidual() << ", sol=" << value;
|
|
PredicateDebugger::printRow(stream, rv, this->type(), details.str());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct UseEEqual : public Predicate_CRTP<UseEEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
bool value;
|
|
|
|
UseEEqual() = default;
|
|
UseEEqual(bool value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "UseE";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.useE() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.useE(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct DataTypeEEqual : public Predicate_CRTP<DataTypeEEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
rocisa::DataType value;
|
|
|
|
DataTypeEEqual() = default;
|
|
DataTypeEEqual(rocisa::DataType value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "DataTypeE";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
if(problem.useE())
|
|
{
|
|
return problem.e().dataType() == value;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
virtual std::string toString() const override
|
|
{
|
|
return concatenate(this->type(), "(e:", value);
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
debugEvalCmp(
|
|
problem, stream, "prob_e", problem.e().dataType(), "==", "sol_e", value);
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct UseScaleABCheck : public Predicate_CRTP<UseScaleABCheck, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
std::string value;
|
|
|
|
UseScaleABCheck() = default;
|
|
UseScaleABCheck(std::string value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "UseScaleAB";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.useScaleAB().empty() || (problem.useScaleAB() == value);
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
std::ostringstream details;
|
|
details << "prob=" << problem.useScaleAB() << ", sol_supports=" << value;
|
|
PredicateDebugger::printRow(stream, rv, this->type(), details.str());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct UseScaleCDCheck : public Predicate_CRTP<UseScaleCDCheck, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
bool value;
|
|
|
|
UseScaleCDCheck() = default;
|
|
UseScaleCDCheck(bool value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "UseScaleCD";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return !problem.useScaleCD() || value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
std::ostringstream details;
|
|
details << "prob=" << problem.useScaleCD() << ", sol_supports=" << value;
|
|
PredicateDebugger::printRow(stream, rv, this->type(), details.str());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct UseScaleAlphaVecCheck
|
|
: public Predicate_CRTP<UseScaleAlphaVecCheck, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
int value;
|
|
|
|
UseScaleAlphaVecCheck() = default;
|
|
UseScaleAlphaVecCheck(int value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "UseScaleAlphaVec";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return !problem.useScaleAlphaVec() || (problem.useScaleAlphaVec() & value);
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
std::ostringstream details;
|
|
details << "prob=" << problem.useScaleAlphaVec() << ", sol_supports=" << value;
|
|
PredicateDebugger::printRow(stream, rv, this->type(), details.str());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct BiasDataTypeWhiteList
|
|
: public Predicate_CRTP<BiasDataTypeWhiteList, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
BiasDataTypeWhiteList() = default;
|
|
|
|
std::vector<rocisa::DataType> value;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "BiasDataTypeWhiteList";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
if(problem.useBias())
|
|
{
|
|
for(size_t i = 0; i < value.size(); i++)
|
|
{
|
|
if(value[i] == problem.bias().dataType())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
std::ostringstream details;
|
|
details << "supported_types=[";
|
|
for(size_t i = 0; i < value.size(); i++)
|
|
{
|
|
details << ToString(value[i]);
|
|
if(i < value.size() - 1)
|
|
details << ", ";
|
|
}
|
|
details << "]";
|
|
if(problem.useBias())
|
|
details << ", prob_type=" << ToString(problem.bias().dataType());
|
|
PredicateDebugger::printRow(stream, rv, this->type(), details.str());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct GateResidualDataTypeWhiteList
|
|
: public Predicate_CRTP<GateResidualDataTypeWhiteList, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
GateResidualDataTypeWhiteList() = default;
|
|
|
|
std::vector<rocisa::DataType> value;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "GateResidualDataTypeWhiteList";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
if(problem.useGateResidual())
|
|
{
|
|
for(size_t i = 0; i < value.size(); i++)
|
|
{
|
|
if(value[i] == problem.gateResidual().dataType())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
std::ostringstream details;
|
|
details << "supported_types=[";
|
|
for(size_t i = 0; i < value.size(); i++)
|
|
{
|
|
details << ToString(value[i]);
|
|
if(i < value.size() - 1)
|
|
details << ", ";
|
|
}
|
|
details << "]";
|
|
if(problem.useGateResidual())
|
|
details << ", prob_type=" << ToString(problem.gateResidual().dataType());
|
|
PredicateDebugger::printRow(stream, rv, this->type(), details.str());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct BiasSrcWhiteList
|
|
: public Predicate_CRTP<BiasSrcWhiteList, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
BiasSrcWhiteList() = default;
|
|
|
|
// This is actually the index of the problem type
|
|
std::vector<int> value;
|
|
|
|
static std::string Type()
|
|
{
|
|
return "BiasSrcWhiteList";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
if(problem.useBias() && problem.useScaleAlphaVec()
|
|
&& problem.useBias() != problem.useScaleAlphaVec())
|
|
return false;
|
|
|
|
int factorDim = (problem.useBias() == 1) ? 0
|
|
: problem.useBias() == 2 ? 1
|
|
: problem.useBias() == 3 ? problem.getParams().factorDim()
|
|
: 0;
|
|
|
|
if(problem.useBias())
|
|
{
|
|
auto& tensor = problem.tensor(ContractionProblemGemm::TENSOR::BIAS);
|
|
if(tensor.sizes().size() == 0)
|
|
return false;
|
|
for(size_t i = 0; i < value.size(); i++)
|
|
{
|
|
if(value[i] == static_cast<int>(problem.biasSrc()))
|
|
{
|
|
// Check if the length is set correctly.
|
|
auto& length = tensor.sizes()[0];
|
|
if(problem.biasSrc() == ContractionProblemGemm::TENSOR::A
|
|
|| problem.biasSrc() == ContractionProblemGemm::TENSOR::D)
|
|
{
|
|
auto eLength = (problem.useBias() == 1
|
|
|| problem.biasSrc()
|
|
!= ContractionProblemGemm::TENSOR::D)
|
|
? problem.d().sizes()[0]
|
|
: (problem.useBias() <= 3)
|
|
? problem.d().sizes()[factorDim]
|
|
: -1;
|
|
if(length < eLength)
|
|
return false;
|
|
}
|
|
else if(problem.biasSrc() == ContractionProblemGemm::TENSOR::B)
|
|
{
|
|
if(length != problem.d().sizes()[1])
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
virtual std::string toString() const override
|
|
{
|
|
std::string biasString = "";
|
|
for(size_t i = 0; i < value.size(); i++)
|
|
{
|
|
biasString += ToString(value[i]) + ", ";
|
|
}
|
|
return std::string("The supported bias source are: " + biasString);
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
std::ostringstream details;
|
|
details << "supported_sources=[";
|
|
for(size_t i = 0; i < value.size(); i++)
|
|
{
|
|
details << value[i];
|
|
if(i < value.size() - 1)
|
|
details << ", ";
|
|
}
|
|
details << "]";
|
|
if(problem.useBias())
|
|
details << ", bias_src=" << static_cast<int>(problem.biasSrc());
|
|
PredicateDebugger::printRow(stream, rv, this->type(), details.str());
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct Sparse : public Predicate_CRTP<Sparse, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
int value;
|
|
|
|
Sparse() = default;
|
|
Sparse(int value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "Sparse";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.sparse() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.sparse(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct SwizzleTensorA : public Predicate_CRTP<SwizzleTensorA, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
bool value;
|
|
|
|
SwizzleTensorA() = default;
|
|
SwizzleTensorA(bool value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "SwizzleTensorA";
|
|
}
|
|
|
|
bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.swizzleTensorA() == value;
|
|
}
|
|
|
|
bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.swizzleTensorA(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct SwizzleTensorB : public Predicate_CRTP<SwizzleTensorB, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
bool value;
|
|
|
|
SwizzleTensorB() = default;
|
|
SwizzleTensorB(bool value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "SwizzleTensorB";
|
|
}
|
|
|
|
bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.swizzleTensorB() == value;
|
|
}
|
|
|
|
bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.swizzleTensorB(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct F32XdlMathOpEqual
|
|
: public Predicate_CRTP<F32XdlMathOpEqual, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
rocisa::DataType value;
|
|
|
|
F32XdlMathOpEqual() = default;
|
|
F32XdlMathOpEqual(rocisa::DataType value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "F32XdlMathOp";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.f32XdlMathOp() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.f32XdlMathOp(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct SupportDeviceUserArguments
|
|
: public Predicate_CRTP<SupportDeviceUserArguments, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
bool value;
|
|
|
|
SupportDeviceUserArguments() = default;
|
|
SupportDeviceUserArguments(bool value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "SupportDeviceUserArguments";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
// Currently some solutions in gemm cannot enable this feature because lack of sgpr.
|
|
if(problem.getUseDeviceUserArguments() && problem.groupedGemm())
|
|
return problem.getUseDeviceUserArguments() == value;
|
|
return true;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
bool rv = (*this)(problem);
|
|
if(problem.getUseDeviceUserArguments())
|
|
return debugEvalCmp(problem,
|
|
stream,
|
|
"prob",
|
|
problem.getUseDeviceUserArguments(),
|
|
"==",
|
|
"sol",
|
|
value);
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
struct WorkgroupMappingXCCCheck
|
|
: public Predicate_CRTP<WorkgroupMappingXCCCheck, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
// value = [XCC, XCCG]
|
|
std::array<int, 2> value;
|
|
size_t cuCount;
|
|
|
|
WorkgroupMappingXCCCheck()
|
|
{
|
|
auto pHardware = hip::GetCurrentDevice();
|
|
assert(pHardware != nullptr);
|
|
Hardware const& hardware = *pHardware;
|
|
AMDGPU const* pAMDGPU = dynamic_cast<AMDGPU const*>(&hardware);
|
|
cuCount = pAMDGPU->computeUnitCount;
|
|
}
|
|
WorkgroupMappingXCCCheck(std::array<int, 2> value)
|
|
: value(value)
|
|
{
|
|
auto pHardware = hip::GetCurrentDevice();
|
|
assert(pHardware != nullptr);
|
|
Hardware const& hardware = *pHardware;
|
|
AMDGPU const* pAMDGPU = dynamic_cast<AMDGPU const*>(&hardware);
|
|
cuCount = pAMDGPU->computeUnitCount;
|
|
}
|
|
|
|
/// Constructor for testing: inject cuCount so selection logic can be
|
|
/// unit-tested without a GPU (e.g. ROCM-2963: 38-CU partition alignment).
|
|
WorkgroupMappingXCCCheck(std::array<int, 2> value, size_t cuCountForTest)
|
|
: value(value)
|
|
, cuCount(cuCountForTest)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "WorkgroupMappingXCCCheck";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
// If XCC == -1, we automatically set it to the number XCCs.
|
|
// In this case, no predicate is needed.
|
|
if(value[0] == -1)
|
|
return true;
|
|
// NB: If this solution is a cu-fallback for current hardware.
|
|
// We overwrite the XCC to 1 to make sure this can pass.
|
|
// But we also have to notice we are passing the correct XCC to kernel.
|
|
// (i.e. Remember to do param.setWGMXCC(1) when running the kernel)
|
|
size_t XCC = (problem.getParams().fallbackStatus()) ? 1 : value[0];
|
|
size_t XCCG = (value[1] == -1) ? cuCount : value[1];
|
|
return ((XCC & (XCC - 1)) == 0) && XCCG % XCC == 0;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
if(value[0] == -1)
|
|
return true;
|
|
size_t XCC = (problem.getParams().fallbackStatus()) ? 1 : value[0];
|
|
size_t XCCG = (value[1] == -1) ? cuCount : value[1];
|
|
return debugEvalCmp(problem,
|
|
stream,
|
|
"WGMXCCG",
|
|
XCCG,
|
|
"%",
|
|
"WGMXCC",
|
|
XCC,
|
|
"==",
|
|
0);
|
|
}
|
|
};
|
|
|
|
struct MXBlockA
|
|
: public Predicate_CRTP<MXBlockA, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
int value;
|
|
|
|
MXBlockA() = default;
|
|
MXBlockA(int value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "MXBlockA";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.mxBlockA() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.mxBlockA(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct MXBlockB
|
|
: public Predicate_CRTP<MXBlockB, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
int value;
|
|
|
|
MXBlockB() = default;
|
|
MXBlockB(int value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "MXBlockB";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.mxBlockB() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.mxBlockB(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct DataTypeMXSA
|
|
: public Predicate_CRTP<DataTypeMXSA, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
rocisa::DataType value;
|
|
|
|
DataTypeMXSA() = default;
|
|
DataTypeMXSA(rocisa::DataType value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "DataTypeMXSA";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.mxTypeA() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.mxTypeA(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct DataTypeMXSB
|
|
: public Predicate_CRTP<DataTypeMXSB, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
rocisa::DataType value;
|
|
|
|
DataTypeMXSB() = default;
|
|
DataTypeMXSB(rocisa::DataType value)
|
|
: value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "DataTypeMXSB";
|
|
}
|
|
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
return problem.mxTypeB() == value;
|
|
}
|
|
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
return debugEvalCmp(
|
|
problem, stream, "prob", problem.mxTypeB(), "==", "sol", value);
|
|
}
|
|
};
|
|
|
|
struct ClusterDimCheck
|
|
: public Predicate_CRTP<ClusterDimCheck, ContractionProblemGemm>
|
|
{
|
|
enum
|
|
{
|
|
HasIndex = false,
|
|
HasValue = true
|
|
};
|
|
size_t index;
|
|
std::array<int, 5> value;
|
|
|
|
ClusterDimCheck() = default;
|
|
ClusterDimCheck(size_t index, std::array<int, 5> value)
|
|
: index(index)
|
|
, value(value)
|
|
{
|
|
}
|
|
|
|
static std::string Type()
|
|
{
|
|
return "ClusterDimCheck";
|
|
}
|
|
virtual bool operator()(ContractionProblemGemm const& problem) const override
|
|
{
|
|
int gsu = problem.getParams().gsu() > 0 ? problem.getParams().gsu() : value[2];
|
|
gsu = gsu > 1 ? gsu : 1;
|
|
int numWG_x = static_cast<int>(
|
|
std::ceil(static_cast<float>(problem.freeSizeA(0)) / value[0])
|
|
);
|
|
int numWG_y = static_cast<int>(
|
|
std::ceil(static_cast<float>(problem.freeSizeB(0)) / value[1])
|
|
) * gsu;
|
|
|
|
bool divisible_x = (numWG_x % value[3]) == 0;
|
|
bool divisible_y = (numWG_y % value[4]) == 0;
|
|
|
|
return (divisible_x and divisible_y);
|
|
}
|
|
virtual bool debugEval(ContractionProblemGemm const& problem,
|
|
std::ostream& stream) const override
|
|
{
|
|
int gsu = problem.getParams().gsu() > 0 ? problem.getParams().gsu() : value[2];
|
|
gsu = gsu > 1 ? gsu : 1;
|
|
int numWG_x = static_cast<int>(
|
|
std::ceil(static_cast<float>(problem.freeSizeA(0)) / value[0])
|
|
);
|
|
int numWG_y = static_cast<int>(
|
|
std::ceil(static_cast<float>(problem.freeSizeB(0)) / value[1])
|
|
) * gsu;
|
|
|
|
std::vector<int> numWG = {numWG_x, numWG_y};
|
|
std::vector<int> clusterDim = {value[3], value[4]};
|
|
|
|
return debugEvalCmp(problem,
|
|
stream,
|
|
"prob's workgroup number [x, y]",
|
|
numWG,
|
|
"%",
|
|
"cluster dimension [x, y]",
|
|
clusterDim);
|
|
}
|
|
};
|
|
} // namespace Contraction
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
} // namespace Predicates
|
|
} // namespace TensileLite
|
|
|