CUTLASS 2.4 (Implicit GEMM convolution) (#147)
CUTLASS 2.4 (Implicit GEMM Convolution) Co-authored-by: Manish Gupta <manigupta@nvidia.com>, Haicheng Wu <haichengw@nvidia.com>, Dustyn Blasig <dblasig@nvidia.com>, Andrew Kerr <akerr@nvidia.com>
This commit is contained in:
co-authored by
Manish Gupta <manigupta@nvidia.com>, Haicheng Wu <haichengw@nvidia.com>, Dustyn Blasig <dblasig@nvidia.com>, Andrew Kerr <akerr@nvidia.com>
parent
c2b80ad4e4
commit
6615010cd0
@@ -340,6 +340,134 @@ struct PitchLinearWarpRakedThreadMap {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Policy defining a warp-raked arrangement in which a shape is partitioned into contiguous
|
||||
/// elements. Warps are arranged based on a stride.
|
||||
///
|
||||
/// This ThreadMap is used by tensor core kernels for NCxHWx layout.
|
||||
template <
|
||||
typename Shape_,
|
||||
int Threads,
|
||||
typename WarpThreadArrangement_,
|
||||
int ElementsPerAccess = 1
|
||||
>
|
||||
struct PitchLinearStridedWarpRakedThreadMap {
|
||||
|
||||
/// Tensor coordinate
|
||||
using TensorCoord = layout::PitchLinearCoord;
|
||||
|
||||
/// Tile shape
|
||||
using Shape = Shape_;
|
||||
|
||||
/// Number of threads total
|
||||
static int const kThreads = Threads;
|
||||
|
||||
using WarpThreadArrangement = WarpThreadArrangement_;
|
||||
|
||||
/// Extract vector length from Layout
|
||||
static int const kElementsPerAccess = ElementsPerAccess;
|
||||
|
||||
/// Base ThreadMap
|
||||
using BaseThreadMap = PitchLinearWarpRakedThreadMap<
|
||||
Shape,
|
||||
kThreads,
|
||||
WarpThreadArrangement,
|
||||
kElementsPerAccess
|
||||
>;
|
||||
|
||||
/// Shape of access by each thread
|
||||
using ThreadAccessShape = typename BaseThreadMap::ThreadAccessShape;
|
||||
|
||||
|
||||
struct Detail {
|
||||
|
||||
using WarpThreadArrangement = WarpThreadArrangement_;
|
||||
|
||||
using WarpAccessIterations = typename BaseThreadMap::Detail::WarpAccessIterations;
|
||||
|
||||
static int const kWarpSize = BaseThreadMap::Detail::kWarpSize;
|
||||
|
||||
static int const kWarpCount = BaseThreadMap::Detail::kWarpCount;
|
||||
|
||||
using ShapeInAccesses = typename BaseThreadMap::Detail::ShapeInAccesses;
|
||||
|
||||
// Divide it into the number of warps, first partitioning the contiguous dimension then the
|
||||
// stride.
|
||||
static int const kWarpsContiguous =
|
||||
(WarpAccessIterations::kContiguous >= kWarpCount
|
||||
? kWarpCount
|
||||
: WarpAccessIterations::kContiguous);
|
||||
|
||||
static int const kWarpsStrided =
|
||||
(kWarpCount > WarpAccessIterations::kContiguous
|
||||
? kWarpCount / kWarpsContiguous
|
||||
: 1);
|
||||
|
||||
/// Arrangement of warps within a threadblock-scoped tile
|
||||
using WarpArrangement = layout::PitchLinearShape<
|
||||
kWarpsContiguous, kWarpsStrided
|
||||
>;
|
||||
|
||||
};
|
||||
|
||||
///< Iterations along each dimension (concept: PitchLinearShape)
|
||||
using Iterations = layout::PitchLinearShape<
|
||||
Detail::WarpAccessIterations::kContiguous / Detail::kWarpsContiguous,
|
||||
Detail::WarpAccessIterations::kStrided / Detail::kWarpsStrided
|
||||
>;
|
||||
|
||||
static_assert(Iterations::kCount,
|
||||
"Number of iterations must be non-zero");
|
||||
|
||||
///< Delta betweeen accesses (units of elements, concept: PitchLinearShape)
|
||||
using Delta = typename BaseThreadMap::Delta;
|
||||
|
||||
/// Maps thread ID to a coordinate offset within the tensor's logical coordinate space
|
||||
CUTLASS_HOST_DEVICE
|
||||
static TensorCoord initial_offset(int thread_id) {
|
||||
|
||||
int warp_id = (thread_id / Detail::kWarpSize);
|
||||
int lane_id = (thread_id % Detail::kWarpSize);
|
||||
|
||||
//
|
||||
// compute warp-level offset
|
||||
//
|
||||
|
||||
// This is the shape of the entire area covered by a warp's memory access (in units of vectors)
|
||||
layout::PitchLinearCoord warp_footprint{
|
||||
Detail::WarpThreadArrangement::kContiguous * Iterations::kContiguous,
|
||||
Detail::WarpThreadArrangement::kStrided * Iterations::kStrided
|
||||
};
|
||||
|
||||
// This is the offset of a specific warp (in units of vectors)
|
||||
layout::PitchLinearCoord warp_offset{
|
||||
(warp_id % Detail::kWarpsContiguous),
|
||||
(warp_id / Detail::kWarpsContiguous)
|
||||
};
|
||||
|
||||
// This is the offset of a specific thread within a warp (units of vectors)
|
||||
layout::PitchLinearCoord thread_offset_in_warp{
|
||||
lane_id % Detail::WarpThreadArrangement::kContiguous,
|
||||
lane_id / Detail::WarpThreadArrangement::kContiguous
|
||||
};
|
||||
|
||||
// This is the offset of a thread within a threadblock tile (units of vectors)
|
||||
layout::PitchLinearCoord thread_offset_in_threadblock_tile_vec =
|
||||
warp_footprint * warp_offset + thread_offset_in_warp;
|
||||
|
||||
// This is the offset of a thread within a threadblock tile (units of elements)
|
||||
layout::PitchLinearCoord thread_offset_in_threadblock_tile_base{
|
||||
thread_offset_in_threadblock_tile_vec.contiguous() * kElementsPerAccess,
|
||||
thread_offset_in_threadblock_tile_vec.strided()
|
||||
};
|
||||
|
||||
return thread_offset_in_threadblock_tile_base;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Transpose the existing ThreadMap. For example, interleaved layout is like
|
||||
/// congruous in the global memory and crosswise in the shared memory. We need
|
||||
/// to transpose the coordinates between two.
|
||||
|
||||
Reference in New Issue
Block a user