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

348 lines
12 KiB
C++

/*******************************************************************************
*
* MIT License
*
* Copyright (C) 2021-2025 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.
*
*******************************************************************************/
#ifndef ROCWMMA_KERNEL_GENERATOR_HPP
#define ROCWMMA_KERNEL_GENERATOR_HPP
#include <tuple>
#include <vector>
#include "hip_device.hpp"
#include <rocwmma/internal/types.hpp>
#include <rocwmma/internal/utility/sequence.hpp>
namespace rocwmma
{
///
/// TestParams: nested tuple of kernel parameters to build
/// a set of test kernels. E.g.
///
/// tuple< tuple<KernelParams0...>, tuple<KernelParams1...>, ...>;
///
/// KernelParams: tuple of Params to build a SINGLE kernel. E.g.
///
/// tuple<KernelParams...>;
///
/// Workflow:
///
/// 1. Build a set of testing kernels with TestParams.
///
/// 2. Map KernelParams to the kernel's template arguments.
/// This is the responsibility of the kernel generator
/// implementation (KernelGeneratorImpl).
///
/// 3. Instantiate each set of KernelParams with the impl,
/// and return a vector of kernels.
///
/// The following utilities are used to build (1).
/// - Concat<>
/// - CombineOne<>
/// - CombineMany<>
/// - CombineLists<>
///
/// for 2) and 3) KernelGenerator class takes the
/// KernelGeneratorImpl and instantiates one kernel
/// per tuple of KernelParams from TestParams (1). It
/// returns the kernels as a vector<KernelI>.
/// There are several classes that provide functionality
/// to build combinations of basic types.
///
/// Concat: Concatenation of types together.
/// E.g.
/// Concat( A ) = tuple<A>
/// Concat( A, B ) = tuple<A, B>
/// Concat( tuple<A>, B ) = tuple<A, B>
/// Concat( A, tuple<B> ) = tuple<A, B>
/// Concat( tuple<A>, tuple<B> ) = tuple<A, B>
/// Concat( A, B, C, ...) = tuple<A, B, C, ...>
template <typename... Args>
struct Concat;
template <typename Arg>
struct Concat<Arg>
{
using Result = decltype(std::make_tuple(Arg()));
};
template <typename... Args>
struct Concat<std::tuple<Args...>>
{
using Result = std::tuple<Args...>;
};
template <typename Lhs, typename Rhs, typename... Rest>
struct Concat<Lhs, Rhs, Rest...>
{
using Result = typename Concat<typename Concat<Lhs, Rhs>::Result, Rest...>::Result;
};
template <typename Lhs, typename Rhs>
struct Concat<Lhs, Rhs>
{
using Result = decltype(std::make_tuple(Lhs(), Rhs()));
};
template <typename Lhs, typename... Rhs>
struct Concat<Lhs, std::tuple<Rhs...>>
{
using Result = decltype(std::tuple_cat(std::make_tuple(Lhs()), std::tuple<Rhs...>()));
};
template <typename... Lhs, typename... Rhs>
struct Concat<std::tuple<Lhs...>, std::tuple<Rhs...>>
{
using Result = decltype(std::tuple_cat(std::tuple<Lhs...>(), std::tuple<Rhs...>()));
};
template <typename... Lhs, typename Rhs>
struct Concat<std::tuple<Lhs...>, Rhs>
{
using Result = decltype(std::tuple_cat(std::tuple<Lhs...>(), std::make_tuple(Rhs())));
};
/// CombineOne: Creates combinatorial pairs of LHS
/// with EACH type of RHS if RHS is a tuple.
/// NOTE: First level of tuples are collapsed into
/// nested tuples, as required by the generator.
///
/// E.g.
/// CombineOne( A, B ) = tuple< tuple<A, B> >
/// CombineOne( A, tuple<B> ) = tuple< tuple<A, B> >
/// CombineOne( A, tuple<B, C, D> ) = tuple< tuple<A, B>,
/// tuple<A, C>,
/// tuple<A, D>>
/// CombineOne( tuple<A, B>, tuple<C, D> ) = tuple< tuple<A, B, C>,
/// tuple<A, B, D>>
///
template <typename Lhs, typename Rhs>
struct CombineOne
{
using Result = decltype(std::make_tuple(typename Concat<Lhs, Rhs>::Result()));
};
template <typename Lhs, typename Rhs>
struct CombineOne<Lhs, std::tuple<Rhs>>
{
using Result = decltype(std::make_tuple(typename Concat<Lhs, Rhs>::Result()));
};
template <typename Lhs, typename Rhs0, typename... Rhs>
struct CombineOne<Lhs, std::tuple<Rhs0, Rhs...>>
{
using Mine = typename Concat<Lhs, Rhs0>::Result;
using Next = CombineOne<Lhs, std::tuple<Rhs...>>;
using Result = decltype(std::tuple_cat(std::make_tuple(Mine()), typename Next::Result()));
};
/// CombineMany: Creates combinatorial pairs two lists:
/// EACH type of LHS with EACH type of RHS.
/// NOTE: First level of tuples are collapsed into
/// nested tuples, as required by the generator.
///
/// E.g.
/// CombineMany( A, B ) = tuple< tuple<A, B> >
/// CombineMany( A, tuple<B> ) = tuple< tuple<A, B> >
/// CombineMany( A, tuple<B, C, D> ) = tuple< tuple<A, B>,
/// tuple<A, C>,
/// tuple<A, D>>
/// CombineMany( tuple<A, B>, tuple<C, D> ) = tuple< tuple<A, C>,
/// tuple<A, D>,
/// tuple<B, C>,
/// tuple<B, D>>
template <typename Lhs, typename Rhs>
struct CombineMany
{
using Result = typename CombineOne<Lhs, Rhs>::Result;
};
template <typename Lhs, typename Rhs>
struct CombineMany<std::tuple<Lhs>, Rhs>
{
using Result = typename CombineOne<Lhs, Rhs>::Result;
};
template <typename Lhs0, typename... Lhs, typename Rhs>
struct CombineMany<std::tuple<Lhs0, Lhs...>, Rhs>
{
using Mine = typename CombineOne<Lhs0, Rhs>::Result;
using Next = CombineMany<std::tuple<Lhs...>, Rhs>;
using Result = decltype(std::tuple_cat(Mine(), typename Next::Result()));
};
/// CombineLists: Creates combinatorial sets from multiple lists.
///
/// E.g:
/// CombineLists( tuple< tuple<A, B> >, tuple< tuple<C, D> > ) =
/// tuple< tuple<A, B, C, D> >
/// CombineLists( tuple< tuple<A, B>, tuple<C, D> >, tuple< tuple<E, F>, tuple<G, H> > ) =
/// tuple< tuple<A, B, E, F>, tuple<A, B, G, H>, tuple<C, D, E, F>, tuple<C, D, G, H> >
template <typename List0, typename... Lists>
struct CombineLists
{
using Result = typename CombineMany<List0, typename CombineLists<Lists...>::Result>::Result;
};
template <typename List>
struct CombineLists<List>
{
using Result = List;
};
// Override wrapper to apply to tuples
namespace detail
{
template <typename DataT, typename... TupleTs>
struct contains_type<DataT, std::tuple<TupleTs...>> : contains_type<DataT, TupleTs...>
{
};
} // namespace detail
/// Kernel Generator
/// Requires two inputs:
/// TestParams: nested tuple of KernelParams
/// GeneratorImpl: a generator class that
/// maps KernelParams to instantiation of the
/// actual kernel.
///
/// NOTE: The GeneratorImpl class decides the final
/// generated kernel instantiated type. This class
/// simply returns a vector of generated kernels of
/// this type.
template <typename TestParams, class GeneratorImpl>
struct KernelGenerator
{
template <typename... Ts>
ROCWMMA_HOST static void generate(Ts...)
{
}
};
template <typename KernelParams, typename... Next, class GeneratorImpl>
struct KernelGenerator<std::tuple<KernelParams, Next...>, GeneratorImpl>
{
using ResultT = std::vector<typename GeneratorImpl::ResultT>;
ROCWMMA_HOST static ResultT generate()
{
auto result = ResultT();
generate(result);
return result;
}
ROCWMMA_HOST static void generate(ResultT& kernels)
{
// Generates the kernel for the current set of KernelParams
auto gen_kernel
= [](ResultT& k) { k.push_back(GeneratorImpl::generate(KernelParams())); };
// Advances to the next set of KernelParams
auto next_kernel = [](ResultT& k) {
KernelGenerator<std::tuple<Next...>, GeneratorImpl>::generate(k);
};
if constexpr(contains_type_v<float8_t,
KernelParams> || contains_type_v<bfloat8_t, KernelParams>)
{
if constexpr(!(bool)ROCWMMA_FP8)
{
// Current KernelParams have f8: skip kernel on unsupported arch.
next_kernel(kernels);
return;
}
// Quirk: Here, the host code supports F8, but doesn't know
// if the runtime target supports it. Make sure the runtime
// target can support this type, otherwise don't generate the kernel.
if constexpr((bool)ROCWMMA_ARCH_HOST)
{
// Only gfx950 and gfx12 devices support f8
using DeviceInfo = HipDevice;
auto arch = DeviceInfo::instance()->getGcnArch();
if(arch != DeviceInfo::hipGcnArch_t::GFX950
&& arch != DeviceInfo::hipGcnArch_t::GFX1200
&& arch != DeviceInfo::hipGcnArch_t::GFX1201
&& arch != DeviceInfo::hipGcnArch_t::GFX1250)
{
// Current KernelParams have f8: skip kernel on host.
next_kernel(kernels);
return;
}
}
// Generate kernel
gen_kernel(kernels);
next_kernel(kernels);
}
else if constexpr(contains_type_v<
float8_fnuz_t,
KernelParams> || contains_type_v<bfloat8_fnuz_t, KernelParams>)
{
if constexpr(!(bool)ROCWMMA_FP8_FNUZ)
{
// Current KernelParams have f8_fnuz: skip kernel on unsupported arch.
next_kernel(kernels);
return;
}
// Quirk: Here, the host code supports F8_fnuz, but doesn't know
// if the runtime target supports it. Make sure the runtime
// target can support this type, otherwise don't generate the kernel.
if constexpr((bool)ROCWMMA_ARCH_HOST)
{
// Only gfx94* devices support f8_fnuz
using DeviceInfo = HipDevice;
auto arch = DeviceInfo::instance()->getGcnArch();
if(arch != DeviceInfo::hipGcnArch_t::GFX942)
{
// Current KernelParams have f8_fnuz: skip kernel on host.
next_kernel(kernels);
return;
}
}
// Generate kernel
gen_kernel(kernels);
next_kernel(kernels);
}
else
{
// Generate kernel
gen_kernel(kernels);
next_kernel(kernels);
}
}
};
} // namespace rocwmma
#endif // ROCWMMA_KERNEL_GENERATOR_HPP