Files
TheRock/rocm-libraries/projects/composablekernel/include/ck/utility/functional3.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

243 lines
8.5 KiB
C++

// Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
// SPDX-License-Identifier: MIT
#pragma once
#include "ck/ck.hpp"
#include "ck/utility/functional.hpp"
#include "ck/utility/functional2.hpp"
#include "ck/utility/sequence.hpp"
#include "ck/utility/multi_index.hpp"
#include "ck/utility/math.hpp"
namespace ck {
namespace detail {
/**
* @brief Common base class for static_ford and ford.
*
* Provides shared compile-time constants and type aliases used by both
* static_ford (compile-time iteration) and ford (runtime iteration).
*
* @tparam Lengths Sequence<L0, L1, ...> specifying the size of each dimension
* @tparam Orders Sequence<O0, O1, ...> specifying the iteration order of dimensions.
* Orders[i] indicates which dimension is iterated at loop level i.
*/
template <class Lengths, class Orders>
struct ford_base
{
/// Number of dimensions
static constexpr index_t NDim = Lengths::Size();
/// Total number of iterations (product of all lengths)
static constexpr index_t TotalSize =
reduce_on_sequence(Lengths{}, math::multiplies{}, Number<1>{});
/// Lengths reordered according to iteration order
static constexpr auto OrderedLengths = Lengths::ReorderGivenNew2Old(Orders{});
/// Type of OrderedLengths with cv-qualifiers removed
using OrderedLengthsType = remove_cvref_t<decltype(OrderedLengths)>;
/// Mapping from loop level ("new" index) to original dimension ("old" index)
using New2Old = Orders;
__host__ __device__ constexpr ford_base()
{
static_assert(Lengths::GetSize() > 0, "wrong! Lengths is empty");
static_assert(Lengths::GetSize() == Orders::GetSize(), "wrong! inconsistent size");
}
};
/**
* @brief Helper for decomposing a linear index into multi-dimensional indices.
*
* Computes strides at compile time and provides both compile-time and runtime
* index decomposition. Used by static_ford and ford to convert a flat iteration
* index into N-dimensional coordinates.
*
* For OrderedLengths = Sequence<L0, L1, L2>:
* - strides = {L1*L2, L2, 1}
* - ordered_idx[i] = (linear_idx / strides[i]) % lengths[i]
*
* @tparam OrderedLengths Sequence<...> of dimension sizes in iteration order
* @tparam IndexSeq Sequence<0, 1, ..., NDim-1> for pack expansion
*/
template <class OrderedLengths, class IndexSeq>
struct index_decomposer;
template <index_t... Ls, index_t... Is>
struct index_decomposer<Sequence<Ls...>, Sequence<Is...>>
{
/// Number of dimensions
static constexpr index_t NDim = sizeof...(Ls);
/// Dimension lengths in iteration order
static constexpr index_array<NDim> lengths = {{Ls...}};
/**
* @brief Compute all strides in a single O(N) pass.
*
* For dimensions with lengths [L0, L1, L2, ...]:
* strides[N-1] = 1
* strides[i] = strides[i+1] * lengths[i+1]
*
* @return index_array containing computed strides
*/
static constexpr index_array<NDim> compute_all_strides()
{
index_array<NDim> result{};
if constexpr(NDim > 0)
{
result[NDim - 1] = 1;
for(index_t i = NDim - 2; i >= 0; --i)
{
result[i] = result[i + 1] * lengths[i + 1];
}
}
return result;
}
/// Pre-computed strides for each dimension
static constexpr index_array<NDim> strides = compute_all_strides();
/**
* @brief Compile-time decomposition of a linear index.
*
* Returns a Sequence containing the multi-dimensional indices
* in iteration order.
*
* @tparam LinearIdx The linear index to decompose (compile-time constant)
*/
template <index_t LinearIdx>
using decompose = Sequence<((LinearIdx / strides[Is]) % lengths[Is])...>;
/**
* @brief Runtime decomposition of a linear index with reordering.
*
* Decomposes linear_idx into ordered indices, then reorders them
* to the original dimension order and stores in result.
*
* @tparam New2Old Sequence mapping iteration position to original dimension
* @tparam MultiIndex Type of the output multi-index container
* @param linear_idx The linear index to decompose
* @param[out] result Multi-index container to store the result
*/
template <class New2Old, class MultiIndex>
__host__ __device__ static void decompose_runtime(index_t linear_idx, MultiIndex& result)
{
// Compute ordered indices and assign to result in original dimension order
((result(Number<New2Old::At(Number<Is>{})>{}) = (linear_idx / strides[Is]) % lengths[Is]),
...);
}
};
} // namespace detail
/**
* @brief Compile-time N-dimensional loop with static multi-indices.
*
* Iterates over an N-dimensional space where dimensions have sizes specified
* by Lengths. The iteration order is controlled by Orders. Each iteration
* provides a compile-time Sequence containing the current multi-index.
*
* Uses O(1) template instantiation depth via flat loop with index decomposition,
* avoiding recursive template structures.
*
* Example:
* @code
* // Iterate over 2x3 space in row-major order (dim 0 outer, dim 1 inner)
* static_ford<Sequence<2, 3>>{}([](auto multi_id) {
* constexpr index_t i = multi_id[Number<0>{}]; // 0, 0, 0, 1, 1, 1
* constexpr index_t j = multi_id[Number<1>{}]; // 0, 1, 2, 0, 1, 2
* });
*
* // Column-major order (dim 1 outer, dim 0 inner)
* static_ford<Sequence<2, 3>, Sequence<1, 0>>{}([](auto multi_id) {
* // Visits: (0,0), (1,0), (0,1), (1,1), (0,2), (1,2)
* });
* @endcode
*
* @tparam Lengths Sequence<L0, L1, ...> specifying dimension sizes
* @tparam Orders Sequence<O0, O1, ...> specifying iteration order
* (default: Sequence<0, 1, ..., N-1> for row-major)
*/
template <class Lengths, class Orders = make_index_sequence<Lengths::GetSize()>>
struct static_ford : detail::ford_base<Lengths, Orders>
{
using Base = detail::ford_base<Lengths, Orders>;
using Decomposer = detail::index_decomposer<typename Base::OrderedLengthsType,
make_index_sequence<Base::NDim>>;
/**
* @brief Execute the N-dimensional loop.
*
* Calls f with a compile-time Sequence<i0, i1, ...> for each point
* in the iteration space.
*
* @tparam F Functor type with signature F(Sequence<...>)
* @param f The functor to call for each multi-index
*/
template <class F>
__host__ __device__ constexpr void operator()(F f) const
{
static_for<0, Base::TotalSize, 1>{}([&](auto linear_idx) {
using OrderedIdx = typename Decomposer::template decompose<linear_idx.value>;
f(OrderedIdx::ReorderGivenOld2New(Orders{}));
});
}
};
/**
* @brief Runtime N-dimensional loop with runtime multi-indices.
*
* Iterates over an N-dimensional space where dimensions have sizes specified
* by Lengths. The iteration order is controlled by Orders. Each iteration
* provides a runtime multi-index container.
*
* Uses O(1) template instantiation depth via flat for-loop with index decomposition,
* avoiding recursive template structures.
*
* Example:
* @code
* // Iterate over 2x3 space in row-major order
* ford<Sequence<2, 3>>{}([](auto multi_id) {
* index_t i = multi_id[Number<0>{}]; // Runtime values
* index_t j = multi_id[Number<1>{}];
* });
* @endcode
*
* @tparam Lengths Sequence<L0, L1, ...> specifying dimension sizes
* @tparam Orders Sequence<O0, O1, ...> specifying iteration order
* (default: Sequence<0, 1, ..., N-1> for row-major)
*/
template <class Lengths, class Orders = make_index_sequence<Lengths::GetSize()>>
struct ford : detail::ford_base<Lengths, Orders>
{
using Base = detail::ford_base<Lengths, Orders>;
using Decomposer = detail::index_decomposer<typename Base::OrderedLengthsType,
make_index_sequence<Base::NDim>>;
/**
* @brief Execute the N-dimensional loop.
*
* Calls f with a runtime multi-index for each point in the iteration space.
*
* @tparam F Functor type with signature F(MultiIndex)
* @param f The functor to call for each multi-index
*/
template <class F>
__host__ __device__ constexpr void operator()(F f) const
{
for(index_t linear_idx = 0; linear_idx < Base::TotalSize; ++linear_idx)
{
auto multi_id = make_zero_multi_index<Base::NDim>();
Decomposer::template decompose_runtime<Orders>(linear_idx, multi_id);
f(multi_id);
}
}
};
} // namespace ck