Files
TheRock/rocm-libraries/projects/rocwmma/library/include/rocwmma/rocwmma.hpp
T
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

362 lines
18 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_API_HPP
#define ROCWMMA_API_HPP
#include "internal/accessors.hpp"
#include "internal/io_scheduler.hpp"
#include "internal/io_traits.hpp"
#include "internal/pack_util.hpp"
#include "internal/types.hpp"
/**
* \mainpage
*
* rocWMMA is a C++ header library for accelerating mixed precision matrix multiply-accumulate operations
* leveraging specialized GPU matrix cores on AMD's latest discrete GPUs. 'roc' being an AMD-specific
* component belonging to the ROCm ecosystem, and WMMA stands for Wavefront Mixed precision Multiply Accumulate.
*
* rocWMMA leverages modern C++ techniques. It is templated for modularity and uses meta-programming paradigms to provide opportunities for customization
* and compile-time inferences and optimizations. The API is seamless across supported CDNA and RDNA architectures. It is also portable with the Nvidia
* nvcuda::wmma library, allowing those users to easily migrate to the AMD platform.
*
* The API is implemented as GPU device code which empowers users with direct use of GPU matrix cores, right from their kernel code.
* Major benefits include kernel-level control which allows authoring flexibility and accessibility to compiler optimization passes in-situ
* with other device code. Users can therefore decide when and where kernel run-time launches are required, which is not dictated by the API.
*
* rocWMMA's API facilitates the decomposition of matrix multiply-accumulate problems into discretized blocks (also known as fragments) and enables
* parallelization of block-wise operations across multiple GPU wavefronts. The programmer's perspective is simplified to wavefront handling of fragments,
* whereas individual threads are handled internally. This can allow for faster development times and a more seamless experience across multiple architectures.
* API functions include data loading and storing, matrix multiply-accumulate and helper transforms that operate on data fragment abstractions. Moreover, data movement
* between global and local memory can be done cooperatively amongst the wavefronts in a threadblock to enable data sharing and re-use. Matrix multiply-accumulate
* functionality supports mixed precision inputs and outputs with native fixed-precision accumulation.
*
* Supporting code is required for GPU device management and kernel invocation. The kernel code samples and tests provided are built and launched via
* the Heterogeneous-Compute Interface for Portability (HIP) ecosystem within ROCm.
*
* This library is an ongoing Work-In-Progress (WIP).
*
* For more documentation, please visit https://rocm.docs.amd.com/projects/rocWMMA/en/latest/index.html.
*
*/
namespace rocwmma
{
//! @defgroup Rocwmma rocWMMA Public API
//!
//! @brief rocWMMA objects and API function definitions.
//! @{
//! @struct row_major
//! @brief Meta-tag indicating 2D in-memory data layout as row major.
struct row_major
{
};
//! @struct col_major
//! @brief Meta-tag indicating 2D in-memory data layout as column major.
struct col_major
{
};
//! @struct matrix_a
//! @brief Meta-tag indicating data context is input Matrix A.
struct matrix_a
{
};
//! @struct matrix_b
//! @brief Meta-tag indicating data context is input Matrix B.
struct matrix_b
{
};
//! @struct accumulator
//! @brief Meta-tag indicating data context is Accumulator (also used as Matrix C / D).
struct accumulator
{
};
//! @struct layout_t
//! @brief Runtime data layout tags
//! @var mem_row_major
//! @var mem_col_major
enum layout_t : uint32_t
{
mem_row_major,
mem_col_major
};
namespace fragment_scheduler
{
//! @typedef default_schedule
//! @brief The default fragment scheduler; each wave operates independently.
using default_schedule = IOScheduler::Default;
//! @typedef coop_row_major_2d
//! @brief A cooperative scheduling strategy where each wave in the 2d threadblock
//! will contribute to the fragment operation in row_major grid order.
//! All waves are scheduled in row_major order.
//! E.g. (TBlockX, TBlockY) => 2x2 waves
//! w0 = (0, 0), w1 = (0, 1),
//! w2 = (1, 0), w3 = (1, 1)
//! @tparam TBlockX the size of the thread-block in the X dimension
//! @tparam TBlockY the size of the thread-block in the Y dimension
template <uint32_t TBlockX, uint32_t TBlockY>
using coop_row_major_2d = IOScheduler::RowMajor2d<TBlockX, TBlockY>;
//! @typedef coop_col_major_2d
//! @brief A cooperative scheduling strategy where each wave in the 2d threadblock
//! will contribute to the fragment operation in col_major grid order.
//! All waves are scheduled in row_major order.
//! E.g. (TBlockX, TBlockY) => 2x2 waves
//! w0 = (0, 0), w2 = (0, 1),
//! w1 = (1, 0), w3 = (1, 1)
//! @tparam TBlockX the size of the thread-block in the X dimension
//! @tparam TBlockY the size of the thread-block in the Y dimension
template <uint32_t TBlockX, uint32_t TBlockY>
using coop_col_major_2d = IOScheduler::ColMajor2d<TBlockX, TBlockY>;
//! @typedef coop_row_slice_2d
//! @brief A cooperative scheduling strategy where each row of waves
//! in the 2d threadblock will contribute to the fragment operation.
//! Waves are partitioned into rows. Only waves in the same row
//! participate together.
//! E.g. (TBlockX, TBlockY) = 2x2 waves
//! RowSlice0: w0 = (0, 0), w1 = (0, 1)
//! RowSlice1: w0 = (1, 0), w1 = (1, 1)
//! @tparam TBlockX the size of the thread-block in the X dimension
//! @tparam TBlockY the size of the thread-block in the Y dimension
template <uint32_t TBlockX, uint32_t TBlockY>
using coop_row_slice_2d = IOScheduler::RowSlice2d<TBlockX, TBlockY>;
//! @typedef coop_col_slice_2d
//! @brief A cooperative scheduling strategy where each col of waves
//! in the 2d threadblock will contribute to the fragment operation.
//! Waves are partitioned into cols. Only waves in the same col
//! participate together.
//! E.g. (TBlockX, TBlockY) = 2x2 waves
//! ColSlice0: ColSlice1:
//! w0 = (0, 0), w0 = (0, 1),
//! w1 = (1, 0) w1 = (1, 1)
//! @tparam TBlockX the size of the thread-block in the X dimension
//! @tparam TBlockY the size of the thread-block in the Y dimension
template <uint32_t TBlockX, uint32_t TBlockY>
using coop_col_slice_2d = IOScheduler::ColSlice2d<TBlockX, TBlockY>;
//! @typedef single
//! @brief A cooperative scheduling strategy where only one wave in
//! the thread block will participate.
//! @tparam TBlockX the size of the thread-block in the X dimension
//! @tparam TBlockY the size of the thread-block in the Y dimension
//! @tparam WaveIdx the index of the wave which will participate
template <uint32_t TBlockX, uint32_t TBlockY, uint32_t WaveIdx = 0u>
using single = IOScheduler::Single<TBlockX, TBlockY, WaveIdx>;
} // namespace fragment_scheduler
//! @class fragment
//! @brief rocWMMA fragment class. This is the primary object used in block-wise decomposition of the matrix multiply-accumulate (mma)
//! problem space. In general, fragment data is associated with a matrix context (matrix_a, matrix_b or accumulator), a block size (BlockM/N/K),
//! a datatype (e.g. single-precision float, etc.) and an in-memory 2D layout (e.g. row_major or col_major). These fragment properties are used
//! to define how data is handled and stored locally, and to drive API implementations for loading / storing, mma and transforms. Fragment abstractions are
//! designed to promote a simple wavefront programming model, which can accelerate development time. Internal thread-level details are handled by rocWMMA
//! which frees the user to focus on wavefront block-wise decomposition. Written purely in device code, the programmer can use this object in their own
//! device kernels.
//!
//! @tparam MatrixT fragment context
//! @tparam FragM/N/K fragment dimensions
//! @tparam DataT datatype
//! @tparam DataLayoutT in-memory layout as col_major or row_major
//! @tparam Scheduler wave-wise scheduler
//! @note Fragments are stored in packed registers, however vector elements have no guaranteed order or locality.
template <typename MatrixT,
uint32_t FragM,
uint32_t FragN,
uint32_t FragK,
typename DataT,
typename DataLayoutT = void,
typename Scheduler = fragment_scheduler::default_schedule>
class __align__(4) fragment
{
public:
//! Input / output traits specific to AMDGCN architecture
using IOTraits =
typename IOConfig<MatrixT, FragM, FragN, FragK, DataT, DataLayoutT, Scheduler>::
IOTraits;
struct Traits
{
private:
//! The packed type for element data
using PackedElementT = typename PackTraits<DataT>::PackedT;
//! The unpacked type for element data
using UnpackedElementT = typename PackTraits<DataT>::UnpackedT;
//! WaveCount sizing factor for cooperative fragments
static constexpr uint32_t WaveCount = scheduler_traits<Scheduler>::WaveCount;
//! Assert the fragment occupies at least one packed register
static_assert(IOTraits::PackedVRegCount >= 1,
"Fragments must occupy at least one packed register");
//! Assert the fragment is equally splittable among the wave count
static_assert(WaveCount >= 1, "WaveCount must be at least 1 for a valid fragment");
static_assert(IOTraits::PackedVRegCount >= WaveCount,
"Packed register count must be equal to or greater than WaveCount");
static_assert(IOTraits::PackedVRegCount % WaveCount == 0,
"Packed register count must be divisible by WaveCount");
public:
constexpr static uint32_t Size = IOTraits::UnpackedSize / WaveCount;
//! Unpacked data access view
using AccessT = VecT<UnpackedElementT, Size>;
//! Packed data storage view
using StorageT = VecT<PackedElementT, IOTraits::PackedSize / WaveCount>;
static_assert(IOTraits::UnpackedSize % IOTraits::PackedSize == 0,
"Unable to pack fragment elements");
};
ROCWMMA_DEVICE fragment() = default;
ROCWMMA_DEVICE fragment(const fragment& other);
ROCWMMA_DEVICE fragment& operator=(const fragment& other);
//! @param index Element index
//! @returns Mutable unpacked element accessor at given index
ROCWMMA_DEVICE inline DataT& operator[](uint32_t index);
//! @param index Element index
//! @returns Immutable unpacked element accessor at given index
ROCWMMA_DEVICE inline DataT const& operator[](uint32_t index) const;
//! @returns Mutable packed storage vector accessor
ROCWMMA_DEVICE inline typename Traits::StorageT& operator*();
//! @returns Immutable packed storage vector accessor
ROCWMMA_DEVICE inline typename Traits::StorageT const& operator*() const;
//! @returns The geometric height of fragment
ROCWMMA_DEVICE constexpr static inline uint32_t height();
//! @returns The geometric width of fragment
ROCWMMA_DEVICE constexpr static inline uint32_t width();
//! @returns The leading block dimension (non-K)
ROCWMMA_DEVICE constexpr static inline uint32_t blockDim();
//! @returns The k dimension
ROCWMMA_DEVICE constexpr static inline uint32_t kDim();
//! @returns The size of the unpacked elements vector
ROCWMMA_DEVICE constexpr static inline uint32_t size();
//! Internal data storage views. Compatibility with nvcuda::wmma
union
{
typename Traits::StorageT mStorage; // Packed
typename Traits::AccessT mAccess; // Unpacked
typename Traits::AccessT::Native_vec_ x; // Nuanced access
static_assert(sizeof(typename Traits::AccessT) == sizeof(typename Traits::StorageT),
"Storage type and access type should be views into the same raw data");
};
// For compatibility
constexpr static uint32_t num_elements = Traits::Size;
using element_type = DataT;
};
//! Fills the entire fragment with the desired value.
//! @param frag Fragment of type MatrixT with its associated block sizes, data type and layout
//! @param value Fill value of type DataT
//! @tparam FragT Opaque fragment type
//! @tparam DataT Datatype
template <typename FragT, typename DataT>
ROCWMMA_DEVICE void fill_fragment(FragT& frag, DataT value);
//! Loads the entire fragment from the data pointer according to its matrix and data layout contexts. Data pointer may point to either local or global memory.
//! @param frag Fragment of type MatrixT with its associated block sizes, data type and layout
//! @param data Data pointer to global or local memory
//! @param ldm Leading dimension size
//! @tparam FragT Opaque fragment type
//! @tparam DataT Datatype
template <typename FragT, typename DataT>
ROCWMMA_DEVICE void load_matrix_sync(FragT& frag, const DataT* data, uint32_t ldm);
//! Loads the entire fragment from the data pointer according to its matrix layout and data layout contexts.
//! Data pointer may point to either local or global memory. This overload provides manual selection of data layout of the incoming memory pointer,
//! which will be transformed to conform to the data layout of the fragment.
//! @param frag Fragment of type MatrixT with its associated block sizes, data type and layout
//! @param data Data pointer to global/local memory
//! @param ldm Leading dimension size
//! @param layout Data layout
//! @tparam FragT Opaque fragment type
//! @tparam DataT Datatype
template <typename FragT, typename DataT>
ROCWMMA_DEVICE void
load_matrix_sync(FragT& frag, const DataT* data, uint32_t ldm, layout_t layout);
//! Stores the entire fragment to the data pointer according to its matrix and data layouts. Data pointer may point to either local or global memory.
//! @param frag Fragment of type MatrixT with its associated block sizes, data type and layout
//! @param data Data pointer to global/local memory
//! @param ldm Leading dimension size
//! @tparam FragT Opaque fragment type
//! @tparam DataT Datatype
template <typename FragT, typename DataT>
ROCWMMA_DEVICE void store_matrix_sync(DataT* data, FragT const& frag, uint32_t ldm);
//! Stores the entire fragment to the data pointer according to its matrix layout and data layout contexts.
//! Data pointer may point to either local or global memory. This overload provides manual selection of data layout of the outgoing memory pointer,
//! which the data layout of the fragment will be transformed to.
//! @param frag Fragment of type MatrixT with its associated block sizes, data type and layout
//! @param data Data pointer to global/local memory
//! @param ldm Leading dimension size
//! @param layout Data layout
//! @tparam FragT Opaque fragment type
//! @tparam DataT Datatype
template <typename FragT, typename DataT>
ROCWMMA_DEVICE void
store_matrix_sync(DataT* data, FragT const& frag, uint32_t ldm, layout_t layout);
//! Performs the Multiply-Accumulate operation on the fragments A, B, C and D (D = A * B + C)
//! @param d Accumulator output D
//! @param a Input fragment A
//! @param b Input fragment B
//! @param c Input accumulator fragment C
//! @tparam FragA Opaque fragment type for matrix A data
//! @tparam FragB Opaque fragment type for matrix A data
//! @tparam FragAccumIn Opaque fragment type for input accumulation data
//! @tparam FragAccumOut Opaque fragment type for output accumulation data
//! @note Frag c = d is valid
template <typename FragA, typename FragB, typename FragAccumIn, typename FragAccumOut>
ROCWMMA_DEVICE void mma_sync(FragAccumOut& d, FragA const& a, FragB const& b, FragAccumIn& c);
//! Synchronization point for all wavefronts in a workgroup. Guarantees pending reads / writes to LDS are flushed.
ROCWMMA_DEVICE ROCWMMA_INLINE void synchronize_workgroup();
/** @}*/
} // namespace rocwmma
#include "rocwmma_impl.hpp"
#endif // ROCWMMA_API_HPP