Files
project_6/cccl_upstream/cub/cub/warp/warp_load.cuh
EngineX CI 56fd68e7dd [INFRA] Import NVIDIA/CCCL upstream as optimization reference library
CCCL (CUDA C++ Core Libraries) provides:
- CUB: device/block/warp-level GPU primitives (reduce, scan, sort, topk)
- Thrust: high-level parallel algorithms (transform_reduce, sort, scan)
- libcudacxx: CUDA C++ standard library (atomics, barriers, memory)
- cudax: experimental features (memory resources, allocators)
- Tuning policies: per-SM hardware-specific algorithm parameters

Competition optimization vectors mapped to CCCL:
- Output TPS (83% weight): warp_reduce, block_reduce, device_topk
- Input TPS (14% weight): device_scan, block_load, prefetch
- Cache TPS (3% weight): prefix caching strategy patterns
- Memory (0.9 util): pooled/cached/buddy allocators

Source: https://github.com/NVIDIA/cccl (shallow clone, HEAD only)
License: Apache-2.0
2026-07-30 09:35:51 +00:00

648 lines
24 KiB
Plaintext

// SPDX-FileCopyrightText: Copyright (c) 2011-2021, NVIDIA CORPORATION. All rights reserved.
// SPDX-License-Identifier: BSD-3
//! @file
//! Operations for reading linear tiles of data into the CUDA warp.
#pragma once
#include <cub/config.cuh>
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
# pragma GCC system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
# pragma clang system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
# pragma system_header
#endif // no system header
#include <cub/block/block_load.cuh>
#include <cub/iterator/cache_modified_input_iterator.cuh>
#include <cub/util_ptx.cuh>
#include <cub/util_type.cuh>
#include <cub/warp/warp_exchange.cuh>
#include <cuda/__cmath/pow2.h>
#include <cuda/__ptx/instructions/get_sreg.h>
#include <cuda/std/__concepts/same_as.h>
#include <cuda/std/__fwd/format.h>
#include <cuda/std/__host_stdlib/ostream>
CUB_NAMESPACE_BEGIN
//! @rst
//! ``cub::WarpLoadAlgorithm`` enumerates alternative algorithms for :cpp:struct:`cub::WarpLoad` to
//! read a linear segment of data from memory into a CUDA warp.
//! @endrst
enum WarpLoadAlgorithm
{
//! @rst
//! Overview
//! ++++++++++++++++++++++++++
//!
//! A :ref:`blocked arrangement <flexible-data-arrangement>` of data is read directly from memory.
//!
//! Performance Considerations
//! ++++++++++++++++++++++++++
//!
//! The utilization of memory transactions (coalescing) decreases as the
//! access stride between threads increases (i.e., the number items per thread).
//! @endrst
WARP_LOAD_DIRECT,
//! @rst
//! Overview
//! ++++++++++++++++++++++++++
//!
//! A :ref:`striped arrangement <flexible-data-arrangement>` of data is read directly from memory.
//!
//! Performance Considerations
//! ++++++++++++++++++++++++++
//!
//! The utilization of memory transactions (coalescing) doesn't depend on
//! the number of items per thread.
//! @endrst
WARP_LOAD_STRIPED,
//! @rst
//! Overview
//! ++++++++++++++++++++++++++
//!
//! A :ref:`blocked arrangement <flexible-data-arrangement>` of data is read from memory using
//! CUDA's built-in vectorized loads as a coalescing optimization.
//! For example, ``ld.global.v4.s32`` instructions will be generated when ``T = int`` and
//! ``ITEMS_PER_THREAD % 4 == 0``.
//!
//! Performance Considerations
//! ++++++++++++++++++++++++++
//!
//! - The utilization of memory transactions (coalescing) remains high until the the
//! access stride between threads (i.e., the number items per thread) exceeds the
//! maximum vector load width (typically 4 items or 64B, whichever is lower).
//! - The following conditions will prevent vectorization and loading will fall
//! back to cub::WARP_LOAD_DIRECT:
//!
//! - ``ITEMS_PER_THREAD`` is odd
//! - The ``InputIteratorT`` is not a simple pointer type
//! - The block input offset is not quadword-aligned
//! - The data type ``T`` is not a built-in primitive or CUDA vector type
//! (e.g., ``short``, ``int2``, ``double``, ``float2``, etc.)
//! @endrst
WARP_LOAD_VECTORIZE,
//! @rst
//! Overview
//! ++++++++++++++++++++++++++
//!
//! A :ref:`striped arrangement <flexible-data-arrangement>` of data is read efficiently from
//! memory and then locally transposed into a
//! :ref:`blocked arrangement <flexible-data-arrangement>`.
//!
//! Performance Considerations
//! ++++++++++++++++++++++++++
//!
//! - The utilization of memory transactions (coalescing) remains high
//! regardless of items loaded per thread.
//! - The local reordering incurs slightly longer latencies and throughput than the direct
//! ``cub::WARP_LOAD_DIRECT`` and ``cub::WARP_LOAD_VECTORIZE`` alternatives.
//! @endrst
WARP_LOAD_TRANSPOSE
};
#if _CCCL_HOSTED()
namespace detail
{
[[nodiscard]] _CCCL_HOST_DEVICE_API constexpr const char* to_string(WarpLoadAlgorithm algo) noexcept
{
switch (algo)
{
case WARP_LOAD_DIRECT:
return "WARP_LOAD_DIRECT";
case WARP_LOAD_STRIPED:
return "WARP_LOAD_STRIPED";
case WARP_LOAD_VECTORIZE:
return "WARP_LOAD_VECTORIZE";
case WARP_LOAD_TRANSPOSE:
return "WARP_LOAD_TRANSPOSE";
}
return "<unknown WarpLoadAlgorithm>";
}
} // namespace detail
#endif // _CCCL_HOSTED()
#if _CCCL_HOSTED()
inline ::std::ostream& operator<<(::std::ostream& os, WarpLoadAlgorithm algo)
{
return os << CUB_NS_QUALIFIER::detail::to_string(algo);
}
#endif // _CCCL_HOSTED() && !_CCCL_DOXYGEN_INVOKED
CUB_NAMESPACE_END
#if __cpp_lib_format >= 201907L && !defined(_CCCL_DOXYGEN_INVOKED)
template <::cuda::std::same_as<char> CharT>
struct std::formatter<CUB_NS_QUALIFIER::WarpLoadAlgorithm, CharT> : formatter<const CharT*, CharT>
{
template <class FmtCtx>
auto format(const CUB_NS_QUALIFIER::WarpLoadAlgorithm& algo, FmtCtx& ctx) const
{
return formatter<const CharT*, CharT>::format(CUB_NS_QUALIFIER::detail::to_string(algo), ctx);
}
};
#endif // __cpp_lib_format >= 201907L && !defined(_CCCL_DOXYGEN_INVOKED)
CUB_NAMESPACE_BEGIN
//! @rst
//! The WarpLoad class provides :ref:`collective <collective-primitives>` data movement methods for
//! loading a linear segment of items from memory into a
//! :ref:`blocked arrangement <flexible-data-arrangement>` across a CUDA thread warp.
//!
//! Overview
//! ++++++++++++++++
//!
//! - The WarpLoad class provides a single data movement abstraction that can be
//! specialized to implement different cub::WarpLoadAlgorithm strategies. This
//! facilitates different performance policies for different architectures, data
//! types, granularity sizes, etc.
//! - WarpLoad can be optionally specialized by different data movement strategies:
//!
//! #. :cpp:enumerator:`cub::WARP_LOAD_DIRECT`:
//! a :ref:`blocked arrangement <flexible-data-arrangement>` of data is read directly from
//! memory.
//! #. :cpp:enumerator:`cub::WARP_LOAD_STRIPED`:
//! a :ref:`striped arrangement <flexible-data-arrangement>` of data is read directly from
//! memory.
//! #. :cpp:enumerator:`cub::WARP_LOAD_VECTORIZE`:
//! a :ref:`blocked arrangement <flexible-data-arrangement>` of data is read directly from
//! memory using CUDA's built-in vectorized loads as a coalescing optimization.
//! #. :cpp:enumerator:`cub::WARP_LOAD_TRANSPOSE`:
//! a :ref:`striped arrangement <flexible-data-arrangement>` of data is read directly from
//! memory and is then locally transposed into a
//! :ref:`blocked arrangement <flexible-data-arrangement>`.
//!
//! A Simple Example
//! ++++++++++++++++
//!
//! The code snippet below illustrates the loading of a linear segment of 64
//! integers into a "blocked" arrangement across 16 threads where each thread
//! owns 4 consecutive items. The load is specialized for ``WARP_LOAD_TRANSPOSE``,
//! meaning memory references are efficiently coalesced using a warp-striped access
//! pattern (after which items are locally reordered among threads).
//!
//! .. code-block:: c++
//!
//! #include <cub/cub.cuh> // or equivalently <cub/warp/warp_load.cuh>
//!
//! __global__ void ExampleKernel(int *d_data, ...)
//! {
//! constexpr int warp_threads = 16;
//! constexpr int threads_per_block = 256;
//! constexpr int items_per_thread = 4;
//!
//! // Specialize WarpLoad for a warp of 16 threads owning 4 integer items each
//! using WarpLoadT = WarpLoad<int,
//! items_per_thread,
//! cub::WARP_LOAD_TRANSPOSE,
//! warp_threads>;
//!
//! constexpr int warps_in_block = threads_per_block / warp_threads;
//! constexpr int tile_size = items_per_thread * warp_threads;
//! const int warp_id = static_cast<int>(threadIdx.x) / warp_threads;
//!
//! // Allocate shared memory for WarpLoad
//! __shared__ typename WarpLoadT::TempStorage temp_storage[warps_in_block];
//!
//! // Load a segment of consecutive items that are blocked across threads
//! int thread_data[items_per_thread];
//! WarpLoadT(temp_storage[warp_id]).Load(d_data + warp_id * tile_size, thread_data);
//! }
//!
//! Suppose the input ``d_data`` is ``0, 1, 2, 3, 4, 5, ...``.
//! The set of ``thread_data`` across the first logical warp of threads in those
//! threads will be: ``{ [0,1,2,3], [4,5,6,7], ..., [60,61,62,63] }``.
//! @endrst
//!
//! @tparam InputT
//! The data type to read into (which must be convertible from the input
//! iterator's value type).
//!
//! @tparam ITEMS_PER_THREAD
//! The number of consecutive items partitioned onto each thread.
//!
//! @tparam ALGORITHM
//! <b>[optional]</b> cub::WarpLoadAlgorithm tuning policy.
//! default: cub::WARP_LOAD_DIRECT.
//!
//! @tparam LOGICAL_WARP_THREADS
//! <b>[optional]</b> The number of threads per "logical" warp (may be less
//! than the number of hardware warp threads). Default is the warp size of the
//! targeted CUDA compute-capability (e.g., 32 threads for SM86). Must be a
//! power of two.
//!
template <typename InputT,
int ITEMS_PER_THREAD,
WarpLoadAlgorithm ALGORITHM = WARP_LOAD_DIRECT,
int LOGICAL_WARP_THREADS = detail::warp_threads>
class WarpLoad
{
static constexpr bool IS_ARCH_WARP = LOGICAL_WARP_THREADS == detail::warp_threads;
static_assert(::cuda::is_power_of_two(LOGICAL_WARP_THREADS), "LOGICAL_WARP_THREADS must be a power of two");
private:
/*****************************************************************************
* Algorithmic variants
****************************************************************************/
/// Load helper
template <WarpLoadAlgorithm _POLICY, int DUMMY>
struct LoadInternal;
template <int DUMMY>
struct LoadInternal<WARP_LOAD_DIRECT, DUMMY>
{
using TempStorage = NullType;
int linear_tid;
_CCCL_DEVICE _CCCL_FORCEINLINE LoadInternal(TempStorage& /*temp_storage*/, int linear_tid)
: linear_tid(linear_tid)
{}
template <typename InputIteratorT>
_CCCL_DEVICE _CCCL_FORCEINLINE void Load(InputIteratorT block_itr, InputT (&items)[ITEMS_PER_THREAD])
{
LoadDirectBlocked(linear_tid, block_itr, items);
}
template <typename InputIteratorT>
_CCCL_DEVICE _CCCL_FORCEINLINE void
Load(InputIteratorT block_itr, InputT (&items)[ITEMS_PER_THREAD], int valid_items)
{
LoadDirectBlocked(linear_tid, block_itr, items, valid_items);
}
template <typename InputIteratorT, typename DefaultT>
_CCCL_DEVICE _CCCL_FORCEINLINE void
Load(InputIteratorT block_itr, InputT (&items)[ITEMS_PER_THREAD], int valid_items, DefaultT oob_default)
{
LoadDirectBlocked(linear_tid, block_itr, items, valid_items, oob_default);
}
};
template <int DUMMY>
struct LoadInternal<WARP_LOAD_STRIPED, DUMMY>
{
using TempStorage = NullType;
int linear_tid;
_CCCL_DEVICE _CCCL_FORCEINLINE LoadInternal(TempStorage& /*temp_storage*/, int linear_tid)
: linear_tid(linear_tid)
{}
template <typename InputIteratorT>
_CCCL_DEVICE _CCCL_FORCEINLINE void Load(InputIteratorT block_itr, InputT (&items)[ITEMS_PER_THREAD])
{
LoadDirectStriped<LOGICAL_WARP_THREADS>(linear_tid, block_itr, items);
}
template <typename InputIteratorT>
_CCCL_DEVICE _CCCL_FORCEINLINE void
Load(InputIteratorT block_itr, InputT (&items)[ITEMS_PER_THREAD], int valid_items)
{
LoadDirectStriped<LOGICAL_WARP_THREADS>(linear_tid, block_itr, items, valid_items);
}
template <typename InputIteratorT, typename DefaultT>
_CCCL_DEVICE _CCCL_FORCEINLINE void
Load(InputIteratorT block_itr, InputT (&items)[ITEMS_PER_THREAD], int valid_items, DefaultT oob_default)
{
LoadDirectStriped<LOGICAL_WARP_THREADS>(linear_tid, block_itr, items, valid_items, oob_default);
}
};
template <int DUMMY>
struct LoadInternal<WARP_LOAD_VECTORIZE, DUMMY>
{
using TempStorage = NullType;
int linear_tid;
_CCCL_DEVICE _CCCL_FORCEINLINE LoadInternal(TempStorage& /*temp_storage*/, int linear_tid)
: linear_tid(linear_tid)
{}
_CCCL_DEVICE _CCCL_FORCEINLINE void Load(InputT* block_ptr, InputT (&items)[ITEMS_PER_THREAD])
{
InternalLoadDirectBlockedVectorized<LOAD_DEFAULT>(linear_tid, block_ptr, items);
}
_CCCL_DEVICE _CCCL_FORCEINLINE void Load(const InputT* block_ptr, InputT (&items)[ITEMS_PER_THREAD])
{
InternalLoadDirectBlockedVectorized<LOAD_DEFAULT>(linear_tid, block_ptr, items);
}
template <CacheLoadModifier MODIFIER, typename ValueType, typename OffsetT>
_CCCL_DEVICE _CCCL_FORCEINLINE void
Load(CacheModifiedInputIterator<MODIFIER, ValueType, OffsetT> block_itr, InputT (&items)[ITEMS_PER_THREAD])
{
InternalLoadDirectBlockedVectorized<MODIFIER>(linear_tid, block_itr.ptr, items);
}
template <typename _InputIteratorT>
_CCCL_DEVICE _CCCL_FORCEINLINE void Load(_InputIteratorT block_itr, InputT (&items)[ITEMS_PER_THREAD])
{
LoadDirectBlocked(linear_tid, block_itr, items);
}
template <typename InputIteratorT>
_CCCL_DEVICE _CCCL_FORCEINLINE void
Load(InputIteratorT block_itr, InputT (&items)[ITEMS_PER_THREAD], int valid_items)
{
LoadDirectBlocked(linear_tid, block_itr, items, valid_items);
}
template <typename InputIteratorT, typename DefaultT>
_CCCL_DEVICE _CCCL_FORCEINLINE void
Load(InputIteratorT block_itr, InputT (&items)[ITEMS_PER_THREAD], int valid_items, DefaultT oob_default)
{
LoadDirectBlocked(linear_tid, block_itr, items, valid_items, oob_default);
}
};
template <int DUMMY>
struct LoadInternal<WARP_LOAD_TRANSPOSE, DUMMY>
{
using WarpExchangeT = WarpExchange<InputT, ITEMS_PER_THREAD, LOGICAL_WARP_THREADS>;
struct _TempStorage : WarpExchangeT::TempStorage
{};
struct TempStorage : Uninitialized<_TempStorage>
{};
_TempStorage& temp_storage;
int linear_tid;
_CCCL_DEVICE _CCCL_FORCEINLINE LoadInternal(TempStorage& temp_storage, int linear_tid)
: temp_storage(temp_storage.Alias())
, linear_tid(linear_tid)
{}
template <typename InputIteratorT>
_CCCL_DEVICE _CCCL_FORCEINLINE void Load(InputIteratorT block_itr, InputT (&items)[ITEMS_PER_THREAD])
{
LoadDirectStriped<LOGICAL_WARP_THREADS>(linear_tid, block_itr, items);
WarpExchangeT(temp_storage).StripedToBlocked(items, items);
}
template <typename InputIteratorT>
_CCCL_DEVICE _CCCL_FORCEINLINE void
Load(InputIteratorT block_itr, InputT (&items)[ITEMS_PER_THREAD], int valid_items)
{
LoadDirectStriped<LOGICAL_WARP_THREADS>(linear_tid, block_itr, items, valid_items);
WarpExchangeT(temp_storage).StripedToBlocked(items, items);
}
template <typename InputIteratorT, typename DefaultT>
_CCCL_DEVICE _CCCL_FORCEINLINE void
Load(InputIteratorT block_itr, InputT (&items)[ITEMS_PER_THREAD], int valid_items, DefaultT oob_default)
{
LoadDirectStriped<LOGICAL_WARP_THREADS>(linear_tid, block_itr, items, valid_items, oob_default);
WarpExchangeT(temp_storage).StripedToBlocked(items, items);
}
};
/*****************************************************************************
* Type definitions
****************************************************************************/
/// Internal load implementation to use
using InternalLoad = LoadInternal<ALGORITHM, 0>;
/// Shared memory storage layout type
using _TempStorage = typename InternalLoad::TempStorage;
/*****************************************************************************
* Utility methods
****************************************************************************/
/// Internal storage allocator
_CCCL_DEVICE _CCCL_FORCEINLINE _TempStorage& PrivateStorage()
{
__shared__ _TempStorage private_storage;
return private_storage;
}
/*****************************************************************************
* Thread fields
****************************************************************************/
/// Thread reference to shared storage
_TempStorage& temp_storage;
/// Linear thread-id
int linear_tid;
public:
/// @smemstorage{WarpLoad}
struct TempStorage : Uninitialized<_TempStorage>
{};
//! @name Collective constructors
//! @{
//! @brief Collective constructor using a private static allocation of
//! shared memory as temporary storage.
_CCCL_DEVICE _CCCL_FORCEINLINE WarpLoad()
: temp_storage(PrivateStorage())
, linear_tid(
IS_ARCH_WARP ? ::cuda::ptx::get_sreg_laneid() : (::cuda::ptx::get_sreg_laneid() % LOGICAL_WARP_THREADS))
{}
//! @brief Collective constructor using the specified memory allocation as
//! temporary storage.
_CCCL_DEVICE _CCCL_FORCEINLINE WarpLoad(TempStorage& temp_storage)
: temp_storage(temp_storage.Alias())
, linear_tid(
IS_ARCH_WARP ? ::cuda::ptx::get_sreg_laneid() : (::cuda::ptx::get_sreg_laneid() % LOGICAL_WARP_THREADS))
{}
//! @}
//! @name Data movement
//! @{
//! @rst
//! Load a linear segment of items from memory.
//!
//! .. versionadded:: 2.2.0
//! First appears in CUDA Toolkit 12.3.
//!
//! @smemwarpreuse
//!
//! Snippet
//! +++++++
//!
//! .. code-block:: c++
//!
//! #include <cub/cub.cuh> // or equivalently <cub/warp/warp_load.cuh>
//!
//! __global__ void ExampleKernel(int *d_data, ...)
//! {
//! constexpr int warp_threads = 16;
//! constexpr int threads_per_block = 256;
//! constexpr int items_per_thread = 4;
//!
//! // Specialize WarpLoad for a warp of 16 threads owning 4 integer items each
//! using WarpLoadT = WarpLoad<int,
//! items_per_thread,
//! cub::WARP_LOAD_TRANSPOSE,
//! warp_threads>;
//!
//! constexpr int warps_in_block = threads_per_block / warp_threads;
//! constexpr int tile_size = items_per_thread * warp_threads;
//! const int warp_id = static_cast<int>(threadIdx.x) / warp_threads;
//!
//! // Allocate shared memory for WarpLoad
//! __shared__ typename WarpLoadT::TempStorage temp_storage[warps_in_block];
//!
//! // Load a segment of consecutive items that are blocked across threads
//! int thread_data[items_per_thread];
//! WarpLoadT(temp_storage[warp_id]).Load(d_data + warp_id * tile_size, thread_data);
//! }
//!
//! Suppose the input ``d_data`` is ``0, 1, 2, 3, 4, 5, ...``,
//! The set of ``thread_data`` across the first logical warp of threads in those
//! threads will be: ``{ [0,1,2,3], [4,5,6,7], ..., [60,61,62,63] }``.
//! @endrst
//!
//! @param[in] block_itr The thread block's base input iterator for loading from
//! @param[out] items Data to load
template <typename InputIteratorT>
_CCCL_DEVICE _CCCL_FORCEINLINE void Load(InputIteratorT block_itr, InputT (&items)[ITEMS_PER_THREAD])
{
InternalLoad(temp_storage, linear_tid).Load(block_itr, items);
}
//! @rst
//! Load a linear segment of items from memory, guarded by range.
//!
//! .. versionadded:: 2.2.0
//! First appears in CUDA Toolkit 12.3.
//!
//! @smemwarpreuse
//!
//! Snippet
//! +++++++
//!
//! .. code-block:: c++
//!
//! #include <cub/cub.cuh> // or equivalently <cub/warp/warp_load.cuh>
//!
//! __global__ void ExampleKernel(int *d_data, int valid_items, ...)
//! {
//! constexpr int warp_threads = 16;
//! constexpr int threads_per_block = 256;
//! constexpr int items_per_thread = 4;
//!
//! // Specialize WarpLoad for a warp of 16 threads owning 4 integer items each
//! using WarpLoadT = WarpLoad<int,
//! items_per_thread,
//! cub::WARP_LOAD_TRANSPOSE,
//! warp_threads>;
//!
//! constexpr int warps_in_block = threads_per_block / warp_threads;
//! constexpr int tile_size = items_per_thread * warp_threads;
//! const int warp_id = static_cast<int>(threadIdx.x) / warp_threads;
//!
//! // Allocate shared memory for WarpLoad
//! __shared__ typename WarpLoadT::TempStorage temp_storage[warps_in_block];
//!
//! // Load a segment of consecutive items that are blocked across threads
//! int thread_data[items_per_thread];
//! WarpLoadT(temp_storage[warp_id]).Load(d_data + warp_id * tile_size, thread_data,
//! valid_items);
//! }
//!
//! Suppose the input ``d_data`` is ``0, 1, 2, 3, 4, 5, ...`` and ``valid_items`` is ``5``.
//! The set of ``thread_data`` across the first logical warp of threads in those threads will be:
//! ``{ [0,1,2,3], [4,?,?,?], ..., [?,?,?,?] }`` with only the first two threads being unmasked to
//! load portions of valid data (and other items remaining unassigned).
//! @endrst
//!
//! @param[in] block_itr The thread block's base input iterator for loading from
//! @param[out] items Data to load
//! @param[in] valid_items Number of valid items to load
template <typename InputIteratorT>
_CCCL_DEVICE _CCCL_FORCEINLINE void Load(InputIteratorT block_itr, InputT (&items)[ITEMS_PER_THREAD], int valid_items)
{
InternalLoad(temp_storage, linear_tid).Load(block_itr, items, valid_items);
}
//! @rst
//! Load a linear segment of items from memory, guarded by range.
//!
//! .. versionadded:: 2.2.0
//! First appears in CUDA Toolkit 12.3.
//!
//! @smemwarpreuse
//!
//! Snippet
//! +++++++
//!
//! .. code-block:: c++
//!
//! #include <cub/cub.cuh> // or equivalently <cub/warp/warp_load.cuh>
//!
//! __global__ void ExampleKernel(int *d_data, int valid_items, ...)
//! {
//! constexpr int warp_threads = 16;
//! constexpr int threads_per_block = 256;
//! constexpr int items_per_thread = 4;
//!
//! // Specialize WarpLoad for a warp of 16 threads owning 4 integer items each
//! using WarpLoadT = WarpLoad<int,
//! items_per_thread,
//! cub::WARP_LOAD_TRANSPOSE,
//! warp_threads>;
//!
//! constexpr int warps_in_block = threads_per_block / warp_threads;
//! constexpr int tile_size = items_per_thread * warp_threads;
//! const int warp_id = static_cast<int>(threadIdx.x) / warp_threads;
//!
//! // Allocate shared memory for WarpLoad
//! __shared__ typename WarpLoadT::TempStorage temp_storage[warps_in_block];
//!
//! // Load a segment of consecutive items that are blocked across threads
//! int thread_data[items_per_thread];
//! WarpLoadT(temp_storage[warp_id]).Load(d_data + warp_id * tile_size,
//! thread_data,
//! valid_items,
//! -1);
//!
//! Suppose the input ``d_data`` is ``0, 1, 2, 3, 4, 5, ...``, ``valid_items`` is ``5``, and the
//! out-of-bounds default is ``-1``. The set of ``thread_data`` across the first logical warp of
//! threads in those threads will be: ``{ [0,1,2,3], [4,-1,-1,-1], ..., [-1,-1,-1,-1] }`` with
//! only the first two threads being unmasked to load portions of valid data (and other items
//! are assigned ``-1``).
//! @endrst
//!
//! @param[in] block_itr The thread block's base input iterator for loading from
//! @param[out] items Data to load
//! @param[in] valid_items Number of valid items to load
//! @param[in] oob_default Default value to assign out-of-bound items
template <typename InputIteratorT, typename DefaultT>
_CCCL_DEVICE _CCCL_FORCEINLINE void
Load(InputIteratorT block_itr, InputT (&items)[ITEMS_PER_THREAD], int valid_items, DefaultT oob_default)
{
InternalLoad(temp_storage, linear_tid).Load(block_itr, items, valid_items, oob_default);
}
//! @}
};
CUB_NAMESPACE_END