ZhengyangZhang commited on
Commit
37fb1c7
·
verified ·
1 Parent(s): a2585bd

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. lib/python3.12/site-packages/deep_gemm/__init__.py +13 -0
  2. lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/axpby.hpp +95 -0
  3. lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/clear.hpp +64 -0
  4. lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/cooperative_copy.hpp +339 -0
  5. lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/cooperative_gemm.hpp +553 -0
  6. lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/copy.hpp +527 -0
  7. lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/fill.hpp +87 -0
  8. lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/functional.hpp +290 -0
  9. lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/gemm.hpp +500 -0
  10. lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/prefer.hpp +46 -0
  11. lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/prefetch.hpp +145 -0
  12. lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/tensor_algorithms.hpp +166 -0
  13. lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/tuple_algorithms.hpp +1073 -0
  14. lib/python3.12/site-packages/deep_gemm/include/cute/arch/cluster_sm100.hpp +108 -0
  15. lib/python3.12/site-packages/deep_gemm/include/cute/arch/cluster_sm90.hpp +245 -0
  16. lib/python3.12/site-packages/deep_gemm/include/cute/arch/config.hpp +111 -0
  17. lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy.hpp +107 -0
  18. lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm100.hpp +0 -0
  19. lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm100_tma.hpp +664 -0
  20. lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm50.hpp +98 -0
  21. lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm75.hpp +236 -0
  22. lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm80.hpp +198 -0
  23. lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm90.hpp +219 -0
  24. lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm90_desc.hpp +475 -0
  25. lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm90_tma.hpp +1496 -0
  26. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma.hpp +64 -0
  27. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm100.hpp +42 -0
  28. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm100_desc.hpp +651 -0
  29. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm100_umma.hpp +1616 -0
  30. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm120.hpp +0 -0
  31. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm120_sparse.hpp +0 -0
  32. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm61.hpp +87 -0
  33. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm70.hpp +329 -0
  34. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm75.hpp +120 -0
  35. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm80.hpp +2241 -0
  36. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm89.hpp +180 -0
  37. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm90.hpp +0 -0
  38. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm90_desc.hpp +151 -0
  39. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm90_gmma.hpp +0 -0
  40. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm90_gmma_ext.hpp +0 -0
  41. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm90_gmma_sparse.hpp +0 -0
  42. lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm90_gmma_sparse_ext.hpp +0 -0
  43. lib/python3.12/site-packages/deep_gemm/include/cute/arch/simd_sm100.hpp +96 -0
  44. lib/python3.12/site-packages/deep_gemm/include/cute/arch/tmem_allocator_sm100.hpp +168 -0
  45. lib/python3.12/site-packages/deep_gemm/include/cute/arch/util.hpp +320 -0
  46. lib/python3.12/site-packages/deep_gemm/include/cute/atom/copy_atom.hpp +765 -0
  47. lib/python3.12/site-packages/deep_gemm/include/cute/atom/copy_traits.hpp +162 -0
  48. lib/python3.12/site-packages/deep_gemm/include/cute/atom/copy_traits_sm100.hpp +0 -0
  49. lib/python3.12/site-packages/deep_gemm/include/cute/atom/copy_traits_sm100_im2col.hpp +488 -0
  50. lib/python3.12/site-packages/deep_gemm/include/cute/atom/copy_traits_sm100_tma.hpp +487 -0
lib/python3.12/site-packages/deep_gemm/__init__.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+
3
+ from . import jit
4
+ from .jit_kernels import (
5
+ gemm_fp8_fp8_bf16_nt,
6
+ m_grouped_gemm_fp8_fp8_bf16_nt_contiguous,
7
+ m_grouped_gemm_fp8_fp8_bf16_nt_masked,
8
+ ceil_div,
9
+ set_num_sms, get_num_sms,
10
+ get_col_major_tma_aligned_tensor,
11
+ get_m_alignment_for_contiguous_layout
12
+ )
13
+ from .utils import bench, bench_kineto, calc_diff
lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/axpby.hpp ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp>
34
+
35
+ #include <cute/tensor_impl.hpp>
36
+ #include <cute/tensor_predicate.hpp>
37
+
38
+ namespace cute
39
+ {
40
+
41
+ //
42
+ // Accept mutable temporaries
43
+ //
44
+ template <class Alpha,
45
+ class XEngine, class XLayout,
46
+ class Beta,
47
+ class YEngine, class YLayout,
48
+ class PrdTensor = TrivialPredTensor>
49
+ CUTE_HOST_DEVICE
50
+ void
51
+ axpby(Alpha const& alpha,
52
+ Tensor<XEngine, XLayout> const& x,
53
+ Beta const& beta,
54
+ Tensor<YEngine, YLayout> && y,
55
+ PrdTensor const& p = {})
56
+ {
57
+ return axpby(alpha, x, beta, y, p);
58
+ }
59
+
60
+ //
61
+ // AXPBY
62
+ //
63
+ template <class Alpha,
64
+ class XEngine, class XLayout,
65
+ class Beta,
66
+ class YEngine, class YLayout,
67
+ class PrdTensor = TrivialPredTensor>
68
+ CUTE_HOST_DEVICE
69
+ void
70
+ axpby(Alpha const& alpha,
71
+ Tensor<XEngine, XLayout> const& x,
72
+ Beta const& beta,
73
+ Tensor<YEngine, YLayout> & y,
74
+ PrdTensor const& p = {})
75
+ {
76
+ auto isBetaZero = [&] () {
77
+ if constexpr (is_complex<Beta>::value) {
78
+ return beta.real() == Int<0>{} && beta.imag() == Int<0>{};
79
+ }
80
+ else {
81
+ return beta == Int<0>{};
82
+ }
83
+
84
+ CUTE_GCC_UNREACHABLE;
85
+ } ();
86
+
87
+ CUTE_UNROLL
88
+ for (int i = 0; i < size(x); ++i) {
89
+ if (p(i)) {
90
+ y(i) = (isBetaZero ? alpha * x(i) : alpha * x(i) + beta * y(i));
91
+ }
92
+ }
93
+ }
94
+
95
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/clear.hpp ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp> // CUTE_HOST_DEVICE
34
+ #include <cute/tensor_impl.hpp> // cute::Tensor
35
+ #include <cute/algorithm/fill.hpp> // cute::fill
36
+
37
+ namespace cute
38
+ {
39
+
40
+ //
41
+ // Accept mutable temporaries
42
+ //
43
+ template <class Engine, class Layout>
44
+ CUTE_HOST_DEVICE
45
+ void
46
+ clear(Tensor<Engine, Layout>&& tensor)
47
+ {
48
+ return clear(tensor);
49
+ }
50
+
51
+ //
52
+ // Set elements to zero
53
+ //
54
+ template <class Engine, class Layout>
55
+ CUTE_HOST_DEVICE
56
+ void
57
+ clear(Tensor<Engine, Layout>& tensor)
58
+ {
59
+ using T = typename Tensor<Engine,Layout>::value_type;
60
+
61
+ fill(tensor, T{});
62
+ }
63
+
64
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/cooperative_copy.hpp ADDED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2017 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp>
34
+ #include <cute/layout.hpp>
35
+ #include <cute/layout_composed.hpp> // cute::logical_divide
36
+ #include <cute/swizzle.hpp> // cute::Swizzle
37
+ #include <cute/swizzle_layout.hpp> // cute::get_nonswizzle_portion
38
+ #include <cute/tensor_impl.hpp> // cute::Tensor
39
+ #include <cute/tensor_predicate.hpp>
40
+ #include <cute/algorithm/copy.hpp>
41
+ #include <cute/atom/copy_atom.hpp>
42
+
43
+ namespace cute
44
+ {
45
+
46
+ template <uint32_t NumThreads,
47
+ class SrcEngine, class SrcLayout,
48
+ class DstEngine, class DstLayout>
49
+ CUTE_HOST_DEVICE void
50
+ naive_cooperative_copy(uint32_t const& tid,
51
+ Tensor<SrcEngine, SrcLayout> const& src,
52
+ Tensor<DstEngine, DstLayout> & dst)
53
+ {
54
+ auto N = size(dst);
55
+ auto R = N % Int<NumThreads>{};
56
+ if (R > 0 && tid < R) { // Likely static condition && Residue in-bounds
57
+ dst[tid] = src[tid];
58
+ }
59
+ CUTE_UNROLL
60
+ for (uint32_t i = uint32_t(R); i < uint32_t(N); i += NumThreads) { // All in-bounds
61
+ dst[tid + i] = src[tid + i];
62
+ }
63
+ }
64
+
65
+ // Accept mutable temporaries
66
+ template <uint32_t NumThreads,
67
+ class SrcEngine, class SrcLayout,
68
+ class DstEngine, class DstLayout>
69
+ CUTE_HOST_DEVICE void
70
+ naive_cooperative_copy(uint32_t const& tid,
71
+ Tensor<SrcEngine, SrcLayout> const& src,
72
+ Tensor<DstEngine, DstLayout> && dst)
73
+ {
74
+ return naive_cooperative_copy(tid, src, dst);
75
+ }
76
+
77
+ // A heuristic to determine a "good" permutation of two tensors for later vectorization and thr-assignment
78
+ template <class AEngine, class ALayout,
79
+ class BEngine, class BLayout>
80
+ CUTE_HOST_DEVICE constexpr
81
+ auto
82
+ heuristic_permutation(Tensor<AEngine, ALayout> const& a,
83
+ Tensor<BEngine, BLayout> const& b)
84
+ {
85
+ constexpr bool swizzleA = get_swizzle_t<AEngine>::num_bits != 0 or
86
+ get_swizzle_t<ALayout>::num_bits != 0;
87
+ constexpr bool swizzleB = get_swizzle_t<BEngine>::num_bits != 0 or
88
+ get_swizzle_t<BLayout>::num_bits != 0;
89
+ auto a_inv = right_inverse(get_nonswizzle_portion(a.layout()));
90
+ auto b_inv = right_inverse(get_nonswizzle_portion(b.layout()));
91
+
92
+ constexpr uint8_t scoreA = (uint8_t(swizzleA) << 2) |
93
+ (uint8_t(is_smem<AEngine>::value) << 1) |
94
+ (uint8_t(size(a_inv) > size(b_inv)) << 0);
95
+
96
+ constexpr uint8_t scoreB = (uint8_t(swizzleB) << 2) |
97
+ (uint8_t(is_smem<BEngine>::value) << 1) |
98
+ (uint8_t(size(b_inv) > size(a_inv)) << 0);
99
+
100
+ if constexpr (scoreA >= scoreB) {
101
+ return a_inv;
102
+ } else {
103
+ return b_inv;
104
+ }
105
+ }
106
+
107
+ // cooperative_copy<NumThreads, MaxVecBits>(thr_idx, src, dst)
108
+ // Use NumThreads to copy Tensor src to Tensor dst with element-wise vectorization up to MaxVecBits.
109
+ // @pre 0 <= @a tid < NumThreads
110
+ // @pre Tensors @a src and @a dst are aligned up to MaxVecBits.
111
+ // That is, pointers and dynamic strides are assumed to be aligned up to MaxVecBits.
112
+ //
113
+ template <uint32_t NumThreads, uint32_t MaxVecBits,
114
+ class SrcEngine, class SrcLayout,
115
+ class DstEngine, class DstLayout,
116
+ class CopyPolicy = DefaultCopy>
117
+ CUTE_HOST_DEVICE
118
+ void
119
+ cooperative_copy(uint32_t const& tid,
120
+ Tensor<SrcEngine, SrcLayout> const& src,
121
+ Tensor<DstEngine, DstLayout> & dst,
122
+ CopyPolicy const& cpy = {})
123
+ {
124
+ // Assumes the shapes are static, can generalize/fallback
125
+ CUTE_STATIC_ASSERT_V(is_static<decltype(shape(src))>{} && is_static<decltype(shape(dst))>{});
126
+ CUTE_STATIC_ASSERT_V(size(src) == size(dst));
127
+ // Assumes the types are the same, can generalize/fallback
128
+ static_assert(cute::is_same<typename SrcEngine::value_type, typename DstEngine::value_type>::value);
129
+ static_assert(MaxVecBits == sizeof_bits_v<typename SrcEngine::value_type> ||
130
+ MaxVecBits == 8 || MaxVecBits == 16 || MaxVecBits == 32 || MaxVecBits == 64 || MaxVecBits == 128,
131
+ "Expected MaxVecBits to be value size or 8 or 16 or 32 or 64 or 128 for alignment and performance.");
132
+ // Check that the tensors are likely shared across threads: either gmem or smem
133
+ static_assert((is_gmem<SrcEngine>::value || is_smem<SrcEngine>::value),
134
+ "cooperative_copy expects shared gmem or smem source tensor.");
135
+ static_assert((is_gmem<DstEngine>::value || is_smem<DstEngine>::value),
136
+ "cooperative_copy expects shared gmem or smem destination tensor.");
137
+ // Precondition on tid in DEBUG
138
+ assert(tid < NumThreads);
139
+ // Precondition on pointer alignment in DEBUG
140
+ assert(is_byte_aligned<ceil_div(MaxVecBits,8u)>(raw_pointer_cast(src.data())));
141
+ assert(is_byte_aligned<ceil_div(MaxVecBits,8u)>(raw_pointer_cast(dst.data())));
142
+
143
+ #if 0
144
+ if (thread0()) {
145
+ print(" "); print("cooperative_copy\n");
146
+ print(" "); print("NumThreads: "); print(NumThreads); print("\n");
147
+ print(" "); print("MaxVecBits: "); print(MaxVecBits); print("\n");
148
+ print(" "); print("src: "); print(src); print("\n");
149
+ print(" "); print("dst: "); print(dst); print("\n");
150
+ }
151
+ #ifdef __CUDA_ARCH__
152
+ __syncthreads();
153
+ #endif
154
+ #endif
155
+
156
+ // The common layout of the two tensors that can be vectorized over elements and threads
157
+ // vidx -> coord
158
+ auto common_layout = heuristic_permutation(src, dst);
159
+
160
+ // Apply
161
+ // (V, rest)
162
+ Tensor src_a = coalesce(logical_divide(src, common_layout), Shape<_1,_1>{});
163
+ Tensor dst_a = coalesce(logical_divide(dst, common_layout), Shape<_1,_1>{});
164
+
165
+ //
166
+ // Determine vectorization of elems and thrs based on src/dst size and number of threads
167
+ // NOTE: This heuristic promotes parallelization over vectorization
168
+ //
169
+
170
+ // The number of elements and number of bits
171
+ constexpr int elem_bits = sizeof_bits_v<typename SrcEngine::value_type>;
172
+ constexpr int total_elem = size(SrcLayout{});
173
+
174
+ // The number of elements that can be vectorized in values
175
+ constexpr int common_elem = decltype(max_common_vector(src_a, dst_a))::value;
176
+
177
+ #if 0
178
+ if (thread0()) {
179
+ print(" "); print("common_layout: "); print(common_layout); print("\n");
180
+ print(" "); print("src_a: "); print(src_a); print("\n");
181
+ print(" "); print("dst_a: "); print(dst_a); print("\n");
182
+ }
183
+ #ifdef __CUDA_ARCH__
184
+ __syncthreads();
185
+ #endif
186
+ #endif
187
+
188
+ //
189
+ if constexpr (total_elem % NumThreads != 0) {
190
+ // Not attempting to find a partitioning pattern, fallback to dynamically indexed slowpath
191
+
192
+ if constexpr (common_elem > 1 && MaxVecBits > elem_bits) {
193
+ // If the vectorization is non-trivial and divides the maximum vectorizations, then vectorize
194
+ constexpr auto max_align_src = elem_bits * decltype(max_alignment(src_a.layout()))::value;
195
+ constexpr auto max_align_dst = elem_bits * decltype(max_alignment(dst_a.layout()))::value;
196
+ constexpr auto vec_bits = gcd(max_align_src, max_align_dst, MaxVecBits);
197
+ using VecType = uint_bit_t<vec_bits>;
198
+
199
+ static_assert(vec_bits % elem_bits == 0, "Expected divisibility");
200
+ static_assert((vec_bits >= 8), "No support for subbyte copying");
201
+
202
+ Tensor src_v = recast<VecType const>(src_a);
203
+ Tensor dst_v = recast<VecType >(dst_a);
204
+
205
+ #if 0
206
+ if (thread0()) {
207
+ print(" "); print("cooperative_copy -- naive\n");
208
+ print(" "); print("src_v: "); print(src_v); print("\n");
209
+ print(" "); print("dst_v: "); print(dst_v); print("\n");
210
+ }
211
+ #ifdef __CUDA_ARCH__
212
+ __syncthreads();
213
+ #endif
214
+ #endif
215
+
216
+ naive_cooperative_copy<NumThreads>(tid, src_v, dst_v);
217
+ } else {
218
+ naive_cooperative_copy<NumThreads>(tid, src_a, dst_a);
219
+ }
220
+ } else {
221
+ // If the tensors can be equally partitioned by the threads,
222
+ // compute vectorization widths in elements and threads.
223
+
224
+ // If there are too many threads to allow a full vectorized copy, trunc the vectorization
225
+ constexpr int total_bits = total_elem * elem_bits;
226
+ constexpr int max_bits_per_thr = total_bits / NumThreads;
227
+ // At least elem_bits, at most common_bits
228
+ constexpr int common_bits = common_elem * elem_bits;
229
+ constexpr int vec_bits = cute::max(elem_bits, cute::gcd(common_bits, int(MaxVecBits), max_bits_per_thr));
230
+
231
+ // Should account for vec_bits < 8 and/or vec_elem <= 1
232
+ // And also account for subbyte types, which could cause race conditions
233
+ // Want to ENFORCE sufficient vectorization in those cases
234
+ static_assert(vec_bits % elem_bits == 0, "Expected divisibility");
235
+ static_assert(vec_bits >= 8, "No support for subbyte copying");
236
+
237
+ using VecType = uint_bit_t<vec_bits>;
238
+ constexpr int vec_elem = vec_bits / elem_bits;
239
+
240
+ constexpr int vec_thrs = cute::min(int(NumThreads), total_elem / vec_elem);
241
+
242
+ //
243
+ // Determine the partitioning patterns for the vec_elems and vec_thrs
244
+ //
245
+
246
+ // Distribute the rest of the V*T to some consistent portion outside of the common_layout, if needed
247
+ auto common_domain_src = domain_distribute(shape(src_a), Int<vec_elem*vec_thrs>{});
248
+ auto common_domain_dst = domain_distribute(shape(dst_a), Int<vec_elem*vec_thrs>{});
249
+
250
+ // Make sure for now, could fall back here instead
251
+ CUTE_STATIC_ASSERT_V(size(common_domain_src) == Int<vec_elem*vec_thrs>{});
252
+ CUTE_STATIC_ASSERT_V(compatible(common_domain_src, common_domain_dst) ||
253
+ compatible(common_domain_dst, common_domain_src));
254
+ // Use the "more specific" domain for the extra elements of V*T
255
+ auto common_domain = conditional_return(compatible(common_domain_src, common_domain_dst),
256
+ common_domain_dst, common_domain_src);
257
+
258
+ // Construct the tiler
259
+ auto tiler_vt = common_domain.with_shape(Int<vec_elem>{}, Int<vec_thrs>{});
260
+
261
+ // Apply and slice
262
+ Tensor src_v = logical_divide(src_a, tiler_vt)(make_coord(_,tid),_);
263
+ Tensor dst_v = logical_divide(dst_a, tiler_vt)(make_coord(_,tid),_);
264
+
265
+ #if 0
266
+ if (thread0()) {
267
+ print(" "); print("cooperative_copy -- vec\n");
268
+ print(" "); print("Used vector: "); print(vec_elem); print("\n");
269
+ print(" "); print("Used threads: "); print(vec_thrs); print("\n");
270
+ print(" "); print("tiler_vt: "); print(tiler_vt); print("\n");
271
+ print(" "); print("src_v: "); print(src_v); print("\n");
272
+ print(" "); print("dst_v: "); print(dst_v); print("\n");
273
+ print(" "); print("recast<VecType const>(src_v): "); print(recast<VecType const>(src_v)); print("\n");
274
+ print(" "); print("recast<VecType >(dst_v): "); print(recast<VecType >(dst_v)); print("\n");
275
+ }
276
+ #ifdef __CUDA_ARCH__
277
+ __syncthreads();
278
+ #endif
279
+ #endif
280
+
281
+ // If we're using all threads (static) or the tid is in-range (dynamic)
282
+ if (vec_thrs == NumThreads or tid < vec_thrs) {
283
+ auto src_c = recast<VecType const>(src_v);
284
+ auto dst_c = recast<VecType>(dst_v);
285
+ return copy(cpy, src_c, dst_c);
286
+ }
287
+ }
288
+ }
289
+
290
+
291
+ // Default max-vectorization size to value_type size
292
+ template <uint32_t NumThreads,
293
+ class SrcEngine, class SrcLayout,
294
+ class DstEngine, class DstLayout,
295
+ class CopyPolicy = DefaultCopy>
296
+ CUTE_HOST_DEVICE
297
+ void
298
+ cooperative_copy(uint32_t const& tid,
299
+ Tensor<SrcEngine, SrcLayout> const& src,
300
+ Tensor<DstEngine, DstLayout> & dst,
301
+ CopyPolicy const& cpy = {})
302
+ {
303
+ constexpr uint32_t MaxVecBits = sizeof_bits_v<typename SrcEngine::value_type>;
304
+ return cooperative_copy<NumThreads, MaxVecBits>(tid, src, dst, cpy);
305
+ }
306
+
307
+ //
308
+ // Accept mutable temporaries
309
+ //
310
+
311
+ template <uint32_t NumThreads,
312
+ class SrcEngine, class SrcLayout,
313
+ class DstEngine, class DstLayout,
314
+ class CopyPolicy = DefaultCopy>
315
+ CUTE_HOST_DEVICE
316
+ void
317
+ cooperative_copy(uint32_t const& tid,
318
+ Tensor<SrcEngine, SrcLayout> const& src,
319
+ Tensor<DstEngine, DstLayout> && dst,
320
+ CopyPolicy const& cpy = {})
321
+ {
322
+ return cooperative_copy<NumThreads>(tid, src, dst, cpy);
323
+ }
324
+
325
+ template <uint32_t NumThreads, uint32_t MaxVecBits,
326
+ class SrcEngine, class SrcLayout,
327
+ class DstEngine, class DstLayout,
328
+ class CopyPolicy = DefaultCopy>
329
+ CUTE_HOST_DEVICE
330
+ void
331
+ cooperative_copy(uint32_t const& tid,
332
+ Tensor<SrcEngine, SrcLayout> const& src,
333
+ Tensor<DstEngine, DstLayout> && dst,
334
+ CopyPolicy const& cpy = {})
335
+ {
336
+ return cooperative_copy<NumThreads, MaxVecBits>(tid, src, dst, cpy);
337
+ }
338
+
339
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/cooperative_gemm.hpp ADDED
@@ -0,0 +1,553 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2017 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp>
34
+ #include <cute/util/type_traits.hpp>
35
+
36
+ #include <cute/atom/mma_atom.hpp>
37
+
38
+ #include <cute/algorithm/axpby.hpp>
39
+ #include <cute/algorithm/functional.hpp>
40
+ #include <cute/algorithm/gemm.hpp>
41
+
42
+ #include <cute/tensor_impl.hpp>
43
+
44
+ namespace cute
45
+ {
46
+
47
+ //
48
+ // Cooperative Shared-Memory GEMMs
49
+ //
50
+
51
+ namespace detail {
52
+
53
+ // Slow fallback path:
54
+ template<typename ... Args,
55
+ typename Alpha, typename TRC, typename RCLayout,
56
+ typename Beta, class TSC, typename CLayout, typename SCLayout,
57
+ typename CLoadTransformOp, typename CStoreTransformOp>
58
+ CUTE_HOST_DEVICE
59
+ void
60
+ epilogue_predication(ThrMMA<Args...> const& thr_mma,
61
+ Alpha const& alpha,
62
+ Tensor<TRC, RCLayout> & tCrC,
63
+ Beta const& beta,
64
+ Tensor<TSC, CLayout> & sC,
65
+ Tensor<TSC, SCLayout> & tCsC,
66
+ CLoadTransformOp const& sC_load_op, // transforms C values before use in GEMM
67
+ CStoreTransformOp const& sC_store_op) // transforms results before they are stored to C
68
+ {
69
+ using InputTypeC = typename TSC::value_type;
70
+ using ComputeTypeC = typename ThrMMA<Args...>::ValTypeC;
71
+ CUTE_STATIC_ASSERT(CUTE_STL_NAMESPACE::is_same_v<ComputeTypeC, typename TRC::value_type>);
72
+
73
+ // Create coordinate tensors for the problem
74
+ Tensor cC = make_identity_tensor(shape(sC)); // (M,N) -> (m,n)
75
+ // Repeat partitioning with thr_mma
76
+ Tensor tCcC = thr_mma.partition_C(cC); // (MMA,MMA_M,MMA_N) -> (m,n)
77
+
78
+ const bool isBetaZero = [&] () {
79
+ if constexpr (is_complex<Beta>::value) {
80
+ return beta.real() == Int<0>{} && beta.imag() == Int<0>{};
81
+ }
82
+ else {
83
+ return beta == Int<0>{};
84
+ }
85
+ CUTE_GCC_UNREACHABLE;
86
+ } ();
87
+
88
+ // Custom axpby_if for now
89
+ CUTE_UNROLL
90
+ for (int i = 0; i < size(tCrC); ++i)
91
+ {
92
+ if (elem_less(tCcC(i), shape(sC)))
93
+ {
94
+ tCsC(i) = sC_store_op(isBetaZero ? alpha * tCrC(i)
95
+ : alpha * tCrC(i) +
96
+ beta * static_cast<ComputeTypeC>(sC_load_op(tCsC(i))));
97
+ }
98
+ }
99
+ }
100
+
101
+ template<class ... Args,
102
+ class Alpha, class TRC, class RCLayout,
103
+ class Beta, class TSC, class SCLayout,
104
+ class CLoadTransformOp, class CStoreTransformOp,
105
+ class SmemCopyLdOpC, class SmemCopyStOpC>
106
+ CUTE_HOST_DEVICE
107
+ void
108
+ epilogue_no_predication(uint32_t thread_idx,
109
+ ThrMMA<Args...> const& thr_mma,
110
+ Alpha const& alpha,
111
+ Tensor<TRC, RCLayout> & tCrC,
112
+ Beta const& beta,
113
+ Tensor<TSC, SCLayout> & sC,
114
+ CLoadTransformOp const& sC_load_op, // transforms C values before use in GEMM
115
+ CStoreTransformOp const& sC_store_op, // transforms results before they are stored to C
116
+ SmemCopyLdOpC const& sC_copy_ld_op,
117
+ SmemCopyStOpC const& sC_copy_st_op)
118
+ {
119
+ using InputTypeC = typename TSC::value_type;
120
+ using ComputeTypeC = typename TRC::value_type;
121
+
122
+ const bool isBetaZero = [&] () {
123
+ if constexpr (is_complex<Beta>::value) {
124
+ return beta.real() == Int<0>{} && beta.imag() == Int<0>{};
125
+ }
126
+ else {
127
+ return beta == Int<0>{};
128
+ }
129
+ CUTE_GCC_UNREACHABLE;
130
+ } ();
131
+
132
+ Tensor tCrD = make_fragment_like(tCrC);
133
+ Tensor tCrDi = make_fragment_like<InputTypeC>(tCrD);
134
+
135
+ if(!isBetaZero) {
136
+ auto smem_tiled_copy_C = make_tiled_copy_C(Copy_Atom<SmemCopyLdOpC, InputTypeC>{}, thr_mma);
137
+ auto smem_thr_copy_C = smem_tiled_copy_C.get_thread_slice(thread_idx);
138
+ Tensor tCsC = smem_thr_copy_C.partition_S(sC);
139
+ Tensor tCrDi_copy_view = smem_thr_copy_C.retile_D(tCrDi);
140
+ CUTE_STATIC_ASSERT_V(size<1>(tCsC) == size<1>(tCrDi_copy_view)); // CPY_M
141
+ CUTE_STATIC_ASSERT_V(size<2>(tCsC) == size<2>(tCrDi_copy_view)); // CPY_N
142
+ copy(smem_tiled_copy_C, tCsC, tCrDi_copy_view);
143
+
144
+ // Transform C on/after load
145
+ cute::transform(tCrDi, tCrD, sC_load_op);
146
+ }
147
+ // C = alpha * (A * B) + beta * C
148
+ axpby(alpha, tCrC, beta, tCrD);
149
+ // Transform C before/on store
150
+ cute::transform(tCrD, tCrDi, sC_store_op);
151
+
152
+ auto smem_tiled_copy_C = make_tiled_copy_C(Copy_Atom<SmemCopyStOpC, InputTypeC>{}, thr_mma);
153
+ auto smem_thr_copy_C = smem_tiled_copy_C.get_thread_slice(thread_idx);
154
+ Tensor tCsC = smem_thr_copy_C.partition_D(sC);
155
+ Tensor tCrDi_copy_view = smem_thr_copy_C.retile_S(tCrDi);
156
+ CUTE_STATIC_ASSERT_V(size<1>(tCsC) == size<1>(tCrDi_copy_view)); // CPY_M
157
+ CUTE_STATIC_ASSERT_V(size<2>(tCsC) == size<2>(tCrDi_copy_view)); // CPY_N
158
+ copy(smem_tiled_copy_C, tCrDi_copy_view, tCsC);
159
+ }
160
+
161
+ // Predicated Cooperative GEMM
162
+ template <class... Args,
163
+ class TA, class ALayout, class TB, class BLayout,
164
+ class TC, class RCLayout,
165
+ class ALoadTransformOp, class BLoadTransformOp>
166
+ CUTE_HOST_DEVICE
167
+ void
168
+ cooperative_gemm_predication(ThrMMA<Args...> const& thr_mma,
169
+ Tensor<TA, ALayout> const& sA,
170
+ Tensor<TB, BLayout> const& sB,
171
+ Tensor<TC, RCLayout> & tCrC,
172
+ ALoadTransformOp const& sA_load_op, // transforms A values before use in GEMM
173
+ BLoadTransformOp const& sB_load_op) // transforms B values before use in GEMM
174
+ {
175
+ using InputTypeA = typename TA::value_type;
176
+ using InputTypeB = typename TB::value_type;
177
+ using InputTypeC = typename TC::value_type;
178
+ using ComputeTypeA = typename ThrMMA<Args...>::ValTypeA;
179
+ using ComputeTypeB = typename ThrMMA<Args...>::ValTypeB;
180
+ using ComputeTypeC = typename ThrMMA<Args...>::ValTypeC;
181
+
182
+ //
183
+ // MMA Partitioning
184
+ //
185
+
186
+ // Partition the sA, sB, and sC tiles across the threads for the MMA
187
+ Tensor tCsA = thr_mma.partition_A(sA); // (MMA,MMA_M,MMA_K)
188
+ Tensor tCsB = thr_mma.partition_B(sB); // (MMA,MMA_N,MMA_K)
189
+
190
+ // Create register tensors for the MMA to operate on
191
+ Tensor tCrA = thr_mma.make_fragment_A(tCsA); // (MMA,MMA_M,MMA_K)
192
+ Tensor tCrB = thr_mma.make_fragment_B(tCsB); // (MMA,MMA_N,MMA_K)
193
+ //
194
+ // PREDICATION
195
+ //
196
+
197
+ // Create coordinate tensors for the problem
198
+ Tensor cA = make_identity_tensor(shape(sA)); // (M,K) -> (m,k)
199
+ Tensor cB = make_identity_tensor(shape(sB)); // (N,K) -> (n,k)
200
+
201
+ // Repeat partitioning with thr_mma
202
+ Tensor tCcA = thr_mma.partition_A(cA); // (MMA,MMA_M,MMA_K) -> (m,k)
203
+ Tensor tCcB = thr_mma.partition_B(cB); // (MMA,MMA_N,MMA_K) -> (n,k)
204
+
205
+ // Allocate the preds for MMA- and MMA_MN-modes
206
+ Tensor tCpA = make_tensor<bool>(make_shape(size<0>(tCsA), size<1>(tCsA)));
207
+ Tensor tCpB = make_tensor<bool>(make_shape(size<0>(tCsB), size<1>(tCsB)));
208
+ // Populate the predicates on M and N
209
+ CUTE_UNROLL
210
+ for (int i = 0; i < size(tCpA); ++i) {
211
+ tCpA(i) = elem_less(get<0>(tCcA(_,_,Int<0>{})(i)), shape<0>(sA));
212
+ }
213
+ CUTE_UNROLL
214
+ for (int i = 0; i < size(tCpB); ++i) {
215
+ tCpB(i) = elem_less(get<0>(tCcB(_,_,Int<0>{})(i)), shape<0>(sB));
216
+ }
217
+ //
218
+ // PREFETCH k_block = 0
219
+ // Condition the k-predication on (static) k_block == K_BLOCK_MAX-1, the last k_block
220
+ // Assumes the MMA-tiling in K is trivial
221
+ //
222
+
223
+ constexpr int K_BLOCK_MAX = size<2>(tCrA);
224
+
225
+ CUTE_UNROLL
226
+ for (int m = 0; m < size<1>(tCrA); ++m) { // Copy MMA_M
227
+ CUTE_UNROLL
228
+ for (int i = 0; i < size<0>(tCrA); ++i) { // Copy MMA_I
229
+ tCrA(i,m,0) = (tCpA(i,m) && (0 < K_BLOCK_MAX-1 || elem_less(get<1>(tCcA(i,m,0)), shape<1>(sA)))) ? static_cast<ComputeTypeA>(sA_load_op(tCsA(i,m,0))) : ComputeTypeA{};
230
+ }
231
+ }
232
+ CUTE_UNROLL
233
+ for (int n = 0; n < size<1>(tCrB); ++n) { // Copy MMA_N
234
+ CUTE_UNROLL
235
+ for (int i = 0; i < size<0>(tCrB); ++i) { // Copy MMA_I
236
+ tCrB(i,n,0) = (tCpB(i,n) && (0 < K_BLOCK_MAX-1 || elem_less(get<1>(tCcB(i,n,0)), shape<1>(sB)))) ? static_cast<ComputeTypeB>(sB_load_op(tCsB(i,n,0))) : ComputeTypeB{};
237
+ }
238
+ }
239
+ //
240
+ // MAINLOOP
241
+ //
242
+
243
+ CUTE_UNROLL
244
+ for (int k_block = 0; k_block < K_BLOCK_MAX; ++k_block)
245
+ {
246
+ if (k_block < K_BLOCK_MAX-1) // static-if not the last k_block
247
+ {
248
+ int k_next = k_block + 1; // Load k_next block
249
+
250
+ // Condition the k-predication on (static) k_block == K_BLOCK_MAX-1, the last k_block
251
+ // Assumes the MMA-tiling in K is trivial
252
+
253
+ CUTE_UNROLL
254
+ for (int m = 0; m < size<1>(tCrA); ++m) { // Copy MMA_M
255
+ CUTE_UNROLL
256
+ for (int i = 0; i < size<0>(tCrA); ++i) { // Copy MMA_I
257
+ tCrA(i,m,k_next) = (tCpA(i,m) && (k_next < K_BLOCK_MAX-1 || elem_less(get<1>(tCcA(i,m,k_next)), shape<1>(sA)))) ? static_cast<ComputeTypeA>(sA_load_op(tCsA(i,m,k_next))) : ComputeTypeA{};
258
+ }
259
+ }
260
+ CUTE_UNROLL
261
+ for (int n = 0; n < size<1>(tCrB); ++n) { // Copy MMA_N
262
+ CUTE_UNROLL
263
+ for (int i = 0; i < size<0>(tCrB); ++i) { // Copy MMA_I
264
+ tCrB(i,n,k_next) = (tCpB(i,n) && (k_next < K_BLOCK_MAX-1 || elem_less(get<1>(tCcB(i,n,k_next)), shape<1>(sB)))) ? static_cast<ComputeTypeB>(sB_load_op(tCsB(i,n,k_next))) : ComputeTypeB{};
265
+ }
266
+ }
267
+ }
268
+ // GEMM on k_block in registers
269
+ gemm(thr_mma, tCrA(_,_,k_block), tCrB(_,_,k_block), tCrC);
270
+ }
271
+ }
272
+
273
+ // Unpredicated Cooperative GEMM
274
+ template <class... Args,
275
+ class TA, class ALayout, class TB, class BLayout,
276
+ class TC, class CLayout,
277
+ class ALoadTransformOp, class BLoadTransformOp,
278
+ class SmemCopyOpA, class SmemCopyOpB>
279
+ CUTE_HOST_DEVICE
280
+ void
281
+ cooperative_gemm_no_predication(uint32_t thread_idx,
282
+ ThrMMA<Args...> const& thr_mma,
283
+ Tensor<TA, ALayout> const& sA,
284
+ Tensor<TB, BLayout> const& sB,
285
+ Tensor<TC, CLayout> & tCrC,
286
+ ALoadTransformOp const& sA_load_op, // transforms A values before use in GEMM
287
+ BLoadTransformOp const& sB_load_op, // transforms B values before use in GEMM
288
+ SmemCopyOpA const& sA_copy_op,
289
+ SmemCopyOpB const& sB_copy_op)
290
+ {
291
+ using InputTypeA = typename TA::value_type;
292
+ using InputTypeB = typename TB::value_type;
293
+ using InputTypeC = typename TC::value_type;
294
+ using ComputeTypeA = typename ThrMMA<Args...>::ValTypeA;
295
+ using ComputeTypeB = typename ThrMMA<Args...>::ValTypeB;
296
+ using ComputeTypeC = typename ThrMMA<Args...>::ValTypeC;
297
+
298
+
299
+ //
300
+ // MMA Partitioning
301
+ //
302
+
303
+ // Create register tensors for the MMA to operate on
304
+ Tensor tCrA = thr_mma.partition_fragment_A(sA); // (MMA,MMA_M,MMA_K)
305
+ Tensor tCrAi = make_fragment_like<InputTypeA>(tCrA);
306
+ Tensor tCrB = thr_mma.partition_fragment_B(sB); // (MMA,MMA_N,MMA_K)
307
+ Tensor tCrBi = make_fragment_like<InputTypeB>(tCrB);
308
+
309
+ using CopyOpAType = SmemCopyOpA;
310
+ using CopyOpBType = SmemCopyOpB;
311
+
312
+ auto smem_tiled_copy_A = make_tiled_copy_A(Copy_Atom<CopyOpAType, InputTypeA>{}, thr_mma);
313
+ auto smem_thr_copy_A = smem_tiled_copy_A.get_thread_slice(thread_idx);
314
+ Tensor tCsA = smem_thr_copy_A.partition_S(sA);
315
+ Tensor tCrAi_copy_view = smem_thr_copy_A.retile_D(tCrAi);
316
+ CUTE_STATIC_ASSERT_V(size<1>(tCsA) == size<1>(tCrAi_copy_view)); // CPY_M
317
+ CUTE_STATIC_ASSERT_V(size<2>(tCsA) == size<2>(tCrAi_copy_view)); // CPY_K
318
+
319
+ auto smem_tiled_copy_B = make_tiled_copy_B(Copy_Atom<CopyOpBType, InputTypeB>{}, thr_mma);
320
+ auto smem_thr_copy_B = smem_tiled_copy_B.get_thread_slice(thread_idx);
321
+ Tensor tCsB = smem_thr_copy_B.partition_S(sB);
322
+ Tensor tCrBi_copy_view = smem_thr_copy_B.retile_D(tCrBi);
323
+ CUTE_STATIC_ASSERT_V(size<1>(tCsB) == size<1>(tCrBi_copy_view)); // CPY_N
324
+ CUTE_STATIC_ASSERT_V(size<2>(tCsB) == size<2>(tCrBi_copy_view)); // CPY_K
325
+ //
326
+ // PREFETCH
327
+ //
328
+
329
+ copy(smem_tiled_copy_A, tCsA(_,_,Int<0>{}), tCrAi_copy_view(_,_,Int<0>{}));
330
+ copy(smem_tiled_copy_B, tCsB(_,_,Int<0>{}), tCrBi_copy_view(_,_,Int<0>{}));
331
+ //
332
+ // MAINLOOP
333
+ //
334
+
335
+ constexpr int K_BLOCK_MAX = size<2>(tCrA);
336
+
337
+ CUTE_UNROLL
338
+ for (int k_block = 0; k_block < K_BLOCK_MAX; ++k_block)
339
+ {
340
+ // static-if load the next k_block. No k-predication required on these loads.
341
+ if (k_block < K_BLOCK_MAX-1)
342
+ {
343
+ // Load the next k_block
344
+ int k_next = k_block + 1; // statically unrolled
345
+ copy(smem_tiled_copy_A, tCsA(_,_,k_next), tCrAi_copy_view(_,_,k_next));
346
+ copy(smem_tiled_copy_B, tCsB(_,_,k_next), tCrBi_copy_view(_,_,k_next));
347
+ }
348
+
349
+ // Transform A and B, relying on the compiler to remove in case of identity ops
350
+ cute::transform(tCrAi(_,_,k_block), tCrA(_,_,k_block), sA_load_op);
351
+ cute::transform(tCrBi(_,_,k_block), tCrB(_,_,k_block), sB_load_op);
352
+
353
+ // GEMM on k_block in registers
354
+ gemm(thr_mma, tCrA(_,_,k_block), tCrB(_,_,k_block), tCrC);
355
+ }
356
+ }
357
+
358
+ } // end namespace detail
359
+
360
+ // C passed as a shared memory tensor
361
+ // Epilogue included
362
+ template <class... Args,
363
+ class Alpha, class TA, class ALayout, class TB, class BLayout,
364
+ class Beta, class TC, class CLayout,
365
+ class ALoadTransformOp = cute::identity, class BLoadTransformOp = cute::identity,
366
+ class CLoadTransformOp = cute::identity, class CStoreTransformOp = cute::identity,
367
+ class SmemCopyOpA = DefaultCopy, class SmemCopyOpB = DefaultCopy,
368
+ class SmemCopyLdOpC = DefaultCopy, class SmemCopyStOpC = DefaultCopy>
369
+ CUTE_HOST_DEVICE
370
+ void
371
+ cooperative_gemm(uint32_t thread_idx,
372
+ TiledMMA<Args...> const& tiled_mma,
373
+ Alpha const& alpha,
374
+ Tensor<TA, ALayout> const& sA,
375
+ Tensor<TB, BLayout> const& sB,
376
+ Beta const& beta,
377
+ Tensor<TC, CLayout> & sC,
378
+ ALoadTransformOp const& sA_load_op = {}, // transforms A values before use in GEMM
379
+ BLoadTransformOp const& sB_load_op = {}, // transforms B values before use in GEMM
380
+ CLoadTransformOp const& sC_load_op = {}, // transforms C values before use in GEMM
381
+ CStoreTransformOp const& sC_store_op = {}, // transforms results before they are stored to C
382
+ SmemCopyOpA const& sA_copy_op = {},
383
+ SmemCopyOpB const& sB_copy_op = {},
384
+ SmemCopyLdOpC const& sC_copy_ld_op = {},
385
+ SmemCopyStOpC const& sC_copy_st_op = {})
386
+ {
387
+ CUTE_STATIC_ASSERT_V(rank(sA) == Int<2>{});
388
+ CUTE_STATIC_ASSERT_V(rank(sB) == Int<2>{});
389
+ CUTE_STATIC_ASSERT_V(rank(sC) == Int<2>{});
390
+
391
+ CUTE_STATIC_ASSERT_V(size<0>(sA) == size<0>(sC)); // AM == CM
392
+ CUTE_STATIC_ASSERT_V(size<0>(sB) == size<1>(sC)); // BN == CN
393
+ CUTE_STATIC_ASSERT_V(size<1>(sA) == size<1>(sB)); // AK == BK
394
+
395
+ using InputTypeA = typename TA::value_type;
396
+ using InputTypeB = typename TB::value_type;
397
+ using InputTypeC = typename TC::value_type;
398
+ using ComputeTypeA = typename TiledMMA<Args...>::ValTypeA;
399
+ using ComputeTypeB = typename TiledMMA<Args...>::ValTypeB;
400
+ using ComputeTypeC = typename TiledMMA<Args...>::ValTypeC;
401
+
402
+ auto compat = evenly_divides(make_shape(size<0>(sA), size<0>(sB), size<1>(sA)),
403
+ tile_shape(TiledMMA<Args...>{}));
404
+
405
+ // ThrMMA
406
+ auto thr_mma = tiled_mma.get_thread_slice(thread_idx);
407
+ Tensor tCsC = thr_mma.partition_C(sC); // (MMA,MMA_M,MMA_N) :: InputTypeC
408
+ Tensor tCrC = thr_mma.make_fragment_C(tCsC); // (MMA,MMA_M,MMA_N) :: ComputeTypeC
409
+
410
+ // Clear accumulators
411
+ clear(tCrC);
412
+ if constexpr (is_constant<true, decltype(compat)>::value) {
413
+ detail::cooperative_gemm_no_predication(
414
+ thread_idx, thr_mma, sA, sB, tCrC, sA_load_op, sB_load_op, sA_copy_op, sB_copy_op
415
+ );
416
+ detail::epilogue_no_predication(
417
+ thread_idx, thr_mma,alpha, tCrC, beta, sC, sC_load_op, sC_store_op, sC_copy_ld_op, sC_copy_st_op
418
+ );
419
+ } else {
420
+ detail::cooperative_gemm_predication(
421
+ thr_mma, sA, sB, tCrC, sA_load_op, sB_load_op
422
+ );
423
+ detail::epilogue_predication(
424
+ thr_mma, alpha, tCrC, beta, sC, tCsC, sC_load_op, sC_store_op
425
+ );
426
+ }
427
+ }
428
+
429
+ // C already partitioned into registers on input
430
+ // It can be passed non-empty
431
+ // Epilogue not included
432
+ template <class... Args,
433
+ class TA, class ALayout, class TB, class BLayout,
434
+ class TC, class CLayout,
435
+ class ALoadTransformOp = cute::identity, class BLoadTransformOp = cute::identity,
436
+ class SmemCopyOpA = DefaultCopy, class SmemCopyOpB = DefaultCopy>
437
+ CUTE_HOST_DEVICE
438
+ void
439
+ cooperative_gemm(uint32_t thread_idx,
440
+ TiledMMA<Args...> const& tiled_mma,
441
+ Tensor<TA, ALayout> const& sA,
442
+ Tensor<TB, BLayout> const& sB,
443
+ Tensor<TC, CLayout> & tCrC,
444
+ ALoadTransformOp const& sA_load_op = {}, // transforms A values before use in GEMM
445
+ BLoadTransformOp const& sB_load_op = {}, // transforms B values before use in GEMM
446
+ SmemCopyOpA const& sA_copy_op = {},
447
+ SmemCopyOpB const& sB_copy_op = {})
448
+ {
449
+ CUTE_STATIC_ASSERT_V(rank(sA) == Int<2>{});
450
+ CUTE_STATIC_ASSERT_V(rank(sB) == Int<2>{});
451
+
452
+ CUTE_STATIC_ASSERT_V(size<1>(sA) == size<1>(sB)); // AK == BK
453
+
454
+ using InputTypeA = typename TA::value_type;
455
+ using InputTypeB = typename TB::value_type;
456
+ using InputTypeC = typename TC::value_type;
457
+ using ComputeTypeA = typename TiledMMA<Args...>::ValTypeA;
458
+ using ComputeTypeB = typename TiledMMA<Args...>::ValTypeB;
459
+ using ComputeTypeC = typename TiledMMA<Args...>::ValTypeC;
460
+
461
+ // Check if input C fragment is compatible with thr_mma and problem size
462
+ using ref_c_frag = decltype(partition_shape_C(tiled_mma, make_shape(size<0>(sA), size<0>(sB))));
463
+ CUTE_STATIC_ASSERT_V(compatible(shape(ref_c_frag{}), shape(tCrC)));
464
+
465
+ auto compat = evenly_divides(make_shape(size<0>(sA), size<0>(sB), size<1>(sA)),
466
+ tile_shape(TiledMMA<Args...>{}));
467
+
468
+ // ThrMMA
469
+ auto thr_mma = tiled_mma.get_thread_slice(thread_idx);
470
+
471
+ if constexpr (is_constant<true, decltype(compat)>::value) {
472
+ detail::cooperative_gemm_no_predication(
473
+ thread_idx, thr_mma, sA, sB, tCrC, sA_load_op, sB_load_op, sA_copy_op, sB_copy_op
474
+ );
475
+ } else {
476
+ detail::cooperative_gemm_predication(
477
+ thr_mma, sA, sB, tCrC, sA_load_op, sB_load_op
478
+ );
479
+ }
480
+ }
481
+
482
+ // Accept mutable temporaries
483
+ template <class... Args,
484
+ class Alpha, class TA, class ALayout, class TB, class BLayout,
485
+ class Beta, class TC, class CLayout,
486
+ class ALoadTransformOp = cute::identity, class BLoadTransformOp = cute::identity,
487
+ class CLoadTransformOp = cute::identity, class CStoreTransformOp = cute::identity,
488
+ class SmemCopyOpA = DefaultCopy, class SmemCopyOpB = DefaultCopy,
489
+ class SmemCopyLdOpC = DefaultCopy, class SmemCopyStOpC = DefaultCopy>
490
+ CUTE_HOST_DEVICE
491
+ void
492
+ cooperative_gemm(uint32_t thread_idx,
493
+ TiledMMA<Args...> const& tiled_mma,
494
+ Alpha const& alpha,
495
+ Tensor<TA, ALayout> const& sA,
496
+ Tensor<TB, BLayout> const& sB,
497
+ Beta const& beta,
498
+ Tensor<TC, CLayout> && sC,
499
+ ALoadTransformOp const& sA_load_op = {}, // transforms A values before use in GEMM
500
+ BLoadTransformOp const& sB_load_op = {}, // transforms B values before use in GEMM
501
+ CLoadTransformOp const& sC_load_op = {}, // transforms C values before use in GEMM
502
+ CStoreTransformOp const& sC_store_op = {}, // transforms results before they are stored to C
503
+ SmemCopyOpA const& sA_copy_op = {},
504
+ SmemCopyOpB const& sB_copy_op = {},
505
+ SmemCopyLdOpC const& sC_copy_ld_op = {},
506
+ SmemCopyStOpC const& sC_copy_st_op = {})
507
+ {
508
+ cooperative_gemm(thread_idx, tiled_mma, alpha, sA, sB, beta, sC,
509
+ sA_load_op, sB_load_op, sC_load_op, sC_store_op,
510
+ sA_copy_op, sB_copy_op, sC_copy_ld_op, sC_copy_st_op);
511
+ }
512
+
513
+ // Legacy overload of cute::gemm for backwards-compatibility
514
+ template <class... Args,
515
+ class Alpha, class TA, class ALayout, class TB, class BLayout,
516
+ class Beta, class TC, class CLayout,
517
+ class ALoadTransformOp = cute::identity, class BLoadTransformOp = cute::identity,
518
+ class CLoadTransformOp = cute::identity, class CStoreTransformOp = cute::identity>
519
+ CUTE_HOST_DEVICE
520
+ void
521
+ gemm(ThrMMA<Args...> const& thr_mma,
522
+ Alpha const& alpha,
523
+ Tensor<TA, ALayout> const& sA,
524
+ Tensor<TB, BLayout> const& sB,
525
+ Beta const& beta,
526
+ Tensor<TC, CLayout> & sC,
527
+ ALoadTransformOp const& sA_load_op = {}, // transforms A values before use in GEMM
528
+ BLoadTransformOp const& sB_load_op = {}, // transforms B values before use in GEMM
529
+ CLoadTransformOp const& sC_load_op = {}, // transforms C values before use in GEMM
530
+ CStoreTransformOp const& sC_store_op = {}) // transforms results before they are stored to C
531
+ {
532
+ CUTE_STATIC_ASSERT_V(rank(sA) == Int<2>{});
533
+ CUTE_STATIC_ASSERT_V(rank(sB) == Int<2>{});
534
+ CUTE_STATIC_ASSERT_V(rank(sC) == Int<2>{});
535
+
536
+ CUTE_STATIC_ASSERT_V(size<0>(sA) == size<0>(sC)); // AM == CM
537
+ CUTE_STATIC_ASSERT_V(size<0>(sB) == size<1>(sC)); // BN == CN
538
+ CUTE_STATIC_ASSERT_V(size<1>(sA) == size<1>(sB)); // AK == BK
539
+
540
+ Tensor tCsC = thr_mma.partition_C(sC); // (MMA,MMA_M,MMA_N)
541
+ Tensor tCrC = thr_mma.make_fragment_C(tCsC); // (MMA,MMA_M,MMA_N)
542
+
543
+ // Goes directly to the slow path to avoid getting thread_idx from thr_mma
544
+ detail::cooperative_gemm_predication(
545
+ thr_mma, sA, sB, sC, sA_load_op, sB_load_op
546
+ );
547
+
548
+ detail::epilogue_predication(
549
+ thr_mma, alpha, tCrC, beta, sC, tCsC, sC_load_op, sC_store_op
550
+ );
551
+ }
552
+
553
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/copy.hpp ADDED
@@ -0,0 +1,527 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp> // CUTE_HOST_DEVICE
34
+ #include <cute/tensor_impl.hpp> // cute::Tensor
35
+ #include <cute/tensor_predicate.hpp> // cute::TrivialPredTensor
36
+ #include <cute/atom/copy_atom.hpp> // cute::Copy_Atom
37
+
38
+ namespace cute
39
+ {
40
+
41
+ //
42
+ // copy_if -- Predicated Copy
43
+ //
44
+
45
+ template <class PrdTensor,
46
+ class SrcEngine, class SrcLayout,
47
+ class DstEngine, class DstLayout>
48
+ CUTE_HOST_DEVICE
49
+ void
50
+ copy_if(PrdTensor const& pred,
51
+ Tensor<SrcEngine, SrcLayout> const& src,
52
+ Tensor<DstEngine, DstLayout> & dst)
53
+ {
54
+ using SrcType = typename SrcEngine::value_type;
55
+ using DstType = typename DstEngine::value_type;
56
+
57
+ CUTE_UNROLL
58
+ for (int i = 0; i < size(dst); ++i) {
59
+ if (pred(i)) {
60
+ dst(i) = static_cast<DstType>(static_cast<SrcType>(src(i)));
61
+ }
62
+ }
63
+ }
64
+
65
+ //
66
+ // copy_if -- Predicated CopyAtom
67
+ //
68
+
69
+ template <class... CopyArgs,
70
+ class PredTensor,
71
+ class SrcEngine, class SrcLayout,
72
+ class DstEngine, class DstLayout>
73
+ CUTE_HOST_DEVICE
74
+ void
75
+ copy_if(Copy_Atom<CopyArgs...> const& copy_atom,
76
+ PredTensor const& pred, // (Rest...)
77
+ Tensor<SrcEngine, SrcLayout> const& src, // (V,Rest...)
78
+ Tensor<DstEngine, DstLayout> & dst) // (V,Rest...)
79
+ {
80
+ static_assert(SrcLayout::rank == DstLayout::rank, "CopyAtom rank-mismatch.");
81
+ auto has_with_bool = cute::is_valid([](auto t)->void_t<decltype(declval<typename decltype(t)::Traits>().with(true))>{}, copy_atom);
82
+
83
+ if constexpr (SrcLayout::rank == 1) { // Dispatch the copy
84
+ if constexpr (has_with_bool) {
85
+ copy_atom.with(pred()).call(src, dst);
86
+ } else {
87
+ if (pred()) { copy_atom.call(src, dst); }
88
+ }
89
+ } else { // Loop over all but the first mode
90
+ constexpr int R = SrcLayout::rank;
91
+ Tensor src_v = group_modes<1,R>(src);
92
+ Tensor dst_v = group_modes<1,R>(dst);
93
+ CUTE_UNROLL
94
+ for (int i = 0; i < size<1>(dst_v); ++i) {
95
+ if constexpr (has_with_bool) {
96
+ copy_atom.with(pred(i)).call(src_v(_,i), dst_v(_,i));
97
+ } else {
98
+ if (pred(i)) { copy_atom.call(src_v(_,i), dst_v(_,i)); }
99
+ }
100
+ }
101
+ }
102
+ }
103
+
104
+ //
105
+ // copy_if -- AutoCopyAsync
106
+ //
107
+ template <class PrdTensor,
108
+ class SrcEngine, class SrcLayout,
109
+ class DstEngine, class DstLayout>
110
+ CUTE_HOST_DEVICE
111
+ void
112
+ copy_if(AutoCopyAsync const& cpy,
113
+ PrdTensor const& pred,
114
+ Tensor<SrcEngine, SrcLayout> const& src,
115
+ Tensor<DstEngine, DstLayout> & dst)
116
+ {
117
+ using SrcElemWithConst = remove_reference_t<typename SrcEngine::reference>;
118
+ using SrcType = typename SrcEngine::value_type;
119
+ using DstType = typename DstEngine::value_type;
120
+
121
+ auto copy_op = []() {
122
+ #if defined(CUTE_ARCH_CP_ASYNC_SM80_ENABLED)
123
+ if constexpr (is_gmem<SrcEngine>::value && is_smem<DstEngine>::value &&
124
+ sizeof(SrcType) == sizeof(DstType)) {
125
+ if constexpr (is_const_v<SrcElemWithConst> && sizeof(SrcType) == 16) {
126
+ return SM80_CP_ASYNC_CACHEGLOBAL<SrcType,DstType>{};
127
+ } else if constexpr (sizeof(SrcType) == 4 || sizeof(SrcType) == 8 || sizeof(SrcType) == 16) {
128
+ return SM80_CP_ASYNC_CACHEALWAYS<SrcType,DstType>{};
129
+ } else {
130
+ return UniversalCopy<SrcType,DstType>{};
131
+ }
132
+ } else {
133
+ return UniversalCopy<SrcType,DstType>{};
134
+ }
135
+
136
+ CUTE_GCC_UNREACHABLE;
137
+ #else
138
+ return UniversalCopy<SrcType,DstType>{};
139
+ #endif
140
+ }();
141
+
142
+ CUTE_UNROLL
143
+ for (int i = 0; i < size(dst); ++i) {
144
+ if (pred(i)) {
145
+ copy_op.copy(src(i), dst(i));
146
+ }
147
+ }
148
+ }
149
+
150
+ //
151
+ // copy -- AutoCopyAsync
152
+ //
153
+
154
+ template <class SrcEngine, class SrcLayout,
155
+ class DstEngine, class DstLayout>
156
+ CUTE_HOST_DEVICE
157
+ void
158
+ copy(AutoCopyAsync const& cpy,
159
+ Tensor<SrcEngine, SrcLayout> const& src, // (V,Rest...)
160
+ Tensor<DstEngine, DstLayout> & dst) // (V,Rest...)
161
+ {
162
+ copy_if(cpy, TrivialPredTensor{}, src, dst);
163
+ }
164
+
165
+ //
166
+ // copy -- CopyAtom
167
+ //
168
+
169
+ template <class... CopyArgs,
170
+ class SrcEngine, class SrcLayout,
171
+ class DstEngine, class DstLayout>
172
+ CUTE_HOST_DEVICE
173
+ void
174
+ copy(Copy_Atom<CopyArgs...> const& copy_atom,
175
+ Tensor<SrcEngine, SrcLayout> const& src, // (V,Rest...)
176
+ Tensor<DstEngine, DstLayout> & dst) // (V,Rest...)
177
+ {
178
+ static_assert(SrcLayout::rank == DstLayout::rank, "CopyAtom rank-mismatch.");
179
+
180
+ if constexpr (SrcLayout::rank == 1) { // Dispatch the copy
181
+ copy_atom.call(src, dst);
182
+ } else { // Loop over all but the first mode
183
+ constexpr int R = SrcLayout::rank;
184
+ Tensor src_v = group_modes<1,R>(src);
185
+ Tensor dst_v = group_modes<1,R>(dst);
186
+
187
+ if constexpr (is_static<decltype(shape(src_v))>::value && is_static<decltype(shape(dst_v))>::value) {
188
+ CUTE_STATIC_ASSERT_V(size<1>(src_v) == size<1>(dst_v));
189
+
190
+ // AutoFilter on the Rest-mode
191
+ auto dst_null = nullspace(layout<1>(dst_v));
192
+
193
+ Tensor dst_n = zipped_divide(dst_v, make_tile(shape<0>(dst_v), dst_null)); // ((V, NLL), (_1, Rest))
194
+ Tensor src_n = zipped_divide(src_v, make_tile(shape<0>(src_v), dst_null)); // ((V, NLL), (_1, Rest))
195
+
196
+ CUTE_STATIC_ASSERT_V(size<1>(src_n) == size<1>(dst_n));
197
+ CUTE_STATIC_ASSERT_V((cosize<0,1>(dst_n.layout()) == Int<1>{}), "Nullspace definition error");
198
+ CUTE_STATIC_ASSERT_V((cosize<0,1>(src_n.layout()) == Int<1>{}), "Error: Ambiguous scatter detected in copy");
199
+ CUTE_STATIC_ASSERT_V((size<1,0>(dst_n) == Int<1>{}));
200
+ CUTE_STATIC_ASSERT_V((size<1,0>(src_n) == Int<1>{}));
201
+
202
+ Tensor dst_c = dst_n(make_coord(_,Int<0>{}),make_coord(Int<0>{},_)); // (V, Rest)
203
+ Tensor src_c = src_n(make_coord(_,Int<0>{}),make_coord(Int<0>{},_)); // (V, Rest)
204
+
205
+ CUTE_STATIC_ASSERT_V(size<1>(src_c) == size<1>(dst_c));
206
+ CUTE_STATIC_ASSERT_V(shape<0>(dst_c) == shape<0>(dst));
207
+ CUTE_STATIC_ASSERT_V(shape<0>(src_c) == shape<0>(src));
208
+
209
+ CUTE_UNROLL
210
+ for (int i = 0; i < size<1>(dst_c); ++i) {
211
+ copy_atom.call(src_c(_,i), dst_c(_,i));
212
+ }
213
+ } else {
214
+ CUTE_UNROLL
215
+ for (int i = 0; i < size<1>(dst_v); ++i) {
216
+ copy_atom.call(src_v(_,i), dst_v(_,i));
217
+ }
218
+ }
219
+ }
220
+ }
221
+
222
+ ////////////////////////////////////////////////////////
223
+ // Special Auto-Vectorizing, Auto-Filtering Overloads //
224
+ ////////////////////////////////////////////////////////
225
+
226
+ // Specialization for AutoVectorizingCopyAssumedAlignment<MaxVecBits>
227
+ template <int MaxVecBits, class... Args,
228
+ class SrcEngine, class SrcLayout,
229
+ class DstEngine, class DstLayout>
230
+ CUTE_HOST_DEVICE
231
+ void
232
+ copy(AutoVectorizingCopyWithAssumedAlignment<MaxVecBits> const&,
233
+ Tensor<SrcEngine, SrcLayout> const& src,
234
+ Tensor<DstEngine, DstLayout> & dst)
235
+ {
236
+ constexpr int common_elem = CUTE_STATIC_V(max_common_vector(src, dst));
237
+ constexpr int align_bits = CUTE_STATIC_V(gcd(max_alignment(src), max_alignment(dst), Int<MaxVecBits>{}));
238
+ static_assert(is_integral<decltype(Int<common_elem>{} * sizeof_bits_v<typename SrcEngine::value_type>)>::value, "Error: Attempting a subbit copy!");
239
+ constexpr int vec_bits = gcd(common_elem * sizeof_bits_v<typename SrcEngine::value_type>, align_bits);
240
+
241
+ if constexpr (common_elem > 1 && ((vec_bits % 8) == 0)) {
242
+ // If more than one element vectorizes to 8bits or more, then recast and copy
243
+ using VecType = uint_bit_t<vec_bits>;
244
+ // Preserve volatility
245
+ using SrcVecType = conditional_t<is_volatile_v<typename SrcEngine::element_type>, VecType const volatile, VecType const>;
246
+ using DstVecType = conditional_t<is_volatile_v<typename DstEngine::element_type>, VecType volatile, VecType >;
247
+
248
+ // Recast
249
+ Tensor src_v = recast<SrcVecType>(src);
250
+ Tensor dst_v = recast<DstVecType>(dst);
251
+ return copy_if(TrivialPredTensor{}, src_v, dst_v);
252
+ } else {
253
+ return copy_if(TrivialPredTensor{}, src, dst);
254
+ }
255
+ }
256
+
257
+ template <class Base>
258
+ struct AutoFilter {
259
+ Base const& base;
260
+ CUTE_HOST_DEVICE AutoFilter(Base const& b) : base(b) {}
261
+ };
262
+
263
+ // Specialization for AutoFilter
264
+ template <class CopyOp,
265
+ class SrcEngine, class SrcLayout,
266
+ class DstEngine, class DstLayout>
267
+ CUTE_HOST_DEVICE
268
+ void
269
+ copy(AutoFilter<CopyOp> const& copy_op,
270
+ Tensor<SrcEngine, SrcLayout> const& src,
271
+ Tensor<DstEngine, DstLayout> & dst)
272
+ {
273
+ if constexpr (is_constant<true, decltype(size(src) == size(dst))>::value) {
274
+ auto dst_null = nullspace(dst.layout());
275
+
276
+ Tensor dst_n = zipped_divide(dst, dst_null);
277
+ Tensor src_n = zipped_divide(src, dst_null);
278
+
279
+ CUTE_STATIC_ASSERT_V(cosize<0>(dst_n.layout()) == Int<1>{}, "Nullspace definition error");
280
+ CUTE_STATIC_ASSERT_V(cosize<0>(src_n.layout()) == Int<1>{}, "Error: Ambiguous scatter detected in copy");
281
+
282
+ copy(copy_op.base, src_n(Int<0>{},_), dst_n(Int<0>{},_));
283
+ } else {
284
+ copy(copy_op.base, src, dst);
285
+ }
286
+ }
287
+
288
+ // Auto-vectorizing copy for static layouts
289
+ template <class SrcEngine, class SrcLayout,
290
+ class DstEngine, class DstLayout>
291
+ CUTE_HOST_DEVICE
292
+ void
293
+ copy(Tensor<SrcEngine, SrcLayout> const& src,
294
+ Tensor<DstEngine, DstLayout> & dst)
295
+ {
296
+ if constexpr (is_static<SrcLayout>::value && is_static<DstLayout>::value) {
297
+ // Assume Tensors with static layouts (e.g. registers) have pointers that are 128b aligned
298
+ return copy(AutoFilter(AutoVectorizingCopyWithAssumedAlignment<128>{}), src, dst);
299
+ } else
300
+ if constexpr (is_static<decltype(shape(src))>::value && is_static<decltype(shape(dst))>::value) {
301
+ // Tensors with static shapes can be filtered, but do not assume that dynamic layouts are aligned.
302
+ return copy(AutoFilter(AutoVectorizingCopyWithAssumedAlignment<8>{}), src, dst);
303
+ } else {
304
+ // Do not assume that dynamic layouts are aligned.
305
+ return copy(AutoVectorizingCopyWithAssumedAlignment<8>{}, src, dst);
306
+ }
307
+ }
308
+
309
+ // Auto-vectorizing copy with assumed alignment up to 128bit.
310
+ template <class SrcEngine, class SrcLayout,
311
+ class DstEngine, class DstLayout>
312
+ CUTE_HOST_DEVICE
313
+ void
314
+ copy_aligned(Tensor<SrcEngine, SrcLayout> const& src,
315
+ Tensor<DstEngine, DstLayout> & dst)
316
+ {
317
+ if constexpr (is_static<decltype(shape(src))>::value && is_static<decltype(shape(dst))>::value) {
318
+ // Tensors with static shapes can be filtered
319
+ return copy(AutoFilter(AutoVectorizingCopyWithAssumedAlignment<128>{}), src, dst);
320
+ } else {
321
+ return copy(AutoVectorizingCopyWithAssumedAlignment<128>{}, src, dst);
322
+ }
323
+ }
324
+
325
+ // Specializaton for Atom AutoVectorizingCopyAssumedAlignment
326
+ template <int MaxVecBits, class... Args,
327
+ class SrcEngine, class SrcLayout,
328
+ class DstEngine, class DstLayout>
329
+ CUTE_HOST_DEVICE
330
+ void
331
+ copy(Copy_Atom<AutoVectorizingCopyWithAssumedAlignment<MaxVecBits>, Args...> const&,
332
+ Tensor<SrcEngine, SrcLayout> const& src,
333
+ Tensor<DstEngine, DstLayout> & dst)
334
+ {
335
+ return copy(AutoVectorizingCopyWithAssumedAlignment<MaxVecBits>{}, src, dst);
336
+ }
337
+
338
+ #if defined(CUTE_COPY_ATOM_TMA_SM90_ENABLED)
339
+ template <class... CT_Args,
340
+ class SrcEngine, class SrcLayout,
341
+ class DstEngine, class DstLayout>
342
+ CUTE_HOST_DEVICE
343
+ void
344
+ copy(Copy_Traits<SM90_BULK_COPY_AUTO, CT_Args...> const& atom, // Copy_Traits may or may not have the memory barrier in it already
345
+ Tensor<SrcEngine, SrcLayout> const& src,
346
+ Tensor<DstEngine, DstLayout> & dst)
347
+ {
348
+ using SrcType = typename SrcEngine::value_type;
349
+ using DstType = typename DstEngine::value_type;
350
+ static_assert(cute::is_same<SrcType, DstType>::value);
351
+ static_assert((is_gmem<SrcEngine>::value && is_smem<DstEngine>::value) ||
352
+ (is_smem<SrcEngine>::value && is_gmem<DstEngine>::value),
353
+ "Bulk Copy only supports gmem -> smem or smem -> gmem movement.");
354
+ // G2S or S2G dispatch
355
+ using BULK_COPY_OP = conditional_t<is_gmem<SrcEngine>::value,
356
+ SM90_BULK_COPY_G2S,
357
+ SM90_BULK_COPY_S2G>;
358
+
359
+ // Find the common subtensor of src and dst
360
+ auto tiler = max_common_layout(src, dst);
361
+ constexpr int vec_elem = decltype(size(tiler))::value;
362
+ constexpr int vec_bits = vec_elem * sizeof_bits_v<SrcType>;
363
+ static_assert(vec_bits >= 128, "Expected at least 128-bits for BLKCP");
364
+
365
+ // Construct a new concrete Atom of the vector size
366
+ using BulkAtom = Copy_Atom<Copy_Traits<BULK_COPY_OP, Int<vec_bits>, CT_Args...>, SrcType>;
367
+ auto bulk_atom = apply(atom.opargs_, [](auto const&... args) { return BulkAtom{args...}; });
368
+ return copy(bulk_atom, logical_divide(src, tiler), logical_divide(dst, tiler));
369
+ }
370
+
371
+ // Backwards-compat. Throw out any extra Copy_Atom args.
372
+ template <class... CT_Args, class... CA_Args,
373
+ class SrcEngine, class SrcLayout,
374
+ class DstEngine, class DstLayout>
375
+ CUTE_HOST_DEVICE
376
+ void
377
+ copy(Copy_Atom<Copy_Traits<SM90_BULK_COPY_AUTO, CT_Args...>, CA_Args...> const& atom,
378
+ Tensor<SrcEngine, SrcLayout> const& src,
379
+ Tensor<DstEngine, DstLayout> & dst)
380
+ {
381
+ return copy(static_cast<Copy_Traits<SM90_BULK_COPY_AUTO, CT_Args...> const&>(atom), src, dst);
382
+ }
383
+ #endif // #if defined(CUTE_COPY_ATOM_TMA_SM90_ENABLED)
384
+
385
+ //
386
+ // Decay TiledCopy to CopyAtom
387
+ //
388
+
389
+ template <class CopyAtom, class TV, class Tiler,
390
+ class PrdTensor,
391
+ class SrcEngine, class SrcLayout,
392
+ class DstEngine, class DstLayout>
393
+ CUTE_HOST_DEVICE
394
+ void
395
+ copy_if(TiledCopy<CopyAtom, TV, Tiler> const& tiled_copy,
396
+ PrdTensor const& pred,
397
+ Tensor<SrcEngine, SrcLayout> const& src,
398
+ Tensor<DstEngine, DstLayout> & dst)
399
+ {
400
+ return copy_if(static_cast<CopyAtom const&>(tiled_copy), pred, src, dst);
401
+ }
402
+
403
+ template <class CopyAtom, class TV, class Tiler,
404
+ class SrcEngine, class SrcLayout,
405
+ class DstEngine, class DstLayout>
406
+ CUTE_HOST_DEVICE
407
+ void
408
+ copy(TiledCopy<CopyAtom, TV, Tiler> const& tiled_copy,
409
+ Tensor<SrcEngine, SrcLayout> const& src,
410
+ Tensor<DstEngine, DstLayout> & dst)
411
+ {
412
+ return copy(static_cast<CopyAtom const&>(tiled_copy), src, dst);
413
+ }
414
+
415
+ template <class TiledCopy, class ThrIdx,
416
+ class PrdTensor,
417
+ class SrcEngine, class SrcLayout,
418
+ class DstEngine, class DstLayout>
419
+ CUTE_HOST_DEVICE
420
+ void
421
+ copy_if(ThrCopy<TiledCopy, ThrIdx> const& thr_copy,
422
+ PrdTensor const& pred,
423
+ Tensor<SrcEngine, SrcLayout> const& src,
424
+ Tensor<DstEngine, DstLayout> & dst) = delete;
425
+
426
+ template <class TiledCopy, class ThrIdx,
427
+ class SrcEngine, class SrcLayout,
428
+ class DstEngine, class DstLayout>
429
+ CUTE_HOST_DEVICE
430
+ void
431
+ copy(ThrCopy<TiledCopy, ThrIdx> const& thr_copy,
432
+ Tensor<SrcEngine, SrcLayout> const& src,
433
+ Tensor<DstEngine, DstLayout> & dst) = delete;
434
+
435
+ //
436
+ // Catch uncaught policies
437
+ //
438
+
439
+ template <class CopyPolicy,
440
+ class PredTensor,
441
+ class SrcEngine, class SrcLayout,
442
+ class DstEngine, class DstLayout>
443
+ CUTE_HOST_DEVICE
444
+ void
445
+ copy_if(CopyPolicy const& cpy,
446
+ PredTensor const& prd,
447
+ Tensor<SrcEngine, SrcLayout> const& src,
448
+ Tensor<DstEngine, DstLayout> & dst)
449
+ {
450
+ static_assert(dependent_false<CopyPolicy>, "Unrecognized CopyPolicy.");
451
+ }
452
+
453
+ template <class CopyPolicy,
454
+ class SrcEngine, class SrcLayout,
455
+ class DstEngine, class DstLayout>
456
+ CUTE_HOST_DEVICE
457
+ void
458
+ copy(CopyPolicy const& cpy,
459
+ Tensor<SrcEngine, SrcLayout> const& src,
460
+ Tensor<DstEngine, DstLayout> & dst)
461
+ {
462
+ static_assert(dependent_false<CopyPolicy>, "Unrecognized CopyPolicy.");
463
+ }
464
+
465
+ //
466
+ // Accept mutable temporaries
467
+ //
468
+
469
+ template <class PrdTensor,
470
+ class SrcEngine, class SrcLayout,
471
+ class DstEngine, class DstLayout>
472
+ CUTE_HOST_DEVICE
473
+ void
474
+ copy_if(PrdTensor const& pred,
475
+ Tensor<SrcEngine, SrcLayout> const& src,
476
+ Tensor<DstEngine, DstLayout> && dst)
477
+ {
478
+ return copy_if(pred, src, dst);
479
+ }
480
+
481
+ template <class CopyPolicy,
482
+ class PrdTensor,
483
+ class SrcEngine, class SrcLayout,
484
+ class DstEngine, class DstLayout>
485
+ CUTE_HOST_DEVICE
486
+ void
487
+ copy_if(CopyPolicy const& copy_policy,
488
+ PrdTensor const& pred,
489
+ Tensor<SrcEngine, SrcLayout> const& src,
490
+ Tensor<DstEngine, DstLayout> && dst)
491
+ {
492
+ return copy_if(copy_policy, pred, src, dst);
493
+ }
494
+
495
+ template <class SrcEngine, class SrcLayout,
496
+ class DstEngine, class DstLayout>
497
+ CUTE_HOST_DEVICE
498
+ void
499
+ copy(Tensor<SrcEngine, SrcLayout> const& src,
500
+ Tensor<DstEngine, DstLayout> && dst)
501
+ {
502
+ return copy(src, dst);
503
+ }
504
+
505
+ template <class CopyPolicy,
506
+ class SrcEngine, class SrcLayout,
507
+ class DstEngine, class DstLayout>
508
+ CUTE_HOST_DEVICE
509
+ void
510
+ copy(CopyPolicy const& copy_policy,
511
+ Tensor<SrcEngine, SrcLayout> const& src,
512
+ Tensor<DstEngine, DstLayout> && dst)
513
+ {
514
+ return copy(copy_policy, src, dst);
515
+ }
516
+
517
+ template <class SrcEngine, class SrcLayout,
518
+ class DstEngine, class DstLayout>
519
+ CUTE_HOST_DEVICE
520
+ void
521
+ copy_aligned(Tensor<SrcEngine, SrcLayout> const& src,
522
+ Tensor<DstEngine, DstLayout> && dst)
523
+ {
524
+ return copy_aligned(src, dst);
525
+ }
526
+
527
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/fill.hpp ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp>
34
+
35
+ #include <cute/tensor_impl.hpp>
36
+ #include <cute/algorithm/prefer.hpp>
37
+
38
+ namespace cute
39
+ {
40
+
41
+ //
42
+ // Accept mutable temporaries
43
+ //
44
+ template <class Engine, class Layout, class T>
45
+ CUTE_HOST_DEVICE
46
+ void
47
+ fill(Tensor<Engine, Layout>&& tensor, T const& value)
48
+ {
49
+ return fill(tensor, value);
50
+ }
51
+
52
+ namespace detail
53
+ {
54
+
55
+ // Prefer fill(tensor.data(), value), if possible
56
+ template <class Engine, class Layout, class T>
57
+ CUTE_HOST_DEVICE
58
+ auto
59
+ fill(Tensor<Engine, Layout>& tensor, T const& value, prefer<1>)
60
+ -> decltype(fill(tensor.data(), value))
61
+ {
62
+ fill(tensor.data(), value);
63
+ }
64
+
65
+ // Default implementation
66
+ template <class Engine, class Layout, class T>
67
+ CUTE_HOST_DEVICE
68
+ void
69
+ fill(Tensor<Engine, Layout>& tensor, T const& value, prefer<0>)
70
+ {
71
+ CUTE_UNROLL
72
+ for (int i = 0; i < size(tensor); ++i) {
73
+ tensor(i) = value;
74
+ }
75
+ }
76
+
77
+ } // end namespace detail
78
+
79
+ template <class Engine, class Layout, class T>
80
+ CUTE_HOST_DEVICE
81
+ void
82
+ fill(Tensor<Engine, Layout>& tensor, T const& value)
83
+ {
84
+ return detail::fill(tensor, value, prefer<1>{});
85
+ }
86
+
87
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/functional.hpp ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp> // CUTE_HOST_DEVICE
34
+ #include <cute/numeric/math.hpp> // cute::max, cute::min
35
+ #include <cute/numeric/complex.hpp> // cute::conj
36
+
37
+ /** C++14 <functional> extensions */
38
+
39
+ namespace cute {
40
+
41
+ /**************/
42
+ /** Identity **/
43
+ /**************/
44
+
45
+ struct identity {
46
+ template <class T>
47
+ CUTE_HOST_DEVICE constexpr
48
+ decltype(auto) operator()(T&& arg) const {
49
+ return static_cast<T&&>(arg);
50
+ }
51
+ };
52
+
53
+ template <class R>
54
+ struct constant_fn {
55
+ template <class... T>
56
+ CUTE_HOST_DEVICE constexpr
57
+ decltype(auto) operator()(T&&...) const {
58
+ return r_;
59
+ }
60
+ R r_;
61
+ };
62
+
63
+ /***********/
64
+ /** Unary **/
65
+ /***********/
66
+
67
+ #define CUTE_LEFT_UNARY_OP(NAME,OP) \
68
+ struct NAME { \
69
+ template <class T> \
70
+ CUTE_HOST_DEVICE constexpr \
71
+ decltype(auto) operator()(T&& arg) const { \
72
+ return OP static_cast<T&&>(arg); \
73
+ } \
74
+ }
75
+ #define CUTE_RIGHT_UNARY_OP(NAME,OP) \
76
+ struct NAME { \
77
+ template <class T> \
78
+ CUTE_HOST_DEVICE constexpr \
79
+ decltype(auto) operator()(T&& arg) const { \
80
+ return static_cast<T&&>(arg) OP ; \
81
+ } \
82
+ }
83
+ #define CUTE_NAMED_UNARY_OP(NAME,OP) \
84
+ struct NAME { \
85
+ template <class T> \
86
+ CUTE_HOST_DEVICE constexpr \
87
+ decltype(auto) operator()(T&& arg) const { \
88
+ return OP (static_cast<T&&>(arg)); \
89
+ } \
90
+ }
91
+
92
+ CUTE_LEFT_UNARY_OP(unary_plus, +);
93
+ CUTE_LEFT_UNARY_OP(negate, -);
94
+ CUTE_LEFT_UNARY_OP(bit_not, ~);
95
+ CUTE_LEFT_UNARY_OP(logical_not, !);
96
+ CUTE_LEFT_UNARY_OP(dereference, *);
97
+ CUTE_LEFT_UNARY_OP(address_of, &);
98
+ CUTE_LEFT_UNARY_OP(pre_increment, ++);
99
+ CUTE_LEFT_UNARY_OP(pre_decrement, --);
100
+
101
+ CUTE_RIGHT_UNARY_OP(post_increment, ++);
102
+ CUTE_RIGHT_UNARY_OP(post_decrement, --);
103
+
104
+ CUTE_NAMED_UNARY_OP(abs_fn, abs);
105
+ CUTE_NAMED_UNARY_OP(conjugate, cute::conj);
106
+
107
+ #undef CUTE_LEFT_UNARY_OP
108
+ #undef CUTE_RIGHT_UNARY_OP
109
+ #undef CUTE_NAMED_UNARY_OP
110
+
111
+ template <int Shift_>
112
+ struct shift_right_const {
113
+ static constexpr int Shift = Shift_;
114
+
115
+ template <class T>
116
+ CUTE_HOST_DEVICE constexpr
117
+ decltype(auto) operator()(T&& arg) const {
118
+ return static_cast<T&&>(arg) >> Shift;
119
+ }
120
+ };
121
+
122
+ template <int Shift_>
123
+ struct shift_left_const {
124
+ static constexpr int Shift = Shift_;
125
+
126
+ template <class T>
127
+ CUTE_HOST_DEVICE constexpr
128
+ decltype(auto) operator()(T&& arg) const {
129
+ return static_cast<T&&>(arg) << Shift;
130
+ }
131
+ };
132
+
133
+ /************/
134
+ /** Binary **/
135
+ /************/
136
+
137
+ #define CUTE_BINARY_OP(NAME,OP) \
138
+ struct NAME { \
139
+ template <class T, class U> \
140
+ CUTE_HOST_DEVICE constexpr \
141
+ decltype(auto) operator()(T&& lhs, U&& rhs) const { \
142
+ return static_cast<T&&>(lhs) OP static_cast<U&&>(rhs); \
143
+ } \
144
+ }
145
+ #define CUTE_NAMED_BINARY_OP(NAME,OP) \
146
+ struct NAME { \
147
+ template <class T, class U> \
148
+ CUTE_HOST_DEVICE constexpr \
149
+ decltype(auto) operator()(T&& lhs, U&& rhs) const { \
150
+ return OP (static_cast<T&&>(lhs), static_cast<U&&>(rhs)); \
151
+ } \
152
+ }
153
+
154
+
155
+ CUTE_BINARY_OP(plus, +);
156
+ CUTE_BINARY_OP(minus, -);
157
+ CUTE_BINARY_OP(multiplies, *);
158
+ CUTE_BINARY_OP(divides, /);
159
+ CUTE_BINARY_OP(modulus, %);
160
+
161
+ CUTE_BINARY_OP(plus_assign, +=);
162
+ CUTE_BINARY_OP(minus_assign, -=);
163
+ CUTE_BINARY_OP(multiplies_assign, *=);
164
+ CUTE_BINARY_OP(divides_assign, /=);
165
+ CUTE_BINARY_OP(modulus_assign, %=);
166
+
167
+ CUTE_BINARY_OP(bit_and, &);
168
+ CUTE_BINARY_OP(bit_or, |);
169
+ CUTE_BINARY_OP(bit_xor, ^);
170
+ CUTE_BINARY_OP(left_shift, <<);
171
+ CUTE_BINARY_OP(right_shift, >>);
172
+
173
+ CUTE_BINARY_OP(bit_and_assign, &=);
174
+ CUTE_BINARY_OP(bit_or_assign, |=);
175
+ CUTE_BINARY_OP(bit_xor_assign, ^=);
176
+ CUTE_BINARY_OP(left_shift_assign, <<=);
177
+ CUTE_BINARY_OP(right_shift_assign, >>=);
178
+
179
+ CUTE_BINARY_OP(logical_and, &&);
180
+ CUTE_BINARY_OP(logical_or, ||);
181
+
182
+ CUTE_BINARY_OP(equal_to, ==);
183
+ CUTE_BINARY_OP(not_equal_to, !=);
184
+ CUTE_BINARY_OP(greater, >);
185
+ CUTE_BINARY_OP(less, <);
186
+ CUTE_BINARY_OP(greater_equal, >=);
187
+ CUTE_BINARY_OP(less_equal, <=);
188
+
189
+ CUTE_NAMED_BINARY_OP(max_fn, cute::max);
190
+ CUTE_NAMED_BINARY_OP(min_fn, cute::min);
191
+
192
+ #undef CUTE_BINARY_OP
193
+ #undef CUTE_NAMED_BINARY_OP
194
+
195
+ /**********/
196
+ /** Fold **/
197
+ /**********/
198
+
199
+ #define CUTE_FOLD_OP(NAME,OP) \
200
+ struct NAME##_unary_rfold { \
201
+ template <class... T> \
202
+ CUTE_HOST_DEVICE constexpr \
203
+ auto operator()(T&&... t) const { \
204
+ return (t OP ...); \
205
+ } \
206
+ }; \
207
+ struct NAME##_unary_lfold { \
208
+ template <class... T> \
209
+ CUTE_HOST_DEVICE constexpr \
210
+ auto operator()(T&&... t) const { \
211
+ return (... OP t); \
212
+ } \
213
+ }; \
214
+ struct NAME##_binary_rfold { \
215
+ template <class U, class... T> \
216
+ CUTE_HOST_DEVICE constexpr \
217
+ auto operator()(U&& u, T&&... t) const { \
218
+ return (t OP ... OP u); \
219
+ } \
220
+ }; \
221
+ struct NAME##_binary_lfold { \
222
+ template <class U, class... T> \
223
+ CUTE_HOST_DEVICE constexpr \
224
+ auto operator()(U&& u, T&&... t) const { \
225
+ return (u OP ... OP t); \
226
+ } \
227
+ }
228
+
229
+ CUTE_FOLD_OP(plus, +);
230
+ CUTE_FOLD_OP(minus, -);
231
+ CUTE_FOLD_OP(multiplies, *);
232
+ CUTE_FOLD_OP(divides, /);
233
+ CUTE_FOLD_OP(modulus, %);
234
+
235
+ CUTE_FOLD_OP(plus_assign, +=);
236
+ CUTE_FOLD_OP(minus_assign, -=);
237
+ CUTE_FOLD_OP(multiplies_assign, *=);
238
+ CUTE_FOLD_OP(divides_assign, /=);
239
+ CUTE_FOLD_OP(modulus_assign, %=);
240
+
241
+ CUTE_FOLD_OP(bit_and, &);
242
+ CUTE_FOLD_OP(bit_or, |);
243
+ CUTE_FOLD_OP(bit_xor, ^);
244
+ CUTE_FOLD_OP(left_shift, <<);
245
+ CUTE_FOLD_OP(right_shift, >>);
246
+
247
+ CUTE_FOLD_OP(bit_and_assign, &=);
248
+ CUTE_FOLD_OP(bit_or_assign, |=);
249
+ CUTE_FOLD_OP(bit_xor_assign, ^=);
250
+ CUTE_FOLD_OP(left_shift_assign, <<=);
251
+ CUTE_FOLD_OP(right_shift_assign, >>=);
252
+
253
+ CUTE_FOLD_OP(logical_and, &&);
254
+ CUTE_FOLD_OP(logical_or, ||);
255
+
256
+ CUTE_FOLD_OP(equal_to, ==);
257
+ CUTE_FOLD_OP(not_equal_to, !=);
258
+ CUTE_FOLD_OP(greater, >);
259
+ CUTE_FOLD_OP(less, <);
260
+ CUTE_FOLD_OP(greater_equal, >=);
261
+ CUTE_FOLD_OP(less_equal, <=);
262
+
263
+ #undef CUTE_FOLD_OP
264
+
265
+ /**********/
266
+ /** Meta **/
267
+ /**********/
268
+
269
+ template <class Fn, class Arg>
270
+ struct bound_fn {
271
+
272
+ template <class T>
273
+ CUTE_HOST_DEVICE constexpr
274
+ decltype(auto)
275
+ operator()(T&& arg) {
276
+ return fn_(arg_, static_cast<T&&>(arg));
277
+ }
278
+
279
+ Fn fn_;
280
+ Arg arg_;
281
+ };
282
+
283
+ template <class Fn, class Arg>
284
+ CUTE_HOST_DEVICE constexpr
285
+ auto
286
+ bind(Fn const& fn, Arg const& arg) {
287
+ return bound_fn<Fn,Arg>{fn, arg};
288
+ }
289
+
290
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/gemm.hpp ADDED
@@ -0,0 +1,500 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp>
34
+
35
+ #include <cute/util/type_traits.hpp>
36
+ #include <cute/algorithm/functional.hpp>
37
+
38
+ #include <cute/tensor_impl.hpp>
39
+
40
+ #include <cute/atom/mma_atom.hpp>
41
+
42
+ /** The gemm algorithm takes four (or three) tensors and computes
43
+ * D = A * B + C
44
+ * It dispatches based on the number of modes each tensor has:
45
+ *
46
+ * 1. `(V) x (V) => (V)`.
47
+ * The element-wise product of vectors. Dispatches to FMA or MMA.
48
+ * 2. `(M) x (N) => (M,N)`.
49
+ * The outer product of vectors. Dispatches to [3] with new mode K=(1).
50
+ * 3. `(M,K) x (N,K) => (M,N)`.
51
+ * The product of matrices. Dispatches to [5] with MMA vector-mode V.
52
+ * 4. `(V,M) x (V,N) => (V,M,N)`.
53
+ * The batched outer product of vectors. Accounts for register reuse and dispatches to [1] for each (m,n).
54
+ * 5. `(V,M,K) x (V,N,K) => (V,M,N)`.
55
+ * The batched product of matrices. Dispatches to [4] for each (k).
56
+ */
57
+
58
+ namespace cute
59
+ {
60
+
61
+ //
62
+ // Three arguments to four
63
+ //
64
+
65
+ template <class TA, class ALayout,
66
+ class TB, class BLayout,
67
+ class TC, class CLayout>
68
+ CUTE_HOST_DEVICE
69
+ void
70
+ gemm(Tensor<TA, ALayout> const& A,
71
+ Tensor<TB, BLayout> const& B,
72
+ Tensor<TC, CLayout> & C)
73
+ {
74
+ return gemm(C, A, B, C);
75
+ }
76
+
77
+ template <class MMA,
78
+ class TA, class ALayout,
79
+ class TB, class BLayout,
80
+ class TC, class CLayout>
81
+ CUTE_HOST_DEVICE
82
+ void
83
+ gemm(MMA_Atom<MMA> const& mma,
84
+ Tensor<TA, ALayout> const& A,
85
+ Tensor<TB, BLayout> const& B,
86
+ Tensor<TC, CLayout> & C)
87
+ {
88
+ return gemm(mma, C, A, B, C);
89
+ }
90
+
91
+ //
92
+ // Accept mutable temporaries
93
+ //
94
+
95
+ template <class TA, class ALayout,
96
+ class TB, class BLayout,
97
+ class TC, class CLayout>
98
+ CUTE_HOST_DEVICE
99
+ void
100
+ gemm(Tensor<TA, ALayout> const& A,
101
+ Tensor<TB, BLayout> const& B,
102
+ Tensor<TC, CLayout> && C)
103
+ {
104
+ return gemm(C, A, B, C);
105
+ }
106
+
107
+ template <class TD, class DLayout,
108
+ class TA, class ALayout,
109
+ class TB, class BLayout,
110
+ class TC, class CLayout>
111
+ CUTE_HOST_DEVICE
112
+ void
113
+ gemm(Tensor<TD, DLayout> && D,
114
+ Tensor<TA, ALayout> const& A,
115
+ Tensor<TB, BLayout> const& B,
116
+ Tensor<TC, CLayout> const& C)
117
+ {
118
+ return gemm(D, A, B, C);
119
+ }
120
+
121
+ template <class MMA,
122
+ class TA, class ALayout,
123
+ class TB, class BLayout,
124
+ class TC, class CLayout>
125
+ CUTE_HOST_DEVICE
126
+ void
127
+ gemm(MMA_Atom<MMA> const& mma,
128
+ Tensor<TA, ALayout> const& A,
129
+ Tensor<TB, BLayout> const& B,
130
+ Tensor<TC, CLayout> && C)
131
+ {
132
+ return gemm(mma, C, A, B, C);
133
+ }
134
+
135
+ template <class MMA,
136
+ class TD, class DLayout,
137
+ class TA, class ALayout,
138
+ class TB, class BLayout,
139
+ class TC, class CLayout>
140
+ CUTE_HOST_DEVICE
141
+ void
142
+ gemm(MMA_Atom<MMA> const& mma,
143
+ Tensor<TD, DLayout> && D,
144
+ Tensor<TA, ALayout> const& A,
145
+ Tensor<TB, BLayout> const& B,
146
+ Tensor<TC, CLayout> const& C)
147
+ {
148
+ return gemm(mma, D, A, B, C);
149
+ }
150
+
151
+ //
152
+ // Default MMA is UniversalFMA
153
+ //
154
+
155
+ template <class TD, class DLayout,
156
+ class TA, class ALayout,
157
+ class TB, class BLayout,
158
+ class TC, class CLayout>
159
+ CUTE_HOST_DEVICE
160
+ void
161
+ gemm(Tensor<TD, DLayout> & D,
162
+ Tensor<TA, ALayout> const& A,
163
+ Tensor<TB, BLayout> const& B,
164
+ Tensor<TC, CLayout> const& C)
165
+ {
166
+ using MMA = MMA_Atom<UniversalFMA<typename Tensor<TD,DLayout>::value_type,
167
+ typename Tensor<TA,ALayout>::value_type,
168
+ typename Tensor<TB,BLayout>::value_type,
169
+ typename Tensor<TC,CLayout>::value_type>>;
170
+
171
+ return gemm(MMA{}, D, A, B, C);
172
+ }
173
+
174
+ //
175
+ // Thread-Local Register-Memory GEMMs
176
+ //
177
+
178
+ // Dispatch [1]: (V) x (V) => (V)
179
+ template <class MMA,
180
+ class TD, class DLayout,
181
+ class TA, class ALayout,
182
+ class TB, class BLayout,
183
+ class TC, class CLayout,
184
+ __CUTE_REQUIRES(DLayout::rank == 1 && is_rmem<TD>::value &&
185
+ ALayout::rank == 1 && is_rmem<TA>::value &&
186
+ BLayout::rank == 1 && is_rmem<TB>::value &&
187
+ CLayout::rank == 1 && is_rmem<TC>::value)>
188
+ CUTE_HOST_DEVICE
189
+ void
190
+ gemm(MMA_Atom<MMA> const& mma,
191
+ Tensor<TD, DLayout> & D, // (V) Logical data
192
+ Tensor<TA, ALayout> const& A, // (V) Logical data
193
+ Tensor<TB, BLayout> const& B, // (V) Logical data
194
+ Tensor<TC, CLayout> const& C) // (V) Logical data
195
+ {
196
+ // No static assertions on (V), MMA checks compatibility
197
+ mma.call(D, A, B, C);
198
+ }
199
+
200
+ // Dispatch [2]: (M) x (N) => (M,N)
201
+ template <class MMA,
202
+ class TD, class DLayout,
203
+ class TA, class ALayout,
204
+ class TB, class BLayout,
205
+ class TC, class CLayout,
206
+ __CUTE_REQUIRES(DLayout::rank == 2 && is_rmem<TD>::value &&
207
+ ALayout::rank == 1 && is_rmem<TA>::value &&
208
+ BLayout::rank == 1 && is_rmem<TB>::value &&
209
+ CLayout::rank == 2 && is_rmem<TC>::value)>
210
+ CUTE_HOST_DEVICE
211
+ void
212
+ gemm(MMA_Atom<MMA> const& mma,
213
+ Tensor<TD, DLayout> & D, // (M,N) Logical data
214
+ Tensor<TA, ALayout> const& A, // (M) Logical data
215
+ Tensor<TB, BLayout> const& B, // (N) Logical data
216
+ Tensor<TC, CLayout> const& C) // (M,N) Logical data
217
+ {
218
+ CUTE_STATIC_ASSERT_V(size<0>(A) == size<0>(C)); // AM == CM
219
+ CUTE_STATIC_ASSERT_V(size<0>(B) == size<1>(C)); // BN == CN
220
+ CUTE_STATIC_ASSERT_V(size<0>(C) == size<0>(D) && size<1>(C) == size<1>(D));
221
+ gemm(mma,
222
+ D, // (M,N)
223
+ make_tensor(A.data(), append<2>(A.layout())), // (M,1)
224
+ make_tensor(B.data(), append<2>(B.layout())), // (N,1)
225
+ C); // (M,N)
226
+ }
227
+
228
+ // Dispatch [3]: (M,K) x (N,K) => (M,N)
229
+ template <class MMA,
230
+ class TD, class DLayout,
231
+ class TA, class ALayout,
232
+ class TB, class BLayout,
233
+ class TC, class CLayout,
234
+ __CUTE_REQUIRES(DLayout::rank == 2 && is_rmem<TD>::value &&
235
+ ALayout::rank == 2 && is_rmem<TA>::value &&
236
+ BLayout::rank == 2 && is_rmem<TB>::value &&
237
+ CLayout::rank == 2 && is_rmem<TC>::value)>
238
+ CUTE_HOST_DEVICE
239
+ void
240
+ gemm(MMA_Atom<MMA> const& mma,
241
+ Tensor<TD, DLayout> & D, // (M,N) Logical data
242
+ Tensor<TA, ALayout> const& A, // (M,K) Logical data
243
+ Tensor<TB, BLayout> const& B, // (N,K) Logical data
244
+ Tensor<TC, CLayout> const& C) // (M,N) Logical data
245
+ {
246
+ CUTE_STATIC_ASSERT_V(size<0>(A) == size<0>(C)); // AM == CM
247
+ CUTE_STATIC_ASSERT_V(size<0>(B) == size<1>(C)); // BN == CN
248
+ CUTE_STATIC_ASSERT_V(size<1>(A) == size<1>(B)); // AK == BK
249
+ CUTE_STATIC_ASSERT_V(size<0>(C) == size<0>(D) && size<1>(C) == size<1>(D));
250
+
251
+ // Assert this is a 1-value MMA
252
+ CUTE_STATIC_ASSERT_V(size<1>(typename MMA_Atom<MMA>::LayoutC_TV{}) == Int<1>{});
253
+ CUTE_STATIC_ASSERT_V(size<1>(typename MMA_Atom<MMA>::LayoutA_TV{}) == Int<1>{});
254
+ CUTE_STATIC_ASSERT_V(size<1>(typename MMA_Atom<MMA>::LayoutB_TV{}) == Int<1>{});
255
+
256
+ gemm(mma,
257
+ make_tensor(D.data(), prepend<3>(D.layout())), // (1,M,N)
258
+ make_tensor(A.data(), prepend<3>(A.layout())), // (1,M,K)
259
+ make_tensor(B.data(), prepend<3>(B.layout())), // (1,N,K)
260
+ make_tensor(C.data(), prepend<3>(C.layout()))); // (1,M,N)
261
+ }
262
+
263
+ // Dispatch [4]: (V,M) x (V,N) => (V,M,N)
264
+ template <class MMA,
265
+ class TD, class DLayout,
266
+ class TA, class ALayout,
267
+ class TB, class BLayout,
268
+ class TC, class CLayout,
269
+ __CUTE_REQUIRES(DLayout::rank == 3 && is_rmem<TD>::value &&
270
+ ALayout::rank == 2 && is_rmem<TA>::value &&
271
+ BLayout::rank == 2 && is_rmem<TB>::value &&
272
+ CLayout::rank == 3 && is_rmem<TC>::value)>
273
+ CUTE_HOST_DEVICE
274
+ void
275
+ gemm(MMA_Atom<MMA> const& mma,
276
+ Tensor<TD, DLayout> & D, // (V,M,N) Logical data
277
+ Tensor<TA, ALayout> const& A, // (V,M) Logical data
278
+ Tensor<TB, BLayout> const& B, // (V,N) Logical data
279
+ Tensor<TC, CLayout> const& C) // (V,M,N) Logical data
280
+ {
281
+ CUTE_STATIC_ASSERT_V(size<1>(A) == size<1>(C)); // AM == CM
282
+ CUTE_STATIC_ASSERT_V(size<1>(B) == size<2>(C)); // BN == CN
283
+ CUTE_STATIC_ASSERT_V(size<0>(C) == size<0>(D) && size<1>(C) == size<1>(D) && size<2>(C) == size<2>(D));
284
+ auto M = size<1>(A);
285
+ auto N = size<1>(B);
286
+ // REGISTER .reuse OPTIMIZATIONS
287
+ // 64-bit traversal specialization -- serpentine path
288
+ if constexpr (decltype(size<0>(A))::value * sizeof(typename TA::value_type) == 8 &&
289
+ decltype(size<0>(B))::value * sizeof(typename TB::value_type) == 8)
290
+ {
291
+ #if 1 // NOTE: Row- vs Col- major could depend on the C-matrix order... (which we can test)
292
+ // Row-major serpentine iteration
293
+ CUTE_UNROLL
294
+ for (int m = 0; m < M; ++m) {
295
+ CUTE_UNROLL
296
+ for (int n = 0; n < N; ++n) {
297
+ int ns = (m & 1) ? N-1-n : n; // Serpentine coordinate
298
+ gemm(mma, D(_,m,ns), A(_,m), B(_,ns), C(_,m,ns));
299
+ }
300
+ }
301
+ #else
302
+ // Col-major serpentine iteration
303
+ CUTE_UNROLL
304
+ for (int n = 0; n < N; ++n) {
305
+ CUTE_UNROLL
306
+ for (int m = 0; m < M; ++m) {
307
+ int ms = (n & 1) ? M-1-m : m; // Serpentine coordinate
308
+ gemm(mma, D(_,ms,n), A(_,ms), B(_,n), C(_,ms,n));
309
+ }
310
+ }
311
+ #endif
312
+ } else
313
+ // 32-bit traversal specialization -- kinked serpentine path
314
+ if constexpr (decltype(size<0>(A))::value * sizeof(typename TA::value_type) == 4 &&
315
+ decltype(size<0>(B))::value * sizeof(typename TB::value_type) == 4)
316
+ {
317
+ #if 1 // NOTE: Row- vs Col- major could depend on the C-matrix order... (which we can test)
318
+ // Row-major kinked serpentine iteration
319
+ CUTE_UNROLL
320
+ for (int m = 0; m < M; m += 2) {
321
+ CUTE_UNROLL
322
+ for (int n = 0; n < N; ++n) {
323
+ int ns = (m & 2) ? N-1-n : n;
324
+ gemm(mma, D(_,m+0,ns), A(_,m+0), B(_,ns), C(_,m+0,ns));
325
+
326
+ if (m+1 < M) {
327
+ gemm(mma, D(_,m+1,ns), A(_,m+1), B(_,ns), C(_,m+1,ns));
328
+ }
329
+ }
330
+ }
331
+ #else
332
+ // Col-major kinked serpentine iteration
333
+ CUTE_UNROLL
334
+ for (int n = 0; n < N; n += 2) {
335
+ CUTE_UNROLL
336
+ for (int m = 0; m < M; ++m) {
337
+ // Kinked serpentine traversal for maximum register reuse
338
+ int ms = (n & 2) ? M-1-m : m;
339
+ gemm(mma, D(_,ms,n+0), A(_,ms), B(_,n+0), C(_,ms,n+0));
340
+
341
+ if (n+1 < N) {
342
+ gemm(mma, D(_,ms,n+1), A(_,ms), B(_,n+1), C(_,ms,n+1));
343
+ }
344
+ }
345
+ }
346
+ #endif
347
+ } else
348
+ // 64-bit + 32-bit traversal order -- keep A (64-bit) in the outer loop and serpentine B
349
+ if constexpr (decltype(size<0>(A))::value * sizeof(typename TA::value_type) == 8 &&
350
+ decltype(size<0>(B))::value * sizeof(typename TB::value_type) == 4) {
351
+ // Row-major serpentine iteration
352
+ CUTE_UNROLL
353
+ for (int m = 0; m < M; ++m) {
354
+ CUTE_UNROLL
355
+ for (int n = 0; n < N; ++n) {
356
+ int ns = (m & 1) ? N-1-n : n; // Serpentine coordinate
357
+ gemm(mma, D(_,m,ns), A(_,m), B(_,ns), C(_,m,ns));
358
+ }
359
+ }
360
+ } else
361
+ // 32-bit + 64-bit traversal order -- keep B (64-bit) in the outer loop and serpentine A
362
+ if constexpr (decltype(size<0>(A))::value * sizeof(typename TA::value_type) == 4 &&
363
+ decltype(size<0>(B))::value * sizeof(typename TB::value_type) == 8) {
364
+ // Col-major serpentine iteration
365
+ CUTE_UNROLL
366
+ for (int n = 0; n < N; ++n) {
367
+ CUTE_UNROLL
368
+ for (int m = 0; m < M; ++m) {
369
+ int ms = (n & 1) ? M-1-m : m; // Serpentine coordinate
370
+ gemm(mma, D(_,ms,n), A(_,ms), B(_,n), C(_,ms,n));
371
+ }
372
+ }
373
+ } else
374
+ // Fallback to serpentine loop
375
+ {
376
+ // Col-major serpentine iteration
377
+ CUTE_UNROLL
378
+ for (int n = 0; n < N; ++n) {
379
+ CUTE_UNROLL
380
+ for (int m = 0; m < M; ++m) {
381
+ int ms = (n & 1) ? M-1-m : m; // Serpentine coordinate
382
+ gemm(mma, D(_,ms,n), A(_,ms), B(_,n), C(_,ms,n));
383
+ }
384
+ }
385
+ }
386
+ }
387
+
388
+ // Dispatch [5]: (V,M,K) x (V,N,K) => (V,M,N)
389
+ template <class MMA,
390
+ class TD, class DLayout,
391
+ class TA, class ALayout,
392
+ class TB, class BLayout,
393
+ class TC, class CLayout,
394
+ __CUTE_REQUIRES(DLayout::rank == 3 && is_rmem<TD>::value &&
395
+ ALayout::rank == 3 && is_rmem<TA>::value &&
396
+ BLayout::rank == 3 && is_rmem<TB>::value &&
397
+ CLayout::rank == 3 && is_rmem<TC>::value)>
398
+ CUTE_HOST_DEVICE
399
+ void
400
+ gemm(MMA_Atom<MMA> const& mma,
401
+ Tensor<TD, DLayout> & D, // (V,M,N) Logical data
402
+ Tensor<TA, ALayout> const& A, // (V,M,K) Logical data
403
+ Tensor<TB, BLayout> const& B, // (V,N,K) Logical data
404
+ Tensor<TC, CLayout> const& C) // (V,M,N) Logical data
405
+ {
406
+ CUTE_STATIC_ASSERT_V(size<1>(A) == size<1>(C)); // AM == CM
407
+ CUTE_STATIC_ASSERT_V(size<1>(B) == size<2>(C)); // BN == CN
408
+ CUTE_STATIC_ASSERT_V(size<2>(A) == size<2>(B)); // AK == BK
409
+ CUTE_STATIC_ASSERT_V(size<0>(C) == size<0>(D) && size<1>(C) == size<1>(D) && size<2>(C) == size<2>(D));
410
+ auto K = size<2>(A);
411
+
412
+ CUTE_UNROLL
413
+ for (int k = 0; k < K; ++k) {
414
+ gemm(mma, D, A(_,_,k), B(_,_,k), C);
415
+ }
416
+ }
417
+
418
+ //
419
+ // Thread-Local Shared-Memory GEMMs
420
+ //
421
+
422
+ // Dispatch [1]: (V) x (V) => (V)
423
+ // Dispatch [2]: (M) x (N) => (M,N)
424
+ // Dispatch [3]: (M,K) x (N,K) => (M,N)
425
+ // Dispatch [4]: (V,M) x (V,N) => (V,M,N)
426
+ // Dispatch [5]: (V,M,K) x (V,N,K) => (V,M,N)
427
+ // Dispatch [3]: (M,K) x (N,K) => (M,N)
428
+ template <class MMA,
429
+ class TD, class DLayout,
430
+ class TA, class ALayout,
431
+ class TB, class BLayout,
432
+ class TC, class CLayout,
433
+ __CUTE_REQUIRES(DLayout::rank == 2 && is_rmem<TD>::value &&
434
+ ALayout::rank == 2 && is_smem<TA>::value &&
435
+ BLayout::rank == 2 && is_smem<TB>::value &&
436
+ CLayout::rank == 2 && is_rmem<TC>::value)>
437
+ CUTE_HOST_DEVICE
438
+ void
439
+ gemm(MMA_Atom<MMA> const& mma,
440
+ Tensor<TD, DLayout> & D, // (M,N) Logical data
441
+ Tensor<TA, ALayout> const& A, // (M,K) Logical data
442
+ Tensor<TB, BLayout> const& B, // (N,K) Logical data
443
+ Tensor<TC, CLayout> const& C) // (M,N) Logical data
444
+ {
445
+ CUTE_STATIC_ASSERT_V(size<0>(A) == size<0>(C)); // AM == CM
446
+ CUTE_STATIC_ASSERT_V(size<0>(B) == size<1>(C)); // BN == CN
447
+ CUTE_STATIC_ASSERT_V(size<1>(A) == size<1>(B)); // AK == BK
448
+ CUTE_STATIC_ASSERT_V(size<0>(C) == size<0>(D) && size<1>(C) == size<1>(D));
449
+
450
+ // Assert this is a 1-value MMA
451
+ CUTE_STATIC_ASSERT_V(size<1>(typename MMA_Atom<MMA>::LayoutC_TV{}) == Int<1>{});
452
+ CUTE_STATIC_ASSERT_V(size<1>(typename MMA_Atom<MMA>::LayoutA_TV{}) == Int<1>{});
453
+ CUTE_STATIC_ASSERT_V(size<1>(typename MMA_Atom<MMA>::LayoutB_TV{}) == Int<1>{});
454
+
455
+ gemm(mma,
456
+ make_tensor(D.data(), prepend<3>(D.layout())), // (1,M,N)
457
+ make_tensor(A.data(), prepend<3>(A.layout())), // (1,M,K)
458
+ make_tensor(B.data(), prepend<3>(B.layout())), // (1,N,K)
459
+ make_tensor(C.data(), prepend<3>(C.layout()))); // (1,M,N)
460
+ }
461
+
462
+ // Dispatch [5]: (V,M,K) x (V,N,K) => (V,M,N)
463
+ template <class MMA,
464
+ class TD, class DLayout,
465
+ class TA, class ALayout,
466
+ class TB, class BLayout,
467
+ class TC, class CLayout,
468
+ __CUTE_REQUIRES(DLayout::rank == 3 && is_rmem<TD>::value &&
469
+ ALayout::rank == 3 && is_smem<TA>::value &&
470
+ BLayout::rank == 3 && is_smem<TB>::value &&
471
+ CLayout::rank == 3 && is_rmem<TC>::value)>
472
+ CUTE_HOST_DEVICE
473
+ void
474
+ gemm(MMA_Atom<MMA> const& mma,
475
+ Tensor<TD, DLayout> & D, // (V,M,N) Logical data
476
+ Tensor<TA, ALayout> const& A, // (V,M,K) Logical data
477
+ Tensor<TB, BLayout> const& B, // (V,N,K) Logical data
478
+ Tensor<TC, CLayout> const& C) // (V,M,N) Logical data
479
+ {
480
+ CUTE_STATIC_ASSERT_V(size<1>(A) == size<1>(C)); // AM == CM
481
+ CUTE_STATIC_ASSERT_V(size<1>(B) == size<2>(C)); // BN == CN
482
+ CUTE_STATIC_ASSERT_V(size<2>(A) == size<2>(B)); // AK == BK
483
+ CUTE_STATIC_ASSERT_V(size<0>(C) == size<0>(D) && size<1>(C) == size<1>(D) && size<2>(C) == size<2>(D));
484
+
485
+ auto rA = MMA_Atom<MMA>::make_fragment_A(A);
486
+ auto rB = MMA_Atom<MMA>::make_fragment_B(B);
487
+
488
+ auto K = size<2>(A);
489
+
490
+ CUTE_UNROLL
491
+ for (int k = 0; k < K; ++k)
492
+ {
493
+ copy(A(_,_,k), rA(_,_,k));
494
+ copy(B(_,_,k), rB(_,_,k));
495
+ // Thread-level register gemm for k
496
+ gemm(mma, D, rA(_,_,k), rB(_,_,k), C);
497
+ }
498
+ }
499
+
500
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/prefer.hpp ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ namespace cute
34
+ {
35
+
36
+ // Infinite types that inherit from each other
37
+ template <size_t N>
38
+ struct prefer : prefer<N-1> {};
39
+
40
+ template <>
41
+ struct prefer<0> {};
42
+
43
+ // Can be used to preferencially overload implementations
44
+ // Higher N in prefer<N> have higher priority.
45
+
46
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/prefetch.hpp ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2024 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp> // CUTE_HOST_DEVICE
34
+ #include <cute/tensor_impl.hpp> // cute::Tensor
35
+ #include <cute/atom/copy_atom.hpp> // cute::Copy_Atom
36
+
37
+ namespace cute
38
+ {
39
+
40
+ //
41
+ // Prefetch global tensors into L2
42
+ //
43
+
44
+ template <uint32_t NumThreads, uint32_t FetchBytes = 64,
45
+ class GEngine, class GLayout>
46
+ CUTE_HOST_DEVICE
47
+ void
48
+ cooperative_prefetch(uint32_t const& tid,
49
+ Tensor<GEngine, GLayout> const& src)
50
+ {
51
+ static_assert(is_gmem<GEngine>::value, "Expected global tensor for prefetch");
52
+
53
+ constexpr int V = decltype(max_common_vector(src, src))::value;
54
+
55
+ if constexpr (V > 1) {
56
+ // L2 sector is 32B, default fetch granularity is 64B
57
+ using VecType = conditional_t<(V * sizeof_bits_v<typename GEngine::value_type>) < (FetchBytes * 8),
58
+ ArrayEngine<typename GEngine::value_type, V>,
59
+ uint8_t[FetchBytes] >;
60
+
61
+ Tensor src_v = recast<VecType const>(src);
62
+ CUTE_UNROLL
63
+ for (int i = tid; i < size(src_v); i += NumThreads) {
64
+ prefetch(raw_pointer_cast(&src_v(i)));
65
+ }
66
+ } else {
67
+ CUTE_UNROLL
68
+ for (int i = tid; i < size(src); i += NumThreads) {
69
+ prefetch(raw_pointer_cast(&src(i)));
70
+ }
71
+ }
72
+ }
73
+
74
+ template <class GEngine, class GLayout>
75
+ CUTE_HOST_DEVICE
76
+ void
77
+ prefetch(Tensor<GEngine, GLayout> const& src)
78
+ {
79
+ return cooperative_prefetch<1>(0, src);
80
+ }
81
+
82
+ // Prefetch with copy atom
83
+ namespace detail {
84
+
85
+ template <class CopyOp, class = void>
86
+ constexpr bool has_prefetch = false;
87
+
88
+ template <class CopyOp>
89
+ constexpr bool has_prefetch<CopyOp, void_t<typename CopyOp::PREFETCH>> = true;
90
+
91
+ } // end namespace detail
92
+
93
+ template <class CopyOp, class... CT_Args, class... CA_Args,
94
+ class GEngine, class GLayout>
95
+ CUTE_HOST_DEVICE
96
+ void
97
+ prefetch(Copy_Atom<Copy_Traits<CopyOp, CT_Args...>, CA_Args...> const& atom,
98
+ Tensor<GEngine, GLayout> const& src)
99
+ {
100
+ if constexpr (detail::has_prefetch<CopyOp>) {
101
+ using Prefetch_Traits = Copy_Traits<typename CopyOp::PREFETCH, CT_Args...>;
102
+ using Prefetch_Atom = Copy_Atom<Prefetch_Traits, CA_Args...>;
103
+ Prefetch_Atom prefetch_atom{atom};
104
+ auto& dst = const_cast<Tensor<GEngine, GLayout>&>(src); // dst is ignored for prefetch atoms
105
+ return copy(prefetch_atom, src, dst);
106
+ } else {
107
+ return prefetch(src);
108
+ }
109
+ }
110
+
111
+ #if defined(CUTE_COPY_ATOM_TMA_SM90_ENABLED)
112
+ template <class... CT_Args,
113
+ class SrcEngine, class SrcLayout>
114
+ CUTE_HOST_DEVICE
115
+ void
116
+ prefetch(Copy_Traits<SM90_BULK_COPY_AUTO, CT_Args...> const& atom,
117
+ Tensor<SrcEngine, SrcLayout> const& src)
118
+ {
119
+ using SrcType = typename SrcEngine::value_type;
120
+ static_assert(is_gmem<SrcEngine>::value, "Expected global tensor for L2 prefetch");
121
+
122
+ auto tiler = max_common_layout(src, src);
123
+ constexpr int vec_elem = decltype(size(tiler))::value;
124
+ constexpr int vec_bits = vec_elem * sizeof_bits_v<SrcType>;
125
+ static_assert(vec_bits >= 128, "Expected at least 128-bits for BLKCP");
126
+
127
+ // Construct a new concrete Atom of the vector size
128
+ auto bulk_atom = Copy_Atom<Copy_Traits<SM90_BULK_COPY_G2S, Int<vec_bits>>, SrcType>{};
129
+
130
+ return prefetch(bulk_atom, logical_divide(src, tiler));
131
+ }
132
+
133
+ // Backwards-compat. Throw out any extra Copy_Atom args.
134
+ template <class... CT_Args, class... CA_Args,
135
+ class SrcEngine, class SrcLayout>
136
+ CUTE_HOST_DEVICE
137
+ void
138
+ prefetch(Copy_Atom<Copy_Traits<SM90_BULK_COPY_AUTO, CT_Args...>, CA_Args...> const& atom,
139
+ Tensor<SrcEngine, SrcLayout> const& src)
140
+ {
141
+ return prefetch(static_cast<Copy_Traits<SM90_BULK_COPY_AUTO, CT_Args...> const&>(atom), src);
142
+ }
143
+ #endif // #if defined(CUTE_COPY_ATOM_TMA_SM90_ENABLED)
144
+
145
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/tensor_algorithms.hpp ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ /** Common algorithms on (hierarchical) tensors */
32
+
33
+ #pragma once
34
+
35
+ #include <cute/config.hpp>
36
+ #include <cute/tensor_impl.hpp>
37
+
38
+ namespace cute
39
+ {
40
+
41
+ //
42
+ // for_each
43
+ //
44
+
45
+ template <class Engine, class Layout, class UnaryOp>
46
+ CUTE_HOST_DEVICE constexpr
47
+ void
48
+ for_each(Tensor<Engine,Layout> const& tensor, UnaryOp&& op)
49
+ {
50
+ CUTE_UNROLL
51
+ for (int i = 0; i < size(tensor); ++i) {
52
+ op(tensor(i));
53
+ }
54
+ }
55
+
56
+ template <class Engine, class Layout, class UnaryOp>
57
+ CUTE_HOST_DEVICE constexpr
58
+ void
59
+ for_each(Tensor<Engine,Layout>& tensor, UnaryOp&& op)
60
+ {
61
+ CUTE_UNROLL
62
+ for (int i = 0; i < size(tensor); ++i) {
63
+ op(tensor(i));
64
+ }
65
+ }
66
+
67
+ // Accept mutable temporaries
68
+ template <class Engine, class Layout, class UnaryOp>
69
+ CUTE_HOST_DEVICE constexpr
70
+ void
71
+ for_each(Tensor<Engine,Layout>&& tensor, UnaryOp&& op)
72
+ {
73
+ return for_each(tensor, op);
74
+ }
75
+
76
+ //
77
+ // transform
78
+ //
79
+
80
+ // Similar to std::transform but does not return number of elements affected
81
+ template <class Engine, class Layout, class UnaryOp>
82
+ CUTE_HOST_DEVICE constexpr
83
+ void
84
+ transform(Tensor<Engine,Layout>& tensor, UnaryOp&& op)
85
+ {
86
+ CUTE_UNROLL
87
+ for (int i = 0; i < size(tensor); ++i) {
88
+ tensor(i) = op(tensor(i));
89
+ }
90
+ }
91
+
92
+ // Accept mutable temporaries
93
+ template <class Engine, class Layout, class UnaryOp>
94
+ CUTE_HOST_DEVICE constexpr
95
+ void
96
+ transform(Tensor<Engine,Layout>&& tensor, UnaryOp&& op)
97
+ {
98
+ return transform(tensor, op);
99
+ }
100
+
101
+ // Similar to std::transform transforms one tensors and assigns it to another
102
+ template <class EngineIn, class LayoutIn,
103
+ class EngineOut, class LayoutOut,
104
+ class UnaryOp>
105
+ CUTE_HOST_DEVICE constexpr
106
+ void
107
+ transform(Tensor<EngineIn, LayoutIn > const& tensor_in,
108
+ Tensor<EngineOut,LayoutOut> & tensor_out,
109
+ UnaryOp&& op)
110
+ {
111
+ CUTE_UNROLL
112
+ for (int i = 0; i < size(tensor_in); ++i) {
113
+ tensor_out(i) = op(tensor_in(i));
114
+ }
115
+ }
116
+
117
+ // Accept mutable temporaries
118
+ template <class EngineIn, class LayoutIn,
119
+ class EngineOut, class LayoutOut,
120
+ class UnaryOp>
121
+ CUTE_HOST_DEVICE constexpr
122
+ void
123
+ transform(Tensor<EngineIn, LayoutIn > const& tensor_in,
124
+ Tensor<EngineOut,LayoutOut> && tensor_out,
125
+ UnaryOp&& op)
126
+ {
127
+ return transform(tensor_in, tensor_out, op);
128
+ }
129
+
130
+ // Similar to std::transform with a binary operation
131
+ // Takes two tensors as input and one tensor as output.
132
+ // Applies the binary_op to tensor_in1 and tensor_in2 and
133
+ // assigns it to tensor_out
134
+ template <class EngineIn1, class LayoutIn1,
135
+ class EngineIn2, class LayoutIn2,
136
+ class EngineOut, class LayoutOut,
137
+ class BinaryOp>
138
+ CUTE_HOST_DEVICE constexpr
139
+ void
140
+ transform(Tensor<EngineIn1,LayoutIn1> const& tensor_in1,
141
+ Tensor<EngineIn2,LayoutIn2> const& tensor_in2,
142
+ Tensor<EngineOut,LayoutOut> & tensor_out,
143
+ BinaryOp&& op)
144
+ {
145
+ CUTE_UNROLL
146
+ for (int i = 0; i < size(tensor_in1); ++i) {
147
+ tensor_out(i) = op(tensor_in1(i), tensor_in2(i));
148
+ }
149
+ }
150
+
151
+ // Accept mutable temporaries
152
+ template <class EngineIn1, class LayoutIn1,
153
+ class EngineIn2, class LayoutIn2,
154
+ class EngineOut, class LayoutOut,
155
+ class BinaryOp>
156
+ CUTE_HOST_DEVICE constexpr
157
+ void
158
+ transform(Tensor<EngineIn1,LayoutIn1> const& tensor_in1,
159
+ Tensor<EngineIn2,LayoutIn2> const& tensor_in2,
160
+ Tensor<EngineOut,LayoutOut> && tensor_out,
161
+ BinaryOp&& op)
162
+ {
163
+ return transform(tensor_in1, tensor_in2, tensor_out, op);
164
+ }
165
+
166
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/algorithm/tuple_algorithms.hpp ADDED
@@ -0,0 +1,1073 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp>
34
+
35
+ #include <cute/util/type_traits.hpp>
36
+ #include <cute/container/tuple.hpp>
37
+ #include <cute/algorithm/functional.hpp>
38
+ #include <cute/numeric/integer_sequence.hpp>
39
+ #include <cute/numeric/integral_constant.hpp>
40
+
41
+ /// @file tuple_algorithms.hpp
42
+ /// @brief Common algorithms on (hierarchical) tuples
43
+ ///
44
+ /// Code guidelines and style preferences:
45
+ ///
46
+ /// For perfect forwarding, don't use std::forward, because it may not
47
+ /// be defined in device code when compiling with NVRTC. Instead, use
48
+ /// `static_cast<ParameterType&&>(parameter_name)`.
49
+ ///
50
+ /// CuTe generally does not bother forwarding functions, as
51
+ /// reference-qualified member functions are rare in this code base.
52
+ ///
53
+ /// Throughout CUTLASS, cute::make_tuple always needs to be called
54
+ /// namespace-qualified, EVEN If inside the cute namespace and/or in
55
+ /// scope of a "using namespace cute" declaration. Otherwise, the
56
+ /// compiler may select std::make_tuple instead of cute::make_tuple,
57
+ /// due to argument-dependent lookup.
58
+
59
+ namespace cute
60
+ {
61
+
62
+ //
63
+ // Apply (Unpack)
64
+ // (t, f) => f(t_0,t_1,...,t_n)
65
+ //
66
+
67
+ namespace detail {
68
+
69
+ template <class T, class F, int... I>
70
+ CUTE_HOST_DEVICE constexpr
71
+ auto
72
+ apply(T&& t, F&& f, seq<I...>)
73
+ {
74
+ return f(get<I>(static_cast<T&&>(t))...);
75
+ }
76
+
77
+ } // end namespace detail
78
+
79
+ template <class T, class F>
80
+ CUTE_HOST_DEVICE constexpr
81
+ auto
82
+ apply(T&& t, F&& f)
83
+ {
84
+ return detail::apply(static_cast<T&&>(t), f, tuple_seq<T>{});
85
+ }
86
+
87
+ //
88
+ // Transform Apply
89
+ // (t, f, g) => g(f(t_0),f(t_1),...)
90
+ //
91
+
92
+ namespace detail {
93
+
94
+ template <class T, class F, class G, int... I>
95
+ CUTE_HOST_DEVICE constexpr
96
+ auto
97
+ tapply(T&& t, F&& f, G&& g, seq<I...>)
98
+ {
99
+ return g(f(get<I>(static_cast<T&&>(t)))...);
100
+ }
101
+
102
+ template <class T0, class T1, class F, class G, int... I>
103
+ CUTE_HOST_DEVICE constexpr
104
+ auto
105
+ tapply(T0&& t0, T1&& t1, F&& f, G&& g, seq<I...>)
106
+ {
107
+ return g(f(get<I>(static_cast<T0&&>(t0)),
108
+ get<I>(static_cast<T1&&>(t1)))...);
109
+ }
110
+
111
+ template <class T0, class T1, class T2, class F, class G, int... I>
112
+ CUTE_HOST_DEVICE constexpr
113
+ auto
114
+ tapply(T0&& t0, T1&& t1, T2&& t2, F&& f, G&& g, seq<I...>)
115
+ {
116
+ return g(f(get<I>(static_cast<T0&&>(t0)),
117
+ get<I>(static_cast<T1&&>(t1)),
118
+ get<I>(static_cast<T2&&>(t2)))...);
119
+ }
120
+
121
+ } // end namespace detail
122
+
123
+ template <class T, class F, class G>
124
+ CUTE_HOST_DEVICE constexpr
125
+ auto
126
+ transform_apply(T&& t, F&& f, G&& g)
127
+ {
128
+ if constexpr (is_tuple<remove_cvref_t<T>>::value) {
129
+ return detail::tapply(static_cast<T&&>(t), f, g, tuple_seq<T>{});
130
+ } else {
131
+ return g(f(static_cast<T&&>(t)));
132
+ }
133
+
134
+ CUTE_GCC_UNREACHABLE;
135
+ }
136
+
137
+ template <class T0, class T1, class F, class G>
138
+ CUTE_HOST_DEVICE constexpr
139
+ auto
140
+ transform_apply(T0&& t0, T1&& t1, F&& f, G&& g)
141
+ {
142
+ if constexpr (is_tuple<remove_cvref_t<T0>>::value) {
143
+ return detail::tapply(static_cast<T0&&>(t0), static_cast<T1&&>(t1), f, g, tuple_seq<T0>{});
144
+ } else {
145
+ return g(f(static_cast<T0&&>(t0), static_cast<T1&&>(t1)));
146
+ }
147
+
148
+ CUTE_GCC_UNREACHABLE;
149
+ }
150
+
151
+ template <class T0, class T1, class T2, class F, class G>
152
+ CUTE_HOST_DEVICE constexpr
153
+ auto
154
+ transform_apply(T0&& t0, T1&& t1, T2&& t2, F&& f, G&& g)
155
+ {
156
+ if constexpr (is_tuple<remove_cvref_t<T0>>::value) {
157
+ return detail::tapply(static_cast<T0&&>(t0), static_cast<T1&&>(t1), static_cast<T2&&>(t2), f, g, tuple_seq<T0>{});
158
+ } else {
159
+ return g(f(static_cast<T0&&>(t0), static_cast<T1&&>(t1), static_cast<T2&&>(t2)));
160
+ }
161
+
162
+ CUTE_GCC_UNREACHABLE;
163
+ }
164
+
165
+ //
166
+ // For Each
167
+ // (t, f) => f(t_0),f(t_1),...,f(t_n)
168
+ //
169
+
170
+ template <class T, class F>
171
+ CUTE_HOST_DEVICE constexpr
172
+ void
173
+ for_each(T&& t, F&& f)
174
+ {
175
+ if constexpr (is_tuple<remove_cvref_t<T>>::value) {
176
+ return detail::apply(t, [&](auto&&... a) { (f(static_cast<decltype(a)&&>(a)), ...); }, tuple_seq<T>{});
177
+ } else {
178
+ return f(static_cast<T&&>(t));
179
+ }
180
+
181
+ CUTE_GCC_UNREACHABLE;
182
+ }
183
+
184
+ template <class T, class F>
185
+ CUTE_HOST_DEVICE constexpr
186
+ auto
187
+ for_each_leaf(T&& t, F&& f)
188
+ {
189
+ if constexpr (is_tuple<remove_cvref_t<T>>::value) {
190
+ return detail::apply(static_cast<T&&>(t), [&](auto&&... a){ return (for_each_leaf(static_cast<decltype(a)&&>(a), f), ...); }, tuple_seq<T>{});
191
+ } else {
192
+ return f(static_cast<T&&>(t));
193
+ }
194
+
195
+ CUTE_GCC_UNREACHABLE;
196
+ }
197
+
198
+ //
199
+ // Transform
200
+ // (t, f) => (f(t_0),f(t_1),...,f(t_n))
201
+ //
202
+
203
+ template <class T, class F>
204
+ CUTE_HOST_DEVICE constexpr
205
+ auto
206
+ transform(T const& t, F&& f)
207
+ {
208
+ if constexpr (is_tuple<T>::value) {
209
+ return detail::tapply(t, f, [](auto const&... a){ return cute::make_tuple(a...); }, tuple_seq<T>{});
210
+ } else {
211
+ return f(t);
212
+ }
213
+
214
+ CUTE_GCC_UNREACHABLE;
215
+ }
216
+
217
+ template <class T0, class T1, class F>
218
+ CUTE_HOST_DEVICE constexpr
219
+ auto
220
+ transform(T0 const& t0, T1 const& t1, F&& f)
221
+ {
222
+ if constexpr (is_tuple<T0>::value) {
223
+ static_assert(tuple_size<T0>::value == tuple_size<T1>::value, "Mismatched tuple_size");
224
+ return detail::tapply(t0, t1, f, [](auto const&... a){ return cute::make_tuple(a...); }, tuple_seq<T0>{});
225
+ } else {
226
+ return f(t0, t1);
227
+ }
228
+
229
+ CUTE_GCC_UNREACHABLE;
230
+ }
231
+
232
+ template <class T0, class T1, class T2, class F>
233
+ CUTE_HOST_DEVICE constexpr
234
+ auto
235
+ transform(T0 const& t0, T1 const& t1, T2 const& t2, F&& f)
236
+ {
237
+ if constexpr (is_tuple<T0>::value) {
238
+ static_assert(tuple_size<T0>::value == tuple_size<T1>::value, "Mismatched tuple_size");
239
+ static_assert(tuple_size<T0>::value == tuple_size<T2>::value, "Mismatched tuple_size");
240
+ return detail::tapply(t0, t1, t2, f, [](auto const&... a){ return cute::make_tuple(a...); }, tuple_seq<T0>{});
241
+ } else {
242
+ return f(t0, t1, t2);
243
+ }
244
+
245
+ CUTE_GCC_UNREACHABLE;
246
+ }
247
+
248
+ template <class T, class F>
249
+ CUTE_HOST_DEVICE constexpr
250
+ auto
251
+ transform_leaf(T const& t, F&& f)
252
+ {
253
+ if constexpr (is_tuple<T>::value) {
254
+ return transform(t, [&](auto const& a) { return transform_leaf(a, f); });
255
+ } else {
256
+ return f(t);
257
+ }
258
+
259
+ CUTE_GCC_UNREACHABLE;
260
+ }
261
+
262
+ template <class T0, class T1, class F>
263
+ CUTE_HOST_DEVICE constexpr
264
+ auto
265
+ transform_leaf(T0 const& t0, T1 const& t1, F&& f)
266
+ {
267
+ if constexpr (is_tuple<T0>::value) {
268
+ return transform(t0, t1, [&](auto const& a, auto const& b) { return transform_leaf(a, b, f); });
269
+ } else {
270
+ return f(t0, t1);
271
+ }
272
+
273
+ CUTE_GCC_UNREACHABLE;
274
+ }
275
+
276
+ //
277
+ // find and find_if
278
+ //
279
+
280
+ namespace detail {
281
+
282
+ template <class T, class F, int I, int... Is>
283
+ CUTE_HOST_DEVICE constexpr
284
+ auto
285
+ find_if(T const& t, F&& f, seq<I,Is...>)
286
+ {
287
+ if constexpr (decltype(f(get<I>(t)))::value) {
288
+ return cute::C<I>{};
289
+ } else
290
+ if constexpr (sizeof...(Is) == 0) {
291
+ return cute::C<I+1>{};
292
+ } else {
293
+ return find_if(t, f, seq<Is...>{});
294
+ }
295
+
296
+ CUTE_GCC_UNREACHABLE;
297
+ }
298
+
299
+ } // end namespace detail
300
+
301
+ template <class T, class F>
302
+ CUTE_HOST_DEVICE constexpr
303
+ auto
304
+ find_if(T const& t, F&& f)
305
+ {
306
+ if constexpr (is_tuple<T>::value) {
307
+ return detail::find_if(t, f, tuple_seq<T>{});
308
+ } else {
309
+ return cute::C<decltype(f(t))::value ? 0 : 1>{};
310
+ }
311
+
312
+ CUTE_GCC_UNREACHABLE;
313
+ }
314
+
315
+ template <class T, class X>
316
+ CUTE_HOST_DEVICE constexpr
317
+ auto
318
+ find(T const& t, X const& x)
319
+ {
320
+ return find_if(t, [&](auto const& v) { return v == x; }); // This should always return a static true/false
321
+ }
322
+
323
+ template <class T, class F>
324
+ CUTE_HOST_DEVICE constexpr
325
+ auto
326
+ any_of(T const& t, F&& f)
327
+ {
328
+ if constexpr (is_tuple<T>::value) {
329
+ return detail::apply(cute::transform(t, f), [&] (auto const&... a) { return (false_type{} || ... || a); }, tuple_seq<T>{});
330
+ } else {
331
+ return f(t);
332
+ }
333
+
334
+ CUTE_GCC_UNREACHABLE;
335
+ }
336
+
337
+ template <class T, class F>
338
+ CUTE_HOST_DEVICE constexpr
339
+ auto
340
+ all_of(T const& t, F&& f)
341
+ {
342
+ if constexpr (is_tuple<T>::value) {
343
+ return detail::apply(cute::transform(t, f), [&] (auto const&... a) { return (true_type{} && ... && a); }, tuple_seq<T>{});
344
+ } else {
345
+ return f(t);
346
+ }
347
+
348
+ CUTE_GCC_UNREACHABLE;
349
+ }
350
+
351
+ template <class T, class F>
352
+ CUTE_HOST_DEVICE constexpr
353
+ auto
354
+ none_of(T const& t, F&& f)
355
+ {
356
+ return not any_of(t, f);
357
+ }
358
+
359
+ //
360
+ // Filter
361
+ // (t, f) => <f(t_0),f(t_1),...,f(t_n)>
362
+ //
363
+
364
+ template <class T, class F>
365
+ CUTE_HOST_DEVICE constexpr
366
+ auto
367
+ filter_tuple(T const& t, F&& f)
368
+ {
369
+ return transform_apply(t, f, [](auto const&... a) { return cute::tuple_cat(a...); });
370
+ }
371
+
372
+ template <class T0, class T1, class F>
373
+ CUTE_HOST_DEVICE constexpr
374
+ auto
375
+ filter_tuple(T0 const& t0, T1 const& t1, F&& f)
376
+ {
377
+ return transform_apply(t0, t1, f, [](auto const&... a) { return cute::tuple_cat(a...); });
378
+ }
379
+
380
+ template <class T0, class T1, class T2, class F>
381
+ CUTE_HOST_DEVICE constexpr
382
+ auto
383
+ filter_tuple(T0 const& t0, T1 const& t1, T2 const& t2, F&& f)
384
+ {
385
+ return transform_apply(t0, t1, t2, f, [](auto const&... a) { return cute::tuple_cat(a...); });
386
+ }
387
+
388
+ //
389
+ // Fold (Reduce, Accumulate)
390
+ // (t, v, f) => f(...f(f(v,t_0),t_1),...,t_n)
391
+ //
392
+
393
+ namespace detail {
394
+
395
+ template <class Fn, class Val>
396
+ struct FoldAdaptor {
397
+ template <class X>
398
+ CUTE_HOST_DEVICE constexpr auto operator|(X&& x) {
399
+ auto r = fn_(val_, static_cast<X&&>(x));
400
+ return FoldAdaptor<Fn, decltype(r)>{fn_, r};
401
+ }
402
+ Fn fn_;
403
+ Val val_;
404
+ };
405
+
406
+ template <class T, class V, class F, int... Is>
407
+ CUTE_HOST_DEVICE constexpr
408
+ auto
409
+ fold(T&& t, V const& v, F&& f, seq<Is...>)
410
+ {
411
+ return (FoldAdaptor<F,V>{f,v} | ... | get<Is>(static_cast<T&&>(t))).val_;
412
+ }
413
+
414
+ } // end namespace detail
415
+
416
+ template <class T, class V, class F>
417
+ CUTE_HOST_DEVICE constexpr
418
+ auto
419
+ fold(T&& t, V const& v, F&& f)
420
+ {
421
+ if constexpr (is_tuple<remove_cvref_t<T>>::value) {
422
+ return detail::fold(static_cast<T&&>(t), v, f, tuple_seq<T>{});
423
+ } else {
424
+ return f(v, static_cast<T&&>(t));
425
+ }
426
+
427
+ CUTE_GCC_UNREACHABLE;
428
+ }
429
+
430
+ template <class T, class F>
431
+ CUTE_HOST_DEVICE constexpr
432
+ auto
433
+ fold_first(T&& t, F&& f)
434
+ {
435
+ if constexpr (is_tuple<remove_cvref_t<T>>::value) {
436
+ return detail::fold(static_cast<T&&>(t), get<0>(t), f, make_range<1,tuple_size<remove_cvref_t<T>>::value>{});
437
+ } else {
438
+ return t;
439
+ }
440
+
441
+ CUTE_GCC_UNREACHABLE;
442
+ }
443
+
444
+ //
445
+ // front, back, take, select, unwrap
446
+ //
447
+
448
+ // Get the first non-tuple element in a hierarchical tuple
449
+ template <class T>
450
+ CUTE_HOST_DEVICE constexpr
451
+ decltype(auto)
452
+ front(T&& t)
453
+ {
454
+ if constexpr (is_tuple<remove_cvref_t<T>>::value) {
455
+ return front(get<0>(static_cast<T&&>(t)));
456
+ } else {
457
+ return static_cast<T&&>(t);
458
+ }
459
+
460
+ CUTE_GCC_UNREACHABLE;
461
+ }
462
+
463
+ // Get the last non-tuple element in a hierarchical tuple
464
+ template <class T>
465
+ CUTE_HOST_DEVICE constexpr
466
+ decltype(auto)
467
+ back(T&& t)
468
+ {
469
+ if constexpr (is_tuple<remove_cvref_t<T>>::value) {
470
+ constexpr int N = tuple_size<remove_cvref_t<T>>::value;
471
+
472
+ // MSVC needs a bit of extra help here deducing return types.
473
+ // We help it by peeling off the nonrecursive case a level "early."
474
+ if constexpr (! is_tuple<remove_cvref_t<decltype(get<N - 1>(static_cast<T&&>(t)))>>::value) {
475
+ return get<N - 1>(static_cast<T&&>(t));
476
+ } else {
477
+ return back(get<N - 1>(static_cast<T&&>(t)));
478
+ }
479
+ } else {
480
+ return static_cast<T&&>(t);
481
+ }
482
+
483
+ CUTE_GCC_UNREACHABLE;
484
+ }
485
+
486
+ // Takes the elements in the range [B,E)
487
+ template <int B, int E, class T>
488
+ CUTE_HOST_DEVICE constexpr
489
+ auto
490
+ take(T const& t)
491
+ {
492
+ if constexpr (E == -1) {
493
+ if constexpr (is_tuple<T>::value) {
494
+ return take<B,tuple_size<T>::value>(t);
495
+ } else {
496
+ return take<B,1>(t);
497
+ }
498
+ } else
499
+ if constexpr (B <= E) {
500
+ return detail::apply(t, [](auto const&... a) { return cute::make_tuple(a...); }, make_range<B,E>{});
501
+ } else {
502
+ static_assert(B <= E);
503
+ }
504
+
505
+ CUTE_GCC_UNREACHABLE;
506
+ }
507
+
508
+ // Select tuple elements with given indices.
509
+ template <int... I, class T>
510
+ CUTE_HOST_DEVICE constexpr
511
+ auto
512
+ select(T const& t)
513
+ {
514
+ return cute::make_tuple(get<I>(t)...);
515
+ }
516
+
517
+ // Wrap non-tuples into rank-1 tuples or forward
518
+ template <class T>
519
+ CUTE_HOST_DEVICE constexpr
520
+ auto
521
+ wrap(T const& t)
522
+ {
523
+ if constexpr (is_tuple<T>::value) {
524
+ return t;
525
+ } else {
526
+ return cute::make_tuple(t);
527
+ }
528
+
529
+ CUTE_GCC_UNREACHABLE;
530
+ }
531
+
532
+ // Unwrap rank-1 tuples until we're left with a rank>1 tuple or a non-tuple
533
+ template <class T>
534
+ CUTE_HOST_DEVICE constexpr
535
+ auto
536
+ unwrap(T const& t)
537
+ {
538
+ if constexpr (is_tuple<T>::value) {
539
+ if constexpr (tuple_size<T>::value == 1) {
540
+ return unwrap(get<0>(t));
541
+ } else {
542
+ return t;
543
+ }
544
+ } else {
545
+ return t;
546
+ }
547
+
548
+ CUTE_GCC_UNREACHABLE;
549
+ }
550
+
551
+ //
552
+ // Flatten and Unflatten
553
+ //
554
+
555
+ template <class T>
556
+ struct is_flat : true_type {};
557
+
558
+ template <class... Ts>
559
+ struct is_flat<tuple<Ts...>> : bool_constant<(true && ... && (not is_tuple<Ts>::value))> {};
560
+
561
+ // Flatten a hierarchical tuple to a tuple of depth one
562
+ // and wrap non-tuples into a rank-1 tuple.
563
+ template <class T>
564
+ CUTE_HOST_DEVICE constexpr
565
+ auto
566
+ flatten_to_tuple(T const& t)
567
+ {
568
+ if constexpr (is_tuple<T>::value) {
569
+ if constexpr (is_flat<T>::value) { // Shortcut for perf
570
+ return t;
571
+ } else {
572
+ return filter_tuple(t, [](auto const& a) { return flatten_to_tuple(a); });
573
+ }
574
+ } else {
575
+ return cute::make_tuple(t);
576
+ }
577
+
578
+ CUTE_GCC_UNREACHABLE;
579
+ }
580
+
581
+ // Flatten a hierarchical tuple to a tuple of depth one
582
+ // and leave non-tuple untouched.
583
+ template <class T>
584
+ CUTE_HOST_DEVICE constexpr
585
+ auto
586
+ flatten(T const& t)
587
+ {
588
+ if constexpr (is_tuple<T>::value) {
589
+ if constexpr (is_flat<T>::value) { // Shortcut for perf
590
+ return t;
591
+ } else {
592
+ return filter_tuple(t, [](auto const& a) { return flatten_to_tuple(a); });
593
+ }
594
+ } else {
595
+ return t;
596
+ }
597
+
598
+ CUTE_GCC_UNREACHABLE;
599
+ }
600
+
601
+ namespace detail {
602
+
603
+ template <class FlatTuple, class TargetProfile>
604
+ CUTE_HOST_DEVICE constexpr
605
+ auto
606
+ unflatten_impl(FlatTuple const& flat_tuple, TargetProfile const& target_profile)
607
+ {
608
+ if constexpr (is_tuple<TargetProfile>::value) {
609
+ return fold(target_profile, cute::make_tuple(cute::make_tuple(), flat_tuple), [](auto const& v, auto const& t) {
610
+ auto [result, remaining_tuple] = v;
611
+ auto [sub_result, sub_tuple] = unflatten_impl(remaining_tuple, t);
612
+ return cute::make_tuple(append(result, sub_result), sub_tuple);
613
+ });
614
+ } else {
615
+ return cute::make_tuple(get<0>(flat_tuple), take<1, decltype(rank(flat_tuple))::value>(flat_tuple));
616
+ }
617
+
618
+ CUTE_GCC_UNREACHABLE;
619
+ }
620
+
621
+ } // end namespace detail
622
+
623
+ // Unflatten a flat tuple into a hierarchical tuple
624
+ // @pre flatten(@a flat_tuple) == @a flat_tuple
625
+ // @pre rank(flatten(@a target_profile)) == rank(@a flat_tuple)
626
+ // @post congruent(@a result, @a target_profile)
627
+ // @post flatten(@a result) == @a flat_tuple
628
+ template <class FlatTuple, class TargetProfile>
629
+ CUTE_HOST_DEVICE constexpr
630
+ auto
631
+ unflatten(FlatTuple const& flat_tuple, TargetProfile const& target_profile)
632
+ {
633
+ auto [unflatten_tuple, flat_remainder] = detail::unflatten_impl(flat_tuple, target_profile);
634
+ CUTE_STATIC_ASSERT_V(rank(flat_remainder) == Int<0>{});
635
+ return unflatten_tuple;
636
+ }
637
+
638
+ //
639
+ // insert and remove and replace
640
+ //
641
+
642
+ namespace detail {
643
+
644
+ // Shortcut around cute::tuple_cat for common insert/remove/repeat cases
645
+ template <class T, class X, int... I, int... J, int... K>
646
+ CUTE_HOST_DEVICE constexpr
647
+ auto
648
+ construct(T const& t, X const& x, seq<I...>, seq<J...>, seq<K...>)
649
+ {
650
+ return cute::make_tuple(get<I>(t)..., (void(J),x)..., get<K>(t)...);
651
+ }
652
+
653
+ } // end namespace detail
654
+
655
+ // Insert x into the Nth position of the tuple
656
+ template <int N, class T, class X>
657
+ CUTE_HOST_DEVICE constexpr
658
+ auto
659
+ insert(T const& t, X const& x)
660
+ {
661
+ return detail::construct(t, x, make_seq<N>{}, seq<0>{}, make_range<N,tuple_size<T>::value>{});
662
+ }
663
+
664
+ // Remove the Nth element of the tuple
665
+ template <int N, class T>
666
+ CUTE_HOST_DEVICE constexpr
667
+ auto
668
+ remove(T const& t)
669
+ {
670
+ return detail::construct(t, 0, make_seq<N>{}, seq<>{}, make_range<N+1,tuple_size<T>::value>{});
671
+ }
672
+
673
+ // Replace the Nth element of the tuple with x
674
+ template <int N, class T, class X>
675
+ CUTE_HOST_DEVICE constexpr
676
+ auto
677
+ replace(T const& t, X const& x)
678
+ {
679
+ if constexpr (is_tuple<T>::value) {
680
+ return detail::construct(t, x, make_seq<N>{}, seq<0>{}, make_range<N+1,tuple_size<T>::value>{});
681
+ } else {
682
+ static_assert(N == 0);
683
+ return x;
684
+ }
685
+
686
+ CUTE_GCC_UNREACHABLE;
687
+ }
688
+
689
+ // Replace the first element of the tuple with x
690
+ template <class T, class X>
691
+ CUTE_HOST_DEVICE constexpr
692
+ auto
693
+ replace_front(T const& t, X const& x)
694
+ {
695
+ if constexpr (is_tuple<T>::value) {
696
+ return detail::construct(t, x, seq<>{}, seq<0>{}, make_range<1,tuple_size<T>::value>{});
697
+ } else {
698
+ return x;
699
+ }
700
+
701
+ CUTE_GCC_UNREACHABLE;
702
+ }
703
+
704
+ // Replace the last element of the tuple with x
705
+ template <class T, class X>
706
+ CUTE_HOST_DEVICE constexpr
707
+ auto
708
+ replace_back(T const& t, X const& x)
709
+ {
710
+ if constexpr (is_tuple<T>::value) {
711
+ return detail::construct(t, x, make_seq<tuple_size<T>::value-1>{}, seq<0>{}, seq<>{});
712
+ } else {
713
+ return x;
714
+ }
715
+
716
+ CUTE_GCC_UNREACHABLE;
717
+ }
718
+
719
+ //
720
+ // Make a tuple of Xs of tuple_size N
721
+ //
722
+
723
+ template <int N, class X>
724
+ CUTE_HOST_DEVICE constexpr
725
+ auto
726
+ tuple_repeat(X const& x)
727
+ {
728
+ return detail::construct(0, x, seq<>{}, make_seq<N>{}, seq<>{});
729
+ }
730
+
731
+ //
732
+ // Make repeated Xs of rank N
733
+ //
734
+
735
+ template <int N, class X>
736
+ CUTE_HOST_DEVICE constexpr
737
+ auto
738
+ repeat(X const& x)
739
+ {
740
+ if constexpr (N == 1) {
741
+ return x;
742
+ } else {
743
+ return detail::construct(0, x, seq<>{}, make_seq<N>{}, seq<>{});
744
+ }
745
+
746
+ CUTE_GCC_UNREACHABLE;
747
+ }
748
+
749
+ //
750
+ // Make a tuple of Xs the same profile as tuple T
751
+ //
752
+
753
+ template <class T, class X>
754
+ CUTE_HOST_DEVICE constexpr
755
+ auto
756
+ repeat_like(T const& t, X const& x)
757
+ {
758
+ if constexpr (is_tuple<T>::value) {
759
+ return transform(t, [&](auto const& a) { return repeat_like(a,x); });
760
+ } else {
761
+ return x;
762
+ }
763
+
764
+ CUTE_GCC_UNREACHABLE;
765
+ }
766
+
767
+ // Group the elements [B,E) of a T into a single element
768
+ // e.g. group<2,4>(T<_1,_2,_3,_4,_5,_6>{})
769
+ // => T<_1,_2,T<_3,_4>,_5,_6>{}
770
+ template <int B, int E, class T>
771
+ CUTE_HOST_DEVICE constexpr
772
+ auto
773
+ group(T const& t)
774
+ {
775
+ if constexpr (not is_tuple<T>::value) {
776
+ if constexpr (E == -1) {
777
+ return group<B,1>(t);
778
+ } else {
779
+ return detail::construct(t, take<B,E>(t), make_seq<B>{}, make_seq<(B < E)>{}, make_range<E,1>{});
780
+ }
781
+ } else
782
+ if constexpr (E == -1) {
783
+ return group<B,tuple_size<T>::value>(t);
784
+ } else
785
+ if constexpr (B <= E) {
786
+ return detail::construct(t, take<B,E>(t), make_seq<B>{}, make_seq<(B < E)>{}, make_range<E,tuple_size<T>::value>{});
787
+ } else {
788
+ static_assert(B <= E);
789
+ }
790
+
791
+ CUTE_GCC_UNREACHABLE;
792
+ }
793
+
794
+ //
795
+ // Extend a T to rank N by appending/prepending an element
796
+ //
797
+
798
+ template <int N, class T, class X>
799
+ CUTE_HOST_DEVICE constexpr
800
+ auto
801
+ append(T const& a, X const& x)
802
+ {
803
+ if constexpr (is_tuple<T>::value) {
804
+ if constexpr (N == tuple_size<T>::value) {
805
+ return a;
806
+ } else {
807
+ static_assert(N > tuple_size<T>::value);
808
+ return detail::construct(a, x, make_seq<tuple_size<T>::value>{}, make_seq<N-tuple_size<T>::value>{}, seq<>{});
809
+ }
810
+ } else {
811
+ if constexpr (N == 1) {
812
+ return a;
813
+ } else {
814
+ return detail::construct(cute::make_tuple(a), x, seq<0>{}, make_seq<N-1>{}, seq<>{});
815
+ }
816
+ }
817
+
818
+ CUTE_GCC_UNREACHABLE;
819
+ }
820
+
821
+ template <class T, class X>
822
+ CUTE_HOST_DEVICE constexpr
823
+ auto
824
+ append(T const& a, X const& x)
825
+ {
826
+ if constexpr (is_tuple<T>::value) {
827
+ return detail::construct(a, x, make_seq<tuple_size<T>::value>{}, seq<0>{}, seq<>{});
828
+ } else {
829
+ return cute::make_tuple(a, x);
830
+ }
831
+
832
+ CUTE_GCC_UNREACHABLE;
833
+ }
834
+
835
+ template <int N, class T, class X>
836
+ CUTE_HOST_DEVICE constexpr
837
+ auto
838
+ prepend(T const& a, X const& x)
839
+ {
840
+ if constexpr (is_tuple<T>::value) {
841
+ if constexpr (N == tuple_size<T>::value) {
842
+ return a;
843
+ } else {
844
+ static_assert(N > tuple_size<T>::value);
845
+ return detail::construct(a, x, seq<>{}, make_seq<N-tuple_size<T>::value>{}, make_seq<tuple_size<T>::value>{});
846
+ }
847
+ } else {
848
+ if constexpr (N == 1) {
849
+ return a;
850
+ } else {
851
+ static_assert(N > 1);
852
+ return detail::construct(cute::make_tuple(a), x, seq<>{}, make_seq<N-1>{}, seq<0>{});
853
+ }
854
+ }
855
+
856
+ CUTE_GCC_UNREACHABLE;
857
+ }
858
+
859
+ template <class T, class X>
860
+ CUTE_HOST_DEVICE constexpr
861
+ auto
862
+ prepend(T const& a, X const& x)
863
+ {
864
+ if constexpr (is_tuple<T>::value) {
865
+ return detail::construct(a, x, seq<>{}, seq<0>{}, make_seq<tuple_size<T>::value>{});
866
+ } else {
867
+ return cute::make_tuple(x, a);
868
+ }
869
+
870
+ CUTE_GCC_UNREACHABLE;
871
+ }
872
+
873
+ //
874
+ // Inclusive scan (prefix sum)
875
+ //
876
+
877
+ namespace detail {
878
+
879
+ template <class T, class V, class F, int I, int... Is>
880
+ CUTE_HOST_DEVICE constexpr
881
+ auto
882
+ iscan(T const& t, V const& v, F&& f, seq<I,Is...>)
883
+ {
884
+ // Apply the function to v and the element at I
885
+ auto v_next = f(v, get<I>(t));
886
+ // Replace I with v_next
887
+ auto t_next = replace<I>(t, v_next);
888
+
889
+ #if 0
890
+ std::cout << "ISCAN i" << I << std::endl;
891
+ std::cout << " t " << t << std::endl;
892
+ std::cout << " i " << v << std::endl;
893
+ std::cout << " f(i,t) " << v_next << std::endl;
894
+ std::cout << " t_n " << t_next << std::endl;
895
+ #endif
896
+
897
+ if constexpr (sizeof...(Is) == 0) {
898
+ return t_next;
899
+ } else {
900
+ return iscan(t_next, v_next, f, seq<Is...>{});
901
+ }
902
+
903
+ CUTE_GCC_UNREACHABLE;
904
+ }
905
+
906
+ } // end namespace detail
907
+
908
+ template <class T, class V, class F>
909
+ CUTE_HOST_DEVICE constexpr
910
+ auto
911
+ iscan(T const& t, V const& v, F&& f)
912
+ {
913
+ return detail::iscan(t, v, f, tuple_seq<T>{});
914
+ }
915
+
916
+ //
917
+ // Exclusive scan (prefix sum)
918
+ //
919
+
920
+ namespace detail {
921
+
922
+ template <class T, class V, class F, int I, int... Is>
923
+ CUTE_HOST_DEVICE constexpr
924
+ auto
925
+ escan(T const& t, V const& v, F&& f, seq<I,Is...>)
926
+ {
927
+ if constexpr (sizeof...(Is) == 0) {
928
+ // Replace I with v
929
+ return replace<I>(t, v);
930
+ } else {
931
+ // Apply the function to v and the element at I
932
+ auto v_next = f(v, get<I>(t));
933
+ // Replace I with v
934
+ auto t_next = replace<I>(t, v);
935
+
936
+ #if 0
937
+ std::cout << "ESCAN i" << I << std::endl;
938
+ std::cout << " t " << t << std::endl;
939
+ std::cout << " i " << v << std::endl;
940
+ std::cout << " f(i,t) " << v_next << std::endl;
941
+ std::cout << " t_n " << t_next << std::endl;
942
+ #endif
943
+
944
+ // Recurse
945
+ return escan(t_next, v_next, f, seq<Is...>{});
946
+ }
947
+
948
+ CUTE_GCC_UNREACHABLE;
949
+ }
950
+
951
+ } // end namespace detail
952
+
953
+ template <class T, class V, class F>
954
+ CUTE_HOST_DEVICE constexpr
955
+ auto
956
+ escan(T const& t, V const& v, F&& f)
957
+ {
958
+ return detail::escan(t, v, f, tuple_seq<T>{});
959
+ }
960
+
961
+ //
962
+ // Zip (Transpose)
963
+ //
964
+
965
+ // Take ((a,b,c,...),(x,y,z,...),...) rank-R0 x rank-R1 input
966
+ // to produce ((a,x,...),(b,y,...),(c,z,...),...) rank-R1 x rank-R0 output
967
+
968
+ namespace detail {
969
+
970
+ template <int J, class... Ts>
971
+ CUTE_HOST_DEVICE constexpr
972
+ auto
973
+ zip_(Ts const&... ts)
974
+ {
975
+ return cute::make_tuple(get<J>(ts)...);
976
+ }
977
+
978
+ template <class T, int... Is, int... Js>
979
+ CUTE_HOST_DEVICE constexpr
980
+ auto
981
+ zip(T const& t, seq<Is...>, seq<Js...>)
982
+ {
983
+ static_assert(conjunction<bool_constant<tuple_size<tuple_element_t<0,T>>::value == tuple_size<tuple_element_t<Is,T>>::value>...>::value, "Mismatched Ranks");
984
+ return cute::make_tuple(zip_<Js>(get<Is>(t)...)...);
985
+ }
986
+
987
+ } // end namespace detail
988
+
989
+ template <class T>
990
+ CUTE_HOST_DEVICE constexpr
991
+ auto
992
+ zip(T const& t)
993
+ {
994
+ if constexpr (is_tuple<T>::value) {
995
+ if constexpr (is_tuple<tuple_element_t<0,T>>::value) {
996
+ return detail::zip(t, tuple_seq<T>{}, tuple_seq<tuple_element_t<0,T>>{});
997
+ } else {
998
+ return cute::make_tuple(t);
999
+ }
1000
+ } else {
1001
+ return t;
1002
+ }
1003
+
1004
+ CUTE_GCC_UNREACHABLE;
1005
+ }
1006
+
1007
+ // Convenient to pass them in separately
1008
+ template <class T0, class T1, class... Ts>
1009
+ CUTE_HOST_DEVICE constexpr
1010
+ auto
1011
+ zip(T0 const& t0, T1 const& t1, Ts const&... ts)
1012
+ {
1013
+ return zip(cute::make_tuple(t0, t1, ts...));
1014
+ }
1015
+
1016
+ //
1017
+ // zip2_by -- A guided zip for rank-2 tuples
1018
+ // Take a tuple like ((A,a),((B,b),(C,c)),d)
1019
+ // and produce a tuple ((A,(B,C)),(a,(b,c),d))
1020
+ // where the rank-2 modes are selected by the terminals of the guide (X,(X,X))
1021
+ //
1022
+
1023
+ namespace detail {
1024
+
1025
+ template <class T, class TG, int... Is, int... Js>
1026
+ CUTE_HOST_DEVICE constexpr
1027
+ auto
1028
+ zip2_by(T const& t, TG const& guide, seq<Is...>, seq<Js...>)
1029
+ {
1030
+ // zip2_by produces the modes like ((A,a),(B,b),...)
1031
+ auto split = cute::make_tuple(zip2_by(get<Is>(t), get<Is>(guide))...);
1032
+
1033
+ // Rearrange and append missing modes from t to make ((A,B,...),(a,b,...,x,y))
1034
+ return cute::make_tuple(cute::make_tuple(get<0>(get<Is>(split))...),
1035
+ cute::make_tuple(get<1>(get<Is>(split))..., get<Js>(t)...));
1036
+ }
1037
+
1038
+ } // end namespace detail
1039
+
1040
+ template <class T, class TG>
1041
+ CUTE_HOST_DEVICE constexpr
1042
+ auto
1043
+ zip2_by(T const& t, TG const& guide)
1044
+ {
1045
+ if constexpr (is_tuple<TG>::value) {
1046
+ constexpr int TR = tuple_size<T>::value;
1047
+ constexpr int GR = tuple_size<TG>::value;
1048
+ static_assert(TR >= GR, "Mismatched ranks");
1049
+ return detail::zip2_by(t, guide,
1050
+ make_range< 0, GR>{},
1051
+ make_range<GR, TR>{});
1052
+ } else {
1053
+ static_assert(tuple_size<T>::value == 2, "Mismatched ranks");
1054
+ return t;
1055
+ }
1056
+
1057
+ CUTE_GCC_UNREACHABLE;
1058
+ }
1059
+
1060
+ /// @return A tuple of the elements of @c t in reverse order.
1061
+ template <class T>
1062
+ CUTE_HOST_DEVICE constexpr
1063
+ auto
1064
+ reverse(T const& t)
1065
+ {
1066
+ if constexpr (is_tuple<T>::value) {
1067
+ return detail::apply(t, [](auto const&... a){ return cute::make_tuple(a...); }, tuple_rseq<T>{});
1068
+ } else {
1069
+ return t;
1070
+ }
1071
+ }
1072
+
1073
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/cluster_sm100.hpp ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+
32
+ //
33
+
34
+ //
35
+
36
+ #pragma once
37
+
38
+ #include <cute/config.hpp>
39
+
40
+
41
+ namespace cute {
42
+
43
+
44
+ //
45
+ // Cluster launch utility
46
+ //
47
+ CUTE_HOST
48
+ bool
49
+ initialize_preferred_cluster_launch(void const* const kernel_function,
50
+ dim3 const& grid_dims,
51
+ dim3 const& cluster_dims_preferred,
52
+ dim3 const& cluster_dims_fallback)
53
+ {
54
+ //
55
+ // Validate cluster_dims
56
+ //
57
+
58
+ // Total number of cluster cannot be greater than 32 (hardware requirement)
59
+ if (cluster_dims_preferred.x * cluster_dims_preferred.y * cluster_dims_preferred.z <= 0 ||
60
+ cluster_dims_preferred.x * cluster_dims_preferred.y * cluster_dims_preferred.z > 32) {
61
+ std::cout << "Invalid preferred cluster dimensions: Attempting to init preferred cluster (" << cluster_dims_preferred.x << "," << cluster_dims_preferred.y << "," << cluster_dims_preferred.z
62
+ << ") [" << (cluster_dims_preferred.x * cluster_dims_preferred.y * cluster_dims_preferred.z) << "] which must be within (0,32]." << std::endl;
63
+ return false;
64
+ }
65
+
66
+ // Total number of cluster cannot be greater than 32 (hardware requirement)
67
+ if (cluster_dims_fallback.x * cluster_dims_fallback.y * cluster_dims_fallback.z <= 0 ||
68
+ cluster_dims_fallback.x * cluster_dims_fallback.y * cluster_dims_fallback.z > 32) {
69
+ std::cout << "Invalid cluster dimensions: Attempting to init fallback cluster (" << cluster_dims_fallback.x << "," << cluster_dims_fallback.y << "," << cluster_dims_fallback.z
70
+ << ") [" << (cluster_dims_fallback.x * cluster_dims_fallback.y * cluster_dims_fallback.z) << "] which must be within (0,32]." << std::endl;
71
+ return false;
72
+ }
73
+
74
+ // Total grid dimensions must be within (2^32, 2^16, 2^16)
75
+ if (grid_dims.y > (1 << 16) || grid_dims.z > (1 << 16)) {
76
+ std::cout << "Invalid grid dimensions: Attempting to init grid dimensions (" << grid_dims.x << "," << grid_dims.y << "," << grid_dims.z
77
+ << ") which must be within (2^32, 2^16, 2^16)." << std::endl;
78
+ return false;
79
+ }
80
+
81
+ // grid_dims should be divisible by cluster_dims_preferred
82
+ if (grid_dims.x % cluster_dims_preferred.x != 0 ||
83
+ grid_dims.y % cluster_dims_preferred.y != 0 ||
84
+ grid_dims.z % cluster_dims_preferred.z != 0) {
85
+ std::cout << "Invalid grid dimensions: Preferred cluster (" << cluster_dims_preferred.x << "," << cluster_dims_preferred.y << "," << cluster_dims_preferred.z
86
+ << ") does not divide Grid (" << grid_dims.x << "," << grid_dims.y << "," << grid_dims.z << ")." << std::endl;
87
+ return false;
88
+ }
89
+
90
+ // cluster_dims_preferred should be divisible by cluster_dims_fallback
91
+ if (cluster_dims_preferred.x % cluster_dims_fallback.x != 0 ||
92
+ cluster_dims_preferred.y % cluster_dims_fallback.y != 0 ||
93
+ cluster_dims_preferred.z % cluster_dims_fallback.z != 0) {
94
+ std::cout << "Invalid cluster dimensions: Fallback cluster (" << cluster_dims_fallback.x << "," << cluster_dims_fallback.y << "," << cluster_dims_fallback.z
95
+ << ") does not divide Preferred cluster (" << cluster_dims_preferred.x << "," << cluster_dims_preferred.y << "," << cluster_dims_preferred.z << ")." << std::endl;
96
+ return false;
97
+ }
98
+
99
+ // Both cluster dimenions should have the same depth
100
+ if (cluster_dims_preferred.z != cluster_dims_fallback.z) {
101
+ std::cout << "Invalid cluster dimensions: Fallback cluster (" << cluster_dims_fallback.x << "," << cluster_dims_fallback.y << "," << cluster_dims_fallback.z
102
+ << ") and Preferred cluster (" << cluster_dims_preferred.x << "," << cluster_dims_preferred.y << "," << cluster_dims_preferred.z << ") does not have the same depth." << std::endl;
103
+ return false;
104
+ }
105
+
106
+ return true;
107
+ }
108
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/cluster_sm90.hpp ADDED
@@ -0,0 +1,245 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp>
34
+
35
+ // Config
36
+ #if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 900) && \
37
+ ((__CUDACC_VER_MAJOR__ >= 12) || ((__CUDACC_VER_MAJOR__ == 11) && (__CUDACC_VER_MINOR__ >= 8))))
38
+ # define CUTE_ARCH_CLUSTER_SM90_ENABLED
39
+ #endif
40
+
41
+ #if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 900) && (__CUDACC_VER_MAJOR__ >= 12))
42
+ # define CUTE_ARCH_ELECT_ONE_SM90_ENABLED
43
+ #endif
44
+
45
+ namespace cute {
46
+
47
+ CUTE_DEVICE void cluster_arrive_relaxed()
48
+ {
49
+ #if defined(CUTE_ARCH_CLUSTER_SM90_ENABLED)
50
+ asm volatile("barrier.cluster.arrive.relaxed.aligned;\n" : : );
51
+ #else
52
+ CUTE_INVALID_CONTROL_PATH("CUTE_ARCH_CLUSTER_SM90_ENABLED is not defined");
53
+ #endif
54
+ }
55
+
56
+ CUTE_DEVICE void cluster_arrive()
57
+ {
58
+ #if defined(CUTE_ARCH_CLUSTER_SM90_ENABLED)
59
+ asm volatile("barrier.cluster.arrive.aligned;\n" : : );
60
+ #else
61
+ CUTE_INVALID_CONTROL_PATH("CUTE_ARCH_CLUSTER_SM90_ENABLED is not defined");
62
+ #endif
63
+ }
64
+
65
+ CUTE_DEVICE void cluster_wait()
66
+ {
67
+ #if defined(CUTE_ARCH_CLUSTER_SM90_ENABLED)
68
+ asm volatile("barrier.cluster.wait.aligned;\n" : : );
69
+ #else
70
+ CUTE_INVALID_CONTROL_PATH("CUTE_ARCH_CLUSTER_SM90_ENABLED is not defined");
71
+ #endif
72
+ }
73
+
74
+ CUTE_DEVICE void cluster_sync()
75
+ {
76
+ #if defined(CUTE_ARCH_CLUSTER_SM90_ENABLED)
77
+ cluster_arrive();
78
+ cluster_wait();
79
+ #else
80
+ CUTE_INVALID_CONTROL_PATH("CUTE_ARCH_CLUSTER_SM90_ENABLED is not defined");
81
+ #endif
82
+ }
83
+
84
+ // Returns the dim3 grid size in terms of number of clusters.
85
+ CUTE_DEVICE dim3 cluster_grid_dims()
86
+ {
87
+ #if defined(CUTE_ARCH_CLUSTER_SM90_ENABLED)
88
+ uint32_t x, y, z;
89
+ asm volatile("mov.u32 %0, %%nclusterid.x;\n" : "=r"(x) : );
90
+ asm volatile("mov.u32 %0, %%nclusterid.y;\n" : "=r"(y) : );
91
+ asm volatile("mov.u32 %0, %%nclusterid.z;\n" : "=r"(z) : );
92
+ return {x, y, z};
93
+ #elif defined(__CUDA_ARCH__)
94
+ // MSVC requires protecting use of gridDim with __CUDA_ARCH__.
95
+ return gridDim;
96
+ #elif defined(_MSC_VER)
97
+ CUTE_INVALID_CONTROL_PATH("cluster_grid_dims() can only be called on device");
98
+ return {0, 0, 0};
99
+ #else
100
+ return {0, 0, 0};
101
+ #endif
102
+ }
103
+
104
+ // Returns the dim3 cluster rank in the grid.
105
+ CUTE_DEVICE dim3 cluster_id_in_grid()
106
+ {
107
+ #if defined(CUTE_ARCH_CLUSTER_SM90_ENABLED)
108
+ uint32_t x, y, z;
109
+ asm volatile("mov.u32 %0, %%clusterid.x;\n" : "=r"(x) : );
110
+ asm volatile("mov.u32 %0, %%clusterid.y;\n" : "=r"(y) : );
111
+ asm volatile("mov.u32 %0, %%clusterid.z;\n" : "=r"(z) : );
112
+ return {x, y, z};
113
+ #elif defined(__CUDA_ARCH__)
114
+ // MSVC requires protecting use of blockIdx with __CUDA_ARCH__.
115
+ return blockIdx;
116
+ #elif defined(_MSC_VER)
117
+ CUTE_INVALID_CONTROL_PATH("cluster_id_in_grid() can only be called on device");
118
+ return {0, 0, 0};
119
+ #else
120
+ return {0, 0, 0};
121
+ #endif
122
+ }
123
+
124
+ // Returns the relative dim3 block rank local to the cluster.
125
+ CUTE_DEVICE dim3 block_id_in_cluster()
126
+ {
127
+ #if defined(CUTE_ARCH_CLUSTER_SM90_ENABLED)
128
+ uint32_t x, y, z;
129
+ asm volatile("mov.u32 %0, %%cluster_ctaid.x;\n" : "=r"(x) : );
130
+ asm volatile("mov.u32 %0, %%cluster_ctaid.y;\n" : "=r"(y) : );
131
+ asm volatile("mov.u32 %0, %%cluster_ctaid.z;\n" : "=r"(z) : );
132
+ return {x, y, z};
133
+ #else
134
+ return {0,0,0};
135
+ #endif
136
+ }
137
+
138
+ // Returns the dim3 cluster shape.
139
+ CUTE_DEVICE dim3 cluster_shape()
140
+ {
141
+ #if defined(CUTE_ARCH_CLUSTER_SM90_ENABLED)
142
+ uint32_t x, y, z;
143
+ asm volatile("mov.u32 %0, %%cluster_nctaid.x;\n" : "=r"(x) : );
144
+ asm volatile("mov.u32 %0, %%cluster_nctaid.y;\n" : "=r"(y) : );
145
+ asm volatile("mov.u32 %0, %%cluster_nctaid.z;\n" : "=r"(z) : );
146
+ return {x, y, z};
147
+ #else
148
+ return {1,1,1};
149
+ #endif
150
+ }
151
+
152
+ // Get 1D ctaid in a cluster.
153
+ CUTE_DEVICE uint32_t block_rank_in_cluster()
154
+ {
155
+ #if defined(CUTE_ARCH_CLUSTER_SM90_ENABLED)
156
+ uint32_t rank;
157
+ asm volatile("mov.u32 %0, %%cluster_ctarank;\n" : "=r"(rank) :);
158
+ return rank;
159
+ #else
160
+ return 0;
161
+ #endif
162
+ }
163
+
164
+ // Set the destination block-ID in cluster for a given SMEM Address
165
+ CUTE_DEVICE uint32_t set_block_rank(uint32_t smemAddr, uint32_t rank)
166
+ {
167
+ #if defined(CUTE_ARCH_CLUSTER_SM90_ENABLED)
168
+ uint32_t result;
169
+ asm volatile("mapa.shared::cluster.u32 %0, %1, %2;\n"
170
+ : "=r"(result)
171
+ : "r"(smemAddr), "r"(rank));
172
+ return result;
173
+ #else
174
+ return smemAddr;
175
+ #endif
176
+ }
177
+
178
+ // Elect one thread in the warp. The elected thread gets its predicate set to true, all others obtain false.
179
+ CUTE_HOST_DEVICE uint32_t elect_one_sync()
180
+ {
181
+ #if defined(CUTE_ARCH_ELECT_ONE_SM90_ENABLED)
182
+ uint32_t pred = 0;
183
+ uint32_t laneid = 0;
184
+ asm volatile(
185
+ "{\n"
186
+ ".reg .b32 %%rx;\n"
187
+ ".reg .pred %%px;\n"
188
+ " elect.sync %%rx|%%px, %2;\n"
189
+ "@%%px mov.s32 %1, 1;\n"
190
+ " mov.s32 %0, %%rx;\n"
191
+ "}\n"
192
+ : "+r"(laneid), "+r"(pred)
193
+ : "r"(0xFFFFFFFF));
194
+ return pred;
195
+ #elif defined(__CUDA_ARCH__)
196
+ return (threadIdx.x % 32) == 0;
197
+ #else
198
+ return true;
199
+ #endif
200
+ }
201
+
202
+ struct ElectOneLaneIdReturnType {
203
+ uint32_t is_leader;
204
+ uint32_t leader_lane_id;
205
+ };
206
+
207
+ CUTE_HOST_DEVICE
208
+ ElectOneLaneIdReturnType
209
+ elect_one_leader_sync()
210
+ {
211
+ #if defined(CUTE_ARCH_ELECT_ONE_SM90_ENABLED)
212
+ uint32_t pred = 0;
213
+ uint32_t laneid = 0;
214
+ asm volatile(
215
+ "{\n"
216
+ ".reg .b32 %%rx;\n"
217
+ ".reg .pred %%px;\n"
218
+ " elect.sync %%rx|%%px, %2;\n"
219
+ "@%%px mov.s32 %1, 1;\n"
220
+ " mov.s32 %0, %%rx;\n"
221
+ "}\n"
222
+ : "+r"(laneid), "+r"(pred)
223
+ : "r"(0xFFFFFFFF));
224
+ return {pred, laneid};
225
+ #elif defined(__CUDA_ARCH__)
226
+ return {(threadIdx.x % 32) == 0, 0};
227
+ #else
228
+ return {true, 0};
229
+ #endif
230
+ }
231
+
232
+ // Store value to remote shared memory in the cluster
233
+ CUTE_DEVICE
234
+ void
235
+ store_shared_remote(uint32_t value, uint32_t smem_addr, uint32_t mbarrier_addr, uint32_t dst_cta_rank)
236
+ {
237
+ #if defined(CUTE_ARCH_CLUSTER_SM90_ENABLED)
238
+ uint32_t dsmem_addr = set_block_rank(smem_addr, dst_cta_rank);
239
+ uint32_t remote_barrier_addr = set_block_rank(mbarrier_addr, dst_cta_rank);
240
+ asm volatile("st.async.shared::cluster.mbarrier::complete_tx::bytes.u32 [%0], %1, [%2];"
241
+ : : "r"(dsmem_addr), "r"(value), "r"(remote_barrier_addr));
242
+ #endif
243
+ }
244
+
245
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/config.hpp ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2024 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cutlass/arch/config.h> // CUTLASS_ARCH_MMA_SMxx_ENABLED
34
+
35
+ // MMA SM90A
36
+ #if defined(CUTLASS_ARCH_MMA_SM90A_ENABLED)
37
+ # define CUTE_ARCH_MMA_SM90A_ENABLED
38
+ #endif
39
+
40
+ // TMA instructions
41
+ #if defined(CUTLASS_ARCH_MMA_SM90_ENABLED)
42
+ # define CUTE_ARCH_TMA_SM90_ENABLED
43
+ #endif
44
+
45
+ #if defined(CUTLASS_ARCH_MMA_MODIFIABLE_TMA_SM90_ENABLED)
46
+ # define CUTE_ARCH_DEVICE_MODIFIABLE_TMA_SM90_ENABLED
47
+ #endif
48
+
49
+ // STSM
50
+ #if defined(CUTLASS_ARCH_MMA_SM90_ENABLED)
51
+ # define CUTE_ARCH_STSM_SM90_ENABLED
52
+ #endif
53
+
54
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
55
+
56
+ #if (defined(CUTLASS_ARCH_MMA_SM100A_ENABLED) || defined(CUTLASS_ARCH_MMA_SM101A_ENABLED) ||\
57
+ defined(CUTLASS_ARCH_MMA_SM120A_ENABLED))
58
+ # define CUTE_ARCH_TMA_SM90_ENABLED
59
+ # define CUTE_ARCH_DEVICE_MODIFIABLE_TMA_SM90_ENABLED
60
+ # define CUTE_ARCH_STSM_SM90_ENABLED
61
+ #endif
62
+
63
+ #if (defined(CUTLASS_ARCH_MMA_SM100A_ENABLED) || defined(CUTLASS_ARCH_MMA_SM101A_ENABLED))
64
+ # define CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED
65
+ # define CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED
66
+ # define CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED
67
+ # define CUTE_ARCH_TCGEN05_MXF4_MMA_ENABLED
68
+ # define CUTE_ARCH_TCGEN05_MXF4NVF4_MMA_ENABLED
69
+ #endif
70
+
71
+ #if defined(CUTLASS_ARCH_MMA_SM100A_ENABLED)
72
+ # define CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED
73
+ #endif
74
+
75
+ #if (defined(CUTLASS_ARCH_MMA_SM100A_ENABLED) || defined(CUTLASS_ARCH_MMA_SM101A_ENABLED))
76
+ # define CUTE_ARCH_TCGEN05_S8_MMA_ENABLED
77
+ #endif
78
+
79
+ #if (defined(CUTLASS_ARCH_MMA_SM100A_ENABLED) || defined(CUTLASS_ARCH_MMA_SM101A_ENABLED) ||\
80
+ defined(CUTLASS_ARCH_MMA_SM120A_ENABLED))
81
+ # define CUTE_ARCH_LDSM_SM100A_ENABLED
82
+ # define CUTE_ARCH_STSM_SM100A_ENABLED
83
+ #endif
84
+
85
+ #if (defined(CUTLASS_ARCH_MMA_SM100A_ENABLED) || defined(CUTLASS_ARCH_MMA_SM101A_ENABLED))
86
+ # define CUTE_ARCH_TCGEN05_TMEM_ENABLED
87
+ #endif
88
+
89
+ #if (defined(CUTLASS_ARCH_MMA_SM100A_ENABLED) || defined(CUTLASS_ARCH_MMA_SM101A_ENABLED))
90
+ # define CUTE_ARCH_TMA_SM100_ENABLED
91
+ #endif
92
+
93
+ // {add, mul, fma}.f32x2 PTX
94
+ #if (defined(CUTLASS_ARCH_MMA_SM100A_ENABLED))
95
+ #define CUTE_ARCH_FLOAT2_MATH_ENABLED
96
+ #endif
97
+
98
+ #if defined(CUTLASS_ARCH_MMA_SM120_ENABLED) || defined(CUTLASS_ARCH_MMA_SM120A_ENABLED)
99
+ # define CUTE_ARCH_MMA_SM120_ENABLED
100
+ # define CUTE_ARCH_TMA_SM120_ENABLED
101
+ #endif
102
+
103
+ #if defined(CUTLASS_ARCH_MMA_SM120_ENABLED) || defined(CUTLASS_ARCH_MMA_SM120A_ENABLED)
104
+ # if (__CUDACC_VER_MAJOR__ > 12 || (__CUDACC_VER_MAJOR__ == 12 && __CUDACC_VER_MINOR__ >= 8))
105
+ # define CUTE_ARCH_F8F6F4_MMA_ENABLED
106
+ # define CUTE_ARCH_MXF8F6F4_MMA_ENABLED
107
+ # define CUTE_ARCH_MXF4NVF4_2X_UE8M0_MMA_ENABLED
108
+ # define CUTE_ARCH_MXF4NVF4_4X_UE4M3_MMA_ENABLED
109
+ # endif
110
+ #endif
111
+
lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy.hpp ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp>
34
+
35
+ #include <cute/arch/util.hpp>
36
+ #include <cute/numeric/numeric_types.hpp>
37
+
38
+ namespace cute
39
+ {
40
+
41
+ //
42
+ // Direct Copy for any specific types
43
+ //
44
+
45
+ template <class S, class D = S>
46
+ struct UniversalCopy
47
+ {
48
+ using SRegisters = S[1];
49
+ using DRegisters = D[1];
50
+
51
+ // Sanity
52
+ static_assert(sizeof_bits_v<S> >= 8);
53
+ static_assert(sizeof_bits_v<D> >= 8);
54
+
55
+ CUTE_HOST_DEVICE static constexpr void
56
+ copy(S const& src,
57
+ D & dst)
58
+ {
59
+ dst = src;
60
+ }
61
+ };
62
+
63
+ //
64
+ // Placeholder for the copy algorithm's stronger auto-vectorizing behavior
65
+ // that assumes alignment of pointers and dynamic layouts up to MaxVecBits
66
+ //
67
+
68
+ template <int MaxVecBits = 128>
69
+ struct AutoVectorizingCopyWithAssumedAlignment
70
+ : UniversalCopy<uint_bit_t<MaxVecBits>>
71
+ {
72
+ static_assert(MaxVecBits == 8 || MaxVecBits == 16 || MaxVecBits == 32 || MaxVecBits == 64 || MaxVecBits == 128,
73
+ "Expected MaxVecBits to be 8 or 16 or 32 or 64 or 128 for alignment and performance.");
74
+ };
75
+
76
+ //
77
+ // AutoVectorizingCopy alias assumes maximal alignment of pointers and dynamic strides.
78
+ // If this is not the case then AutoVectorizingCopyWithAssumedAlignment should be used instead
79
+ //
80
+
81
+ using AutoVectorizingCopy = AutoVectorizingCopyWithAssumedAlignment<128>;
82
+
83
+ //
84
+ // DefaultCopy alias does not assume alignment of pointers or dynamic strides.
85
+ //
86
+
87
+ using DefaultCopy = AutoVectorizingCopyWithAssumedAlignment<8>;
88
+
89
+ //
90
+ // Copy policy automatically selecting between
91
+ // UniversalCopy and cp.async , based on type and memory space.
92
+ //
93
+ struct AutoCopyAsync {};
94
+
95
+ //
96
+ // Global memory prefetch into L2
97
+ //
98
+
99
+ CUTE_HOST_DEVICE static void
100
+ prefetch(void const* gmem_ptr)
101
+ {
102
+ #if defined(__CUDA_ARCH__)
103
+ asm volatile("prefetch.global.L2 [%0];\n" : : "l"(gmem_ptr) : "memory");
104
+ #endif
105
+ }
106
+
107
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm100.hpp ADDED
The diff for this file is too large to render. See raw diff
 
lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm100_tma.hpp ADDED
@@ -0,0 +1,664 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2020 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+
32
+
33
+
34
+ #pragma once
35
+
36
+ #include <cute/arch/config.hpp>
37
+
38
+ #include <cute/arch/copy.hpp>
39
+ #include <cute/arch/copy_sm90.hpp>
40
+ namespace cute
41
+ {
42
+
43
+ constexpr uint32_t Sm100MmaPeerBitMask = 0xFEFFFFFF;
44
+ constexpr uint64_t Sm100MemDescDefault = uint64_t(0x1000000000000000);
45
+
46
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
47
+ /// UTMA_LOAD : Initiates a TMA copy from global memory to shared memory
48
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
49
+
50
+ struct SM100_TMA_2SM_LOAD_1D
51
+ {
52
+ CUTE_HOST_DEVICE static void
53
+ copy([[maybe_unused]] void const* desc_ptr, [[maybe_unused]] uint64_t* mbar_ptr, [[maybe_unused]] uint64_t cache_hint,
54
+ [[maybe_unused]] void * smem_ptr,
55
+ [[maybe_unused]] int32_t const& crd0)
56
+ {
57
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
58
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
59
+ // Executed by both CTAs. Set peer bit to 0 so that the
60
+ // transaction bytes will update CTA0's barrier.
61
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
62
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
63
+ asm volatile (
64
+ "cp.async.bulk.tensor.1d.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.L2::cache_hint"
65
+ " [%0], [%1, {%3}], [%2], %4;"
66
+ :
67
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
68
+ "r"(crd0), "l"(cache_hint)
69
+ : "memory");
70
+ #else
71
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM100_ENABLED.");
72
+ #endif
73
+ }
74
+ };
75
+
76
+ struct SM100_TMA_2SM_LOAD_2D
77
+ {
78
+ CUTE_HOST_DEVICE static void
79
+ copy([[maybe_unused]] void const* desc_ptr, [[maybe_unused]] uint64_t* mbar_ptr, [[maybe_unused]] uint64_t cache_hint,
80
+ [[maybe_unused]] void * smem_ptr,
81
+ [[maybe_unused]] int32_t const& crd0, int32_t const& crd1)
82
+ {
83
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
84
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
85
+ // Executed by both CTAs. Set peer bit to 0 so that the
86
+ // transaction bytes will update CTA0's barrier.
87
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
88
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
89
+ asm volatile (
90
+ "cp.async.bulk.tensor.2d.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.L2::cache_hint"
91
+ " [%0], [%1, {%3, %4}], [%2], %5;"
92
+ :
93
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
94
+ "r"(crd0), "r"(crd1), "l"(cache_hint)
95
+ : "memory");
96
+ #else
97
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM100_ENABLED.");
98
+ #endif
99
+ }
100
+ };
101
+
102
+ struct SM100_TMA_2SM_LOAD_3D
103
+ {
104
+ CUTE_HOST_DEVICE static void
105
+ copy([[maybe_unused]] void const* desc_ptr, [[maybe_unused]] uint64_t* mbar_ptr, [[maybe_unused]] uint64_t cache_hint,
106
+ [[maybe_unused]] void * smem_ptr,
107
+ [[maybe_unused]] int32_t const& crd0, int32_t const& crd1, int32_t const& crd2)
108
+ {
109
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
110
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
111
+ // Executed by both CTAs. Set peer bit to 0 so that the
112
+ // transaction bytes will update CTA0's barrier.
113
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
114
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
115
+ asm volatile (
116
+ "cp.async.bulk.tensor.3d.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.L2::cache_hint"
117
+ " [%0], [%1, {%3, %4, %5}], [%2], %6;"
118
+ :
119
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
120
+ "r"(crd0), "r"(crd1), "r"(crd2), "l"(cache_hint)
121
+ : "memory");
122
+ #else
123
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM100_ENABLED.");
124
+ #endif
125
+ }
126
+ };
127
+
128
+ struct SM100_TMA_2SM_LOAD_4D
129
+ {
130
+ CUTE_HOST_DEVICE static void
131
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
132
+ void * smem_ptr,
133
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3)
134
+ {
135
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
136
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
137
+ // Executed by both CTAs. Set peer bit to 0 so that the
138
+ // transaction bytes will update CTA0's barrier.
139
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
140
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
141
+ asm volatile (
142
+ "cp.async.bulk.tensor.4d.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.L2::cache_hint"
143
+ " [%0], [%1, {%3, %4, %5, %6}], [%2], %7;"
144
+ :
145
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
146
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3), "l"(cache_hint)
147
+ : "memory");
148
+ #else
149
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM100_ENABLED.");
150
+ #endif
151
+ }
152
+ };
153
+
154
+ struct SM100_TMA_2SM_LOAD_5D
155
+ {
156
+ CUTE_HOST_DEVICE static void
157
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
158
+ void * smem_ptr,
159
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3, int32_t const& crd4)
160
+ {
161
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
162
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
163
+ // Executed by both CTAs. Set peer bit to 0 so that the
164
+ // transaction bytes will update CTA0's barrier.
165
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
166
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
167
+ asm volatile (
168
+ "cp.async.bulk.tensor.5d.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.L2::cache_hint"
169
+ " [%0], [%1, {%3, %4, %5, %6, %7}], [%2], %8;"
170
+ :
171
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
172
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3), "r"(crd4), "l"(cache_hint)
173
+ : "memory");
174
+ #else
175
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM100_ENABLED.");
176
+ #endif
177
+ }
178
+ };
179
+
180
+ struct SM100_TMA_2SM_LOAD
181
+ {
182
+ CUTE_HOST_DEVICE static void
183
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
184
+ void * smem_ptr,
185
+ int32_t const& crd0)
186
+ {
187
+ return SM100_TMA_2SM_LOAD_1D::copy(desc_ptr, mbar_ptr, cache_hint, smem_ptr, crd0);
188
+ }
189
+ CUTE_HOST_DEVICE static void
190
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
191
+ void * smem_ptr,
192
+ int32_t const& crd0, int32_t const& crd1)
193
+ {
194
+ return SM100_TMA_2SM_LOAD_2D::copy(desc_ptr, mbar_ptr, cache_hint, smem_ptr, crd0, crd1);
195
+ }
196
+ CUTE_HOST_DEVICE static void
197
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
198
+ void * smem_ptr,
199
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2)
200
+ {
201
+ return SM100_TMA_2SM_LOAD_3D::copy(desc_ptr, mbar_ptr, cache_hint, smem_ptr, crd0, crd1, crd2);
202
+ }
203
+ CUTE_HOST_DEVICE static void
204
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
205
+ void * smem_ptr,
206
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3)
207
+ {
208
+ return SM100_TMA_2SM_LOAD_4D::copy(desc_ptr, mbar_ptr, cache_hint, smem_ptr, crd0, crd1, crd2, crd3);
209
+ }
210
+ CUTE_HOST_DEVICE static void
211
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
212
+ void * smem_ptr,
213
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3, int32_t const& crd4)
214
+ {
215
+ return SM100_TMA_2SM_LOAD_5D::copy(desc_ptr, mbar_ptr, cache_hint, smem_ptr, crd0, crd1, crd2, crd3, crd4);
216
+ }
217
+
218
+ using PREFETCH = typename SM90_TMA_LOAD::PREFETCH;
219
+ };
220
+
221
+
222
+
223
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
224
+ /// TMA_LOAD_MULTICAST: Initiates a TMA copy from global memory to shared memory
225
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
226
+
227
+ struct SM100_TMA_2SM_LOAD_MULTICAST_1D
228
+ {
229
+ CUTE_HOST_DEVICE static void
230
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
231
+ void * smem_ptr,
232
+ int32_t const& crd0)
233
+ {
234
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
235
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
236
+ // Executed by both CTAs. Set peer bit to 0 so that the
237
+ // transaction bytes will update CTA0's barrier.
238
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
239
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
240
+ asm volatile (
241
+ "cp.async.bulk.tensor.1d.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.multicast::cluster.L2::cache_hint"
242
+ " [%0], [%1, {%4}], [%2], %3, %5;"
243
+ :
244
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar), "h"(multicast_mask),
245
+ "r"(crd0), "l"(cache_hint)
246
+ : "memory");
247
+ #else
248
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM100_ENABLED.");
249
+ #endif
250
+ }
251
+ };
252
+
253
+ struct SM100_TMA_2SM_LOAD_MULTICAST_2D
254
+ {
255
+ CUTE_HOST_DEVICE static void
256
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
257
+ void * smem_ptr,
258
+ int32_t const& crd0, int32_t const& crd1)
259
+ {
260
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
261
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
262
+ // Executed by both CTAs. Set peer bit to 0 so that the
263
+ // transaction bytes will update CTA0's barrier.
264
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
265
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
266
+ asm volatile (
267
+ "cp.async.bulk.tensor.2d.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.multicast::cluster.L2::cache_hint"
268
+ " [%0], [%1, {%4, %5}], [%2], %3, %6;"
269
+ :
270
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar), "h"(multicast_mask),
271
+ "r"(crd0), "r"(crd1), "l"(cache_hint)
272
+ : "memory");
273
+ #else
274
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM100_ENABLED.");
275
+ #endif
276
+ }
277
+ };
278
+
279
+ struct SM100_TMA_2SM_LOAD_MULTICAST_3D
280
+ {
281
+ CUTE_HOST_DEVICE static void
282
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
283
+ void * smem_ptr,
284
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2)
285
+ {
286
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
287
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
288
+ // Executed by both CTAs. Set peer bit to 0 so that the
289
+ // transaction bytes will update CTA0's barrier.
290
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
291
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
292
+ asm volatile (
293
+ "cp.async.bulk.tensor.3d.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.multicast::cluster.L2::cache_hint"
294
+ " [%0], [%1, {%4, %5, %6}], [%2], %3, %7;"
295
+ :
296
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar), "h"(multicast_mask),
297
+ "r"(crd0), "r"(crd1), "r"(crd2), "l"(cache_hint)
298
+ : "memory");
299
+ #else
300
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM100_ENABLED.");
301
+ #endif
302
+ }
303
+ };
304
+
305
+ struct SM100_TMA_2SM_LOAD_MULTICAST_4D
306
+ {
307
+ CUTE_HOST_DEVICE static void
308
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
309
+ void * smem_ptr,
310
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3)
311
+ {
312
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
313
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
314
+ // Executed by both CTAs. Set peer bit to 0 so that the
315
+ // transaction bytes will update CTA0's barrier.
316
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
317
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
318
+ asm volatile (
319
+ "cp.async.bulk.tensor.4d.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.multicast::cluster.L2::cache_hint"
320
+ " [%0], [%1, {%4, %5, %6, %7}], [%2], %3, %8;"
321
+ :
322
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar), "h"(multicast_mask),
323
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3), "l"(cache_hint)
324
+ : "memory");
325
+ #else
326
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM100_ENABLED.");
327
+ #endif
328
+ }
329
+ };
330
+
331
+ struct SM100_TMA_2SM_LOAD_MULTICAST_5D
332
+ {
333
+ CUTE_HOST_DEVICE static void
334
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
335
+ void * smem_ptr,
336
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3, int32_t const& crd4)
337
+ {
338
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
339
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
340
+ // Executed by both CTAs. Set peer bit to 0 so that the
341
+ // transaction bytes will update CTA0's barrier.
342
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
343
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
344
+ asm volatile (
345
+ "cp.async.bulk.tensor.5d.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.multicast::cluster.L2::cache_hint"
346
+ " [%0], [%1, {%4, %5, %6, %7, %8}], [%2], %3, %9;"
347
+ :
348
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar), "h"(multicast_mask),
349
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3), "r"(crd4), "l"(cache_hint)
350
+ : "memory");
351
+ #else
352
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM0_ENABLED.");
353
+ #endif
354
+ }
355
+ };
356
+
357
+ struct SM100_TMA_2SM_LOAD_MULTICAST
358
+ {
359
+ CUTE_HOST_DEVICE static void
360
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
361
+ void * smem_ptr,
362
+ int32_t const& crd0)
363
+ {
364
+ return SM100_TMA_2SM_LOAD_MULTICAST_1D::copy(desc_ptr, mbar_ptr, multicast_mask, cache_hint, smem_ptr, crd0);
365
+ }
366
+ CUTE_HOST_DEVICE static void
367
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
368
+ void * smem_ptr,
369
+ int32_t const& crd0, int32_t const& crd1)
370
+ {
371
+ return SM100_TMA_2SM_LOAD_MULTICAST_2D::copy(desc_ptr, mbar_ptr, multicast_mask, cache_hint, smem_ptr, crd0, crd1);
372
+ }
373
+ CUTE_HOST_DEVICE static void
374
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
375
+ void * smem_ptr,
376
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2)
377
+ {
378
+ return SM100_TMA_2SM_LOAD_MULTICAST_3D::copy(desc_ptr, mbar_ptr, multicast_mask, cache_hint, smem_ptr, crd0, crd1, crd2);
379
+ }
380
+ CUTE_HOST_DEVICE static void
381
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
382
+ void * smem_ptr,
383
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3)
384
+ {
385
+ return SM100_TMA_2SM_LOAD_MULTICAST_4D::copy(desc_ptr, mbar_ptr, multicast_mask, cache_hint, smem_ptr, crd0, crd1, crd2, crd3);
386
+ }
387
+ CUTE_HOST_DEVICE static void
388
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
389
+ void * smem_ptr,
390
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3, int32_t const& crd4)
391
+ {
392
+ return SM100_TMA_2SM_LOAD_MULTICAST_5D::copy(desc_ptr, mbar_ptr, multicast_mask, cache_hint, smem_ptr, crd0, crd1, crd2, crd3, crd4);
393
+ }
394
+
395
+ using PREFETCH = typename SM90_TMA_LOAD::PREFETCH;
396
+ };
397
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
398
+
399
+
400
+ struct SM100_TMA_2SM_LOAD_IM2COL_3D
401
+ {
402
+ CUTE_HOST_DEVICE static void
403
+ copy(void const* desc_ptr, uint64_t* mbar_ptr,
404
+ void * smem_ptr,
405
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_n,
406
+ uint16_t const& offset_w)
407
+ {
408
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
409
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
410
+ // Executed by both CTAs. Set peer bit to 0 so that the
411
+ // transaction bytes will update CTA0's barrier.
412
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
413
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
414
+ asm volatile (
415
+ "cp.async.bulk.tensor.3d.im2col.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.L2::cache_hint"
416
+ " [%0], [%1, {%3, %4, %5}], [%2], {%6}, %7;"
417
+ :
418
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
419
+ "r"(coord_c), "r"(coord_w), "r"(coord_n),
420
+ "h"(offset_w), "l"(Sm100MemDescDefault)
421
+ : "memory");
422
+ #else
423
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM100_ENABLED.");
424
+ #endif
425
+ }
426
+ };
427
+
428
+ struct SM100_TMA_2SM_LOAD_IM2COL_4D
429
+ {
430
+ CUTE_HOST_DEVICE static void
431
+ copy(void const* desc_ptr, uint64_t* mbar_ptr,
432
+ void * smem_ptr,
433
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_n,
434
+ uint16_t const& offset_w,
435
+ uint16_t const& offset_h)
436
+ {
437
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
438
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
439
+ // Executed by both CTAs. Set peer bit to 0 so that the
440
+ // transaction bytes will update CTA0's barrier.
441
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
442
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
443
+ asm volatile (
444
+ "cp.async.bulk.tensor.4d.im2col.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.L2::cache_hint"
445
+ " [%0], [%1, {%3, %4, %5, %6}], [%2], {%7, %8}, %9;"
446
+ :
447
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
448
+ "r"(coord_c), "r"(coord_w), "r"(coord_h), "r"(coord_n),
449
+ "h"(offset_w), "h"(offset_h), "l"(Sm100MemDescDefault)
450
+ : "memory");
451
+ #else
452
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM100_ENABLED.");
453
+ #endif
454
+ }
455
+ };
456
+
457
+ struct SM100_TMA_2SM_LOAD_IM2COL_5D
458
+ {
459
+ CUTE_HOST_DEVICE static void
460
+ copy(void const* desc_ptr, uint64_t* mbar_ptr,
461
+ void * smem_ptr,
462
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_d, int32_t const& coord_n,
463
+ uint16_t const& offset_w,
464
+ uint16_t const& offset_h,
465
+ uint16_t const& offset_d)
466
+ {
467
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
468
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
469
+ // Executed by both CTAs. Set peer bit to 0 so that the
470
+ // transaction bytes will update CTA0's barrier.
471
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
472
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
473
+ asm volatile (
474
+ "cp.async.bulk.tensor.5d.im2col.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.L2::cache_hint"
475
+ " [%0], [%1, {%3, %4, %5, %6, %7}], [%2], {%8, %9, %10}, %11;"
476
+ :
477
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
478
+ "r"(coord_c), "r"(coord_w), "r"(coord_h), "r"(coord_d), "r"(coord_n),
479
+ "h"(offset_w), "h"(offset_h), "h"(offset_d), "l"(Sm100MemDescDefault)
480
+ : "memory");
481
+ #else
482
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM100_ENABLED.");
483
+ #endif
484
+ }
485
+ };
486
+
487
+ struct SM100_TMA_2SM_LOAD_IM2COL
488
+ {
489
+ CUTE_HOST_DEVICE static void
490
+ copy(void const* desc_ptr, uint64_t* mbar_ptr,
491
+ void * smem_ptr,
492
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_n,
493
+ uint16_t const& offset_w)
494
+ {
495
+ return SM100_TMA_2SM_LOAD_IM2COL_3D::copy(desc_ptr, mbar_ptr, smem_ptr,
496
+ coord_c, coord_w, coord_n,
497
+ offset_w);
498
+ }
499
+ CUTE_HOST_DEVICE static void
500
+ copy(void const* desc_ptr, uint64_t* mbar_ptr,
501
+ void * smem_ptr,
502
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_n,
503
+ uint16_t const& offset_w,
504
+ uint16_t const& offset_h)
505
+ {
506
+ return SM100_TMA_2SM_LOAD_IM2COL_4D::copy(desc_ptr, mbar_ptr, smem_ptr,
507
+ coord_c, coord_w, coord_h, coord_n,
508
+ offset_w, offset_h);
509
+ }
510
+ CUTE_HOST_DEVICE static void
511
+ copy(void const* desc_ptr, uint64_t* mbar_ptr,
512
+ void * smem_ptr,
513
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_d, int32_t const& coord_n,
514
+ uint16_t const& offset_w,
515
+ uint16_t const& offset_h,
516
+ uint16_t const& offset_d)
517
+ {
518
+ return SM100_TMA_2SM_LOAD_IM2COL_5D::copy(desc_ptr, mbar_ptr, smem_ptr,
519
+ coord_c, coord_w, coord_h, coord_d, coord_n,
520
+ offset_w, offset_h, offset_d);
521
+ }
522
+
523
+ using PREFETCH = typename SM90_TMA_LOAD_IM2COL::PREFETCH;
524
+ };
525
+
526
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
527
+
528
+ struct SM100_TMA_2SM_LOAD_IM2COL_MULTICAST_3D
529
+ {
530
+ CUTE_HOST_DEVICE static void
531
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask,
532
+ void * smem_ptr,
533
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_n,
534
+ uint16_t const& offset_w)
535
+ {
536
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
537
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
538
+ // Executed by both CTAs. Set peer bit to 0 so that the
539
+ // transaction bytes will update CTA0's barrier.
540
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
541
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
542
+ asm volatile (
543
+ "cp.async.bulk.tensor.3d.im2col.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.multicast::cluster.L2::cache_hint"
544
+ " [%0], [%1, {%3, %4, %5}], [%2], {%6}, %7, %8;"
545
+ :
546
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
547
+ "r"(coord_c), "r"(coord_w), "r"(coord_n),
548
+ "h"(offset_w),
549
+ "h"(multicast_mask),
550
+ "l"(Sm100MemDescDefault)
551
+ : "memory");
552
+ #else
553
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM100_ENABLED.");
554
+ #endif
555
+ }
556
+ };
557
+
558
+ struct SM100_TMA_2SM_LOAD_IM2COL_MULTICAST_4D
559
+ {
560
+ CUTE_HOST_DEVICE static void
561
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask,
562
+ void * smem_ptr,
563
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_n,
564
+ uint16_t const& offset_w,
565
+ uint16_t const& offset_h)
566
+ {
567
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
568
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
569
+ // Executed by both CTAs. Set peer bit to 0 so that the
570
+ // transaction bytes will update CTA0's barrier.
571
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
572
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
573
+ asm volatile (
574
+ "cp.async.bulk.tensor.4d.im2col.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.multicast::cluster.L2::cache_hint"
575
+ " [%0], [%1, {%3, %4, %5, %6}], [%2], {%7, %8}, %9, %10;"
576
+ :
577
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
578
+ "r"(coord_c), "r"(coord_w), "r"(coord_h), "r"(coord_n),
579
+ "h"(offset_w), "h"(offset_h),
580
+ "h"(multicast_mask),
581
+ "l"(Sm100MemDescDefault)
582
+ : "memory");
583
+ #else
584
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM100_ENABLED.");
585
+ #endif
586
+ }
587
+ };
588
+
589
+ struct SM100_TMA_2SM_LOAD_IM2COL_MULTICAST_5D
590
+ {
591
+ CUTE_HOST_DEVICE static void
592
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask,
593
+ void * smem_ptr,
594
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_d, int32_t const& coord_n,
595
+ uint16_t const& offset_w,
596
+ uint16_t const& offset_h,
597
+ uint16_t const& offset_d)
598
+ {
599
+ #if defined(CUTE_ARCH_TMA_SM100_ENABLED)
600
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
601
+ // Executed by both CTAs. Set peer bit to 0 so that the
602
+ // transaction bytes will update CTA0's barrier.
603
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr) & Sm100MmaPeerBitMask;
604
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
605
+ asm volatile (
606
+ "cp.async.bulk.tensor.5d.im2col.cta_group::2.shared::cluster.global.mbarrier::complete_tx::bytes.multicast::cluster.L2::cache_hint"
607
+ " [%0], [%1, {%3, %4, %5, %6, %7}], [%2], {%8, %9, %10}, %11, %12;"
608
+ :
609
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
610
+ "r"(coord_c), "r"(coord_w), "r"(coord_h), "r"(coord_d), "r"(coord_n),
611
+ "h"(offset_w), "h"(offset_h), "h"(offset_d),
612
+ "h"(multicast_mask),
613
+ "l"(Sm100MemDescDefault)
614
+ : "memory");
615
+ #else
616
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM100_ENABLED.");
617
+ #endif
618
+ }
619
+ };
620
+
621
+ struct SM100_TMA_2SM_LOAD_IM2COL_MULTICAST
622
+ {
623
+ CUTE_HOST_DEVICE static void
624
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask,
625
+ void * smem_ptr,
626
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_n,
627
+ uint16_t const& offset_w)
628
+ {
629
+ return SM100_TMA_2SM_LOAD_IM2COL_MULTICAST_3D::copy(desc_ptr, mbar_ptr, multicast_mask,
630
+ smem_ptr,
631
+ coord_c, coord_w, coord_n,
632
+ offset_w);
633
+ }
634
+ CUTE_HOST_DEVICE static void
635
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask,
636
+ void * smem_ptr,
637
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_n,
638
+ uint16_t const& offset_w, uint16_t const& offset_h)
639
+ {
640
+ return SM100_TMA_2SM_LOAD_IM2COL_MULTICAST_4D::copy(desc_ptr, mbar_ptr, multicast_mask,
641
+ smem_ptr,
642
+ coord_c, coord_w, coord_h, coord_n,
643
+ offset_w, offset_h);
644
+ }
645
+ CUTE_HOST_DEVICE static void
646
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask,
647
+ void * smem_ptr,
648
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_d, int32_t const& coord_n,
649
+ uint16_t const& offset_w, uint16_t const& offset_h, uint16_t const& offset_d)
650
+ {
651
+ return SM100_TMA_2SM_LOAD_IM2COL_MULTICAST_5D::copy(desc_ptr, mbar_ptr, multicast_mask,
652
+ smem_ptr,
653
+ coord_c, coord_w, coord_h, coord_d, coord_n,
654
+ offset_w, offset_h, offset_d);
655
+ }
656
+
657
+ using PREFETCH = typename SM90_TMA_LOAD_IM2COL::PREFETCH;
658
+ };
659
+
660
+
661
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
662
+
663
+
664
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm50.hpp ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2024 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp>
34
+
35
+ #include <cute/arch/copy.hpp>
36
+
37
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 500
38
+ #define CUTE_ARCH_WARP_SHUFFLE_ENABLED 1
39
+ #endif
40
+
41
+ namespace cute
42
+ {
43
+ // Shuffle data between thread pair (0, 1), (2, 3), etc.
44
+ struct SM50_Shuffle_U32_2x2Trans_XOR1
45
+ {
46
+ using SRegisters = uint32_t[2];
47
+ using DRegisters = uint32_t[2];
48
+
49
+ CUTE_HOST_DEVICE static void
50
+ copy(uint32_t const& src0, uint32_t const& src1, uint32_t& dst0, uint32_t& dst1)
51
+ {
52
+ #if defined(CUTE_ARCH_WARP_SHUFFLE_ENABLED)
53
+ uint32_t x0 = src0;
54
+ uint32_t y0 = __shfl_xor_sync(0xffffffff, x0, 1);
55
+
56
+ uint32_t x1 = src1;
57
+ uint32_t y1 = __shfl_xor_sync(0xffffffff, x1, 1);
58
+
59
+ if (threadIdx.x % 2 == 0) {
60
+ dst1 = y0;
61
+ }
62
+ else {
63
+ dst0 = y1;
64
+ }
65
+ #else
66
+ CUTE_INVALID_CONTROL_PATH("Trying to use __shfl_xor_sync without CUTE_ARCH_WARP_SHUFFLE_ENABLED.");
67
+ #endif
68
+ }
69
+ };
70
+
71
+ // Shuffle data between thread pair (0, 4), (1, 5), etc.
72
+ struct SM50_Shuffle_U32_2x2Trans_XOR4
73
+ {
74
+ using SRegisters = uint32_t[2];
75
+ using DRegisters = uint32_t[2];
76
+
77
+ CUTE_HOST_DEVICE static void
78
+ copy(uint32_t const& src0, uint32_t const& src1, uint32_t& dst0, uint32_t& dst1)
79
+ {
80
+ #if defined(CUTE_ARCH_WARP_SHUFFLE_ENABLED)
81
+ uint32_t x0 = threadIdx.x & 4 ? src0 : src1;
82
+ uint32_t y0 = __shfl_xor_sync(0xffffffff, x0, 4);
83
+
84
+ // Replace detination register with shuffle result.
85
+ if (threadIdx.x & 0x4) {
86
+ dst0 = y0;
87
+ }
88
+ else {
89
+ dst1 = y0;
90
+ }
91
+ #else
92
+ CUTE_INVALID_CONTROL_PATH("Trying to use __shfl_xor_sync without CUTE_ARCH_WARP_SHUFFLE_ENABLED.");
93
+ #endif
94
+ }
95
+ };
96
+
97
+
98
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm75.hpp ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp>
34
+
35
+ #include <cute/arch/copy.hpp>
36
+
37
+ // Config
38
+ #if defined(__clang__) && defined(__CUDA__)
39
+ // ldmatrix PTX instructions added in Clang 14: https://reviews.llvm.org/D107046
40
+ // ... but will not work until Clang 15:
41
+ // * https://reviews.llvm.org/D121666
42
+ // * https://reviews.llvm.org/D126846
43
+ #define CUTE_ARCH_CLANG_SUPPORTS_LDSM_SM75 (__clang_major__ >= 15)
44
+ #endif
45
+
46
+ #if defined(__NVCC__) || defined(__CUDACC_RTC__)
47
+ // ldmatrix PTX instruction added in CUDA 10.2+
48
+ #define CUTE_ARCH_NVCC_SUPPORTS_LDSM_SM75 ((__CUDACC_VER_MAJOR__ == 10 && __CUDACC_VER_MINOR__ >= 2) || __CUDACC_VER_MAJOR__ >= 11)
49
+ #endif
50
+
51
+ #if ! defined(CUTE_ARCH_LDSM_SM75_SUPPORTED)
52
+ #define CUTE_ARCH_LDSM_SM75_SUPPORTED (CUTE_ARCH_NVCC_SUPPORTS_LDSM_SM75 || CUTE_ARCH_CLANG_SUPPORTS_LDSM_SM75)
53
+ #endif
54
+
55
+ #if ! defined(CUTE_ARCH_LDSM_SM75_ENABLED)
56
+ #define CUTE_ARCH_LDSM_SM75_ENABLED (CUTE_ARCH_LDSM_SM75_SUPPORTED)
57
+ #endif
58
+
59
+ #if (CUTE_ARCH_LDSM_SM75_ENABLED) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 750
60
+ #define CUTE_ARCH_LDSM_SM75_ACTIVATED 1
61
+ #endif
62
+
63
+ namespace cute
64
+ {
65
+
66
+ struct SM75_U32x1_LDSM_N
67
+ {
68
+ using SRegisters = uint128_t[1];
69
+ using DRegisters = uint32_t[1];
70
+
71
+ CUTE_HOST_DEVICE static void
72
+ copy(uint128_t const& smem_src,
73
+ uint32_t& dst)
74
+ {
75
+ #if defined(CUTE_ARCH_LDSM_SM75_ACTIVATED)
76
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_src);
77
+ asm volatile ("ldmatrix.sync.aligned.x1.m8n8.shared.b16 {%0}, [%1];\n"
78
+ : "=r"(dst)
79
+ : "r"(smem_int_ptr));
80
+ #else
81
+ CUTE_INVALID_CONTROL_PATH("Trying to use ldmatrix without CUTE_ARCH_LDSM_SM75_ACTIVATED.");
82
+ #endif
83
+ }
84
+ };
85
+
86
+ struct SM75_U32x2_LDSM_N
87
+ {
88
+ using SRegisters = uint128_t[1];
89
+ using DRegisters = uint32_t[2];
90
+
91
+ CUTE_HOST_DEVICE static void
92
+ copy(uint128_t const& smem_src,
93
+ uint32_t& dst0, uint32_t& dst1)
94
+ {
95
+ #if defined(CUTE_ARCH_LDSM_SM75_ACTIVATED)
96
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_src);
97
+ asm volatile ("ldmatrix.sync.aligned.x2.m8n8.shared.b16 {%0, %1}, [%2];\n"
98
+ : "=r"(dst0), "=r"(dst1)
99
+ : "r"(smem_int_ptr));
100
+ #else
101
+ CUTE_INVALID_CONTROL_PATH("Trying to use ldmatrix without CUTE_ARCH_LDSM_SM75_ACTIVATED.");
102
+ #endif
103
+ }
104
+ };
105
+
106
+ struct SM75_U32x4_LDSM_N
107
+ {
108
+ using SRegisters = uint128_t[1];
109
+ using DRegisters = uint32_t[4];
110
+
111
+ CUTE_HOST_DEVICE static void
112
+ copy(uint128_t const& smem_src,
113
+ uint32_t& dst0, uint32_t& dst1, uint32_t& dst2, uint32_t& dst3)
114
+ {
115
+ #if defined(CUTE_ARCH_LDSM_SM75_ACTIVATED)
116
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_src);
117
+ asm volatile ("ldmatrix.sync.aligned.x4.m8n8.shared.b16 {%0, %1, %2, %3}, [%4];\n"
118
+ : "=r"(dst0), "=r"(dst1), "=r"(dst2), "=r"(dst3)
119
+ : "r"(smem_int_ptr));
120
+ #else
121
+ CUTE_INVALID_CONTROL_PATH("Trying to use ldmatrix without CUTE_ARCH_LDSM_SM75_ACTIVATED.");
122
+ #endif
123
+ }
124
+ };
125
+
126
+ struct SM75_U16x2_LDSM_T
127
+ {
128
+ using SRegisters = uint128_t[1];
129
+ using DRegisters = uint32_t[1];
130
+
131
+ CUTE_HOST_DEVICE static void
132
+ copy(uint128_t const& smem_src,
133
+ uint32_t& dst)
134
+ {
135
+ #if defined(CUTE_ARCH_LDSM_SM75_ACTIVATED)
136
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_src);
137
+ asm volatile ("ldmatrix.sync.aligned.x1.trans.m8n8.shared.b16 {%0}, [%1];\n"
138
+ : "=r"(dst)
139
+ : "r"(smem_int_ptr));
140
+ #else
141
+ CUTE_INVALID_CONTROL_PATH("Trying to use ldmatrix without CUTE_ARCH_LDSM_SM75_ACTIVATED.");
142
+ #endif
143
+ }
144
+ };
145
+
146
+ struct SM75_U16x4_LDSM_T
147
+ {
148
+ using SRegisters = uint128_t[1];
149
+ using DRegisters = uint32_t[2];
150
+
151
+ CUTE_HOST_DEVICE static void
152
+ copy(uint128_t const& smem_src,
153
+ uint32_t& dst0, uint32_t& dst1)
154
+ {
155
+ #if defined(CUTE_ARCH_LDSM_SM75_ACTIVATED)
156
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_src);
157
+ asm volatile ("ldmatrix.sync.aligned.x2.trans.m8n8.shared.b16 {%0, %1}, [%2];\n"
158
+ : "=r"(dst0), "=r"(dst1)
159
+ : "r"(smem_int_ptr));
160
+ #else
161
+ CUTE_INVALID_CONTROL_PATH("Trying to use ldmatrix without CUTE_ARCH_LDSM_SM75_ACTIVATED.");
162
+ #endif
163
+ }
164
+ };
165
+
166
+ struct SM75_U16x8_LDSM_T
167
+ {
168
+ using SRegisters = uint128_t[1];
169
+ using DRegisters = uint32_t[4];
170
+
171
+ CUTE_HOST_DEVICE static void
172
+ copy(uint128_t const& smem_src,
173
+ uint32_t& dst0, uint32_t& dst1, uint32_t& dst2, uint32_t& dst3)
174
+ {
175
+ #if defined(CUTE_ARCH_LDSM_SM75_ACTIVATED)
176
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_src);
177
+ asm volatile ("ldmatrix.sync.aligned.x4.trans.m8n8.shared.b16 {%0, %1, %2, %3}, [%4];\n"
178
+ : "=r"(dst0), "=r"(dst1), "=r"(dst2), "=r"(dst3)
179
+ : "r"(smem_int_ptr));
180
+ #else
181
+ CUTE_INVALID_CONTROL_PATH("Trying to use ldmatrix without CUTE_ARCH_LDSM_SM75_ACTIVATED.");
182
+ #endif
183
+ }
184
+ };
185
+
186
+ //
187
+ // Legacy LDSM interfaces that aren't very useful
188
+ //
189
+
190
+ template <class T>
191
+ CUTE_HOST_DEVICE
192
+ void
193
+ copy_ldsm(uint128_t const* const smem_ptr,
194
+ T* rmem_ptr)
195
+ {
196
+ uint32_t* reg_ptr = reinterpret_cast<uint32_t*>(rmem_ptr);
197
+
198
+ // if constexpr
199
+ if (sizeof(T) == 4) {
200
+ SM75_U32x1_LDSM_N::copy(smem_ptr[0], reg_ptr[0]);
201
+ }
202
+ else if (sizeof(T) == 8) {
203
+ SM75_U32x2_LDSM_N::copy(smem_ptr[0], reg_ptr[0], reg_ptr[1]);
204
+ }
205
+ else if (sizeof(T) == 16) {
206
+ SM75_U32x4_LDSM_N::copy(smem_ptr[0], reg_ptr[0], reg_ptr[1], reg_ptr[2], reg_ptr[3]);
207
+ }
208
+ else {
209
+ static_assert(sizeof(T) == 4 || sizeof(T) == 8 || sizeof(T) == 16, "sizeof(T) is not supported");
210
+ }
211
+ }
212
+
213
+ template <class T>
214
+ CUTE_HOST_DEVICE
215
+ void
216
+ copy_ldsm_trans(uint128_t const* const smem_ptr,
217
+ T* rmem_ptr)
218
+ {
219
+ uint32_t* reg_ptr = reinterpret_cast<uint32_t*>(rmem_ptr);
220
+
221
+ // if constexpr
222
+ if (sizeof(T) == 4) {
223
+ SM75_U16x2_LDSM_T::copy(smem_ptr[0], reg_ptr[0]);
224
+ }
225
+ else if (sizeof(T) == 8) {
226
+ SM75_U16x4_LDSM_T::copy(smem_ptr[0], reg_ptr[0], reg_ptr[1]);
227
+ }
228
+ else if (sizeof(T) == 16) {
229
+ SM75_U16x8_LDSM_T::copy(smem_ptr[0], reg_ptr[0], reg_ptr[1], reg_ptr[2], reg_ptr[3]);
230
+ }
231
+ else {
232
+ static_assert(sizeof(T) == 4 || sizeof(T) == 8 || sizeof(T) == 16, "sizeof(T) is not supported");
233
+ }
234
+ }
235
+
236
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm80.hpp ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp>
34
+
35
+ #include <cute/arch/copy.hpp>
36
+
37
+ // Config
38
+ #if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 800))
39
+ # define CUTE_ARCH_CP_ASYNC_SM80_ENABLED
40
+ #endif
41
+
42
+ namespace cute
43
+ {
44
+
45
+ /// Copy via cp.async with caching at all levels
46
+ template <class TS, class TD = TS>
47
+ struct SM80_CP_ASYNC_CACHEALWAYS
48
+ {
49
+ using SRegisters = TS[1];
50
+ using DRegisters = TD[1];
51
+
52
+ static_assert(sizeof(TS) == sizeof(TD), "cp.async requires sizeof(src_value_type) == sizeof(dst_value_type)");
53
+ static_assert(sizeof(TS) == 4 || sizeof(TS) == 8 || sizeof(TS) == 16, "cp.async sizeof(TS) is not supported");
54
+
55
+ CUTE_HOST_DEVICE static void
56
+ copy(TS const& gmem_src,
57
+ TD & smem_dst)
58
+ {
59
+ #if defined(CUTE_ARCH_CP_ASYNC_SM80_ENABLED)
60
+ TS const* gmem_ptr = &gmem_src;
61
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_dst);
62
+ asm volatile("cp.async.ca.shared.global.L2::128B [%0], [%1], %2;\n"
63
+ :: "r"(smem_int_ptr),
64
+ "l"(gmem_ptr),
65
+ "n"(sizeof(TS)));
66
+ #else
67
+ CUTE_INVALID_CONTROL_PATH("Support for cp.async instructions has not been enabled");
68
+ #endif
69
+ }
70
+ };
71
+
72
+ /// Copy via cp.async with caching at global level
73
+ template <class TS, class TD = TS>
74
+ struct SM80_CP_ASYNC_CACHEGLOBAL
75
+ {
76
+ using SRegisters = TS[1];
77
+ using DRegisters = TD[1];
78
+
79
+ static_assert(sizeof(TS) == sizeof(TD), "cp.async requires sizeof(src_value_type) == sizeof(dst_value_type)");
80
+ static_assert(sizeof(TS) == 16, "cp.async sizeof(TS) is not supported");
81
+
82
+ CUTE_HOST_DEVICE static void
83
+ copy(TS const& gmem_src,
84
+ TD & smem_dst)
85
+ {
86
+ #if defined(CUTE_ARCH_CP_ASYNC_SM80_ENABLED)
87
+ TS const* gmem_ptr = &gmem_src;
88
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_dst);
89
+ asm volatile("cp.async.cg.shared.global.L2::128B [%0], [%1], %2;\n"
90
+ :: "r"(smem_int_ptr),
91
+ "l"(gmem_ptr),
92
+ "n"(sizeof(TS)));
93
+ #else
94
+ CUTE_INVALID_CONTROL_PATH("Support for cp.async instructions has not been enabled");
95
+ #endif
96
+ }
97
+ };
98
+
99
+ /// Copy via cp.async with caching at all levels
100
+ template <class TS, class TD = TS>
101
+ struct SM80_CP_ASYNC_CACHEALWAYS_ZFILL
102
+ {
103
+ using SRegisters = TS[1];
104
+ using DRegisters = TD[1];
105
+
106
+ static_assert(sizeof(TS) == sizeof(TD), "cp.async requires sizeof(src_value_type) == sizeof(dst_value_type)");
107
+ static_assert(sizeof(TS) == 4 || sizeof(TS) == 8 || sizeof(TS) == 16, "cp.async sizeof(TS) is not supported");
108
+
109
+ CUTE_HOST_DEVICE static void
110
+ copy(TS const& gmem_src,
111
+ TD & smem_dst,
112
+ bool pred)
113
+ {
114
+ #if defined(CUTE_ARCH_CP_ASYNC_SM80_ENABLED)
115
+ TS const* gmem_ptr = &gmem_src;
116
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_dst);
117
+ int src_size = pred ? sizeof(TS) : 0;
118
+ asm volatile("cp.async.ca.shared.global.L2::128B [%0], [%1], %2, %3;\n"
119
+ :: "r"(smem_int_ptr),
120
+ "l"(gmem_ptr),
121
+ "n"(sizeof(TS)),
122
+ "r"(src_size));
123
+ #else
124
+ CUTE_INVALID_CONTROL_PATH("Support for cp.async instructions has not been enabled");
125
+ #endif
126
+ }
127
+ };
128
+
129
+ /// Copy via cp.async with caching at global level
130
+ template <class TS, class TD = TS>
131
+ struct SM80_CP_ASYNC_CACHEGLOBAL_ZFILL
132
+ {
133
+ using SRegisters = TS[1];
134
+ using DRegisters = TD[1];
135
+
136
+ static_assert(sizeof(TS) == sizeof(TD), "cp.async requires sizeof(src_value_type) == sizeof(dst_value_type)");
137
+ static_assert(sizeof(TS) == 16, "cp.async sizeof(TS) is not supported");
138
+
139
+ CUTE_HOST_DEVICE static void
140
+ copy(TS const& gmem_src,
141
+ TD & smem_dst,
142
+ bool pred)
143
+ {
144
+ #if defined(CUTE_ARCH_CP_ASYNC_SM80_ENABLED)
145
+ TS const* gmem_ptr = &gmem_src;
146
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_dst);
147
+ int src_size = pred ? sizeof(TS) : 0;
148
+ asm volatile("cp.async.cg.shared.global.L2::128B [%0], [%1], %2, %3;\n"
149
+ :: "r"(smem_int_ptr),
150
+ "l"(gmem_ptr),
151
+ "n"(sizeof(TS)),
152
+ "r"(src_size));
153
+ #else
154
+ CUTE_INVALID_CONTROL_PATH("Support for cp.async instructions has not been enabled");
155
+ #endif
156
+ }
157
+ };
158
+
159
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
160
+
161
+ /// Establishes an ordering w.r.t previously issued cp.async instructions. Does not block.
162
+ CUTE_HOST_DEVICE
163
+ void
164
+ cp_async_fence()
165
+ {
166
+ #if defined(CUTE_ARCH_CP_ASYNC_SM80_ENABLED)
167
+ asm volatile("cp.async.commit_group;\n" ::);
168
+ #endif
169
+ }
170
+
171
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
172
+
173
+ /// Blocks until all but N previous cp.async.commit_group operations have committed.
174
+ template <int N>
175
+ CUTE_HOST_DEVICE
176
+ void
177
+ cp_async_wait()
178
+ {
179
+ #if defined(CUTE_ARCH_CP_ASYNC_SM80_ENABLED)
180
+ if constexpr (N == 0) {
181
+ asm volatile("cp.async.wait_all;\n" ::);
182
+ } else {
183
+ asm volatile("cp.async.wait_group %0;\n" :: "n"(N));
184
+ }
185
+ #endif
186
+ }
187
+
188
+ template <int N>
189
+ CUTE_HOST_DEVICE
190
+ void
191
+ cp_async_wait(Int<N>)
192
+ {
193
+ return cp_async_wait<N>();
194
+ }
195
+
196
+ /////////////////////////////////////////////////////////////////////////////////////////////////
197
+
198
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm90.hpp ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp> // CUTE_HOST_DEVICE
34
+ #include <cute/arch/config.hpp> // CUTE_ARCH_TMA_SMxx_ENABLED
35
+ #include <cute/arch/copy.hpp>
36
+
37
+ namespace cute
38
+ {
39
+
40
+ struct SM90_U32x1_STSM_N
41
+ {
42
+ using SRegisters = uint32_t[1];
43
+ using DRegisters = uint128_t[1];
44
+
45
+ CUTE_HOST_DEVICE static void
46
+ copy(uint32_t const& src,
47
+ uint128_t & smem_dst)
48
+ {
49
+ #if defined(CUTE_ARCH_STSM_SM90_ENABLED)
50
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_dst);
51
+ asm volatile ("stmatrix.sync.aligned.x1.m8n8.shared.b16 [%0], {%1};\n"
52
+ :: "r"(smem_int_ptr),
53
+ "r"(src));
54
+ #else
55
+ CUTE_INVALID_CONTROL_PATH("Trying to use stmatrix without CUTE_ARCH_STSM_SM90_ENABLED.");
56
+ #endif
57
+ }
58
+ };
59
+
60
+ struct SM90_U32x2_STSM_N
61
+ {
62
+ using SRegisters = uint32_t[2];
63
+ using DRegisters = uint128_t[1];
64
+
65
+ CUTE_HOST_DEVICE static void
66
+ copy(uint32_t const& src0, uint32_t const& src1,
67
+ uint128_t& smem_dst)
68
+ {
69
+ #if defined(CUTE_ARCH_STSM_SM90_ENABLED)
70
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_dst);
71
+ asm volatile ("stmatrix.sync.aligned.x2.m8n8.shared.b16 [%0], {%1, %2};\n"
72
+ :: "r"(smem_int_ptr),
73
+ "r"(src0), "r"(src1));
74
+ #else
75
+ CUTE_INVALID_CONTROL_PATH("Trying to use stmatrix without CUTE_ARCH_STSM_SM90_ENABLED.");
76
+ #endif
77
+ }
78
+ };
79
+
80
+ struct SM90_U32x4_STSM_N
81
+ {
82
+ using SRegisters = uint32_t[4];
83
+ using DRegisters = uint128_t[1];
84
+
85
+ CUTE_HOST_DEVICE static void
86
+ copy(uint32_t const& src0, uint32_t const& src1, uint32_t const& src2, uint32_t const& src3,
87
+ uint128_t& smem_dst)
88
+ {
89
+ #if defined(CUTE_ARCH_STSM_SM90_ENABLED)
90
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_dst);
91
+ asm volatile ("stmatrix.sync.aligned.x4.m8n8.shared.b16 [%0], {%1, %2, %3, %4};\n"
92
+ :: "r"(smem_int_ptr),
93
+ "r"(src0), "r"(src1), "r"(src2), "r"(src3));
94
+ #else
95
+ CUTE_INVALID_CONTROL_PATH("Trying to use stmatrix without CUTE_ARCH_STSM_SM90_ENABLED.");
96
+ #endif
97
+ }
98
+ };
99
+
100
+ struct SM90_U16x2_STSM_T
101
+ {
102
+ using SRegisters = uint32_t[1];
103
+ using DRegisters = uint128_t[1];
104
+
105
+ CUTE_HOST_DEVICE static void
106
+ copy(uint32_t const& src,
107
+ uint128_t& smem_dst)
108
+ {
109
+ #if defined(CUTE_ARCH_STSM_SM90_ENABLED)
110
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_dst);
111
+ asm volatile ("stmatrix.sync.aligned.x1.trans.m8n8.shared.b16 [%0], {%1};\n"
112
+ :: "r"(smem_int_ptr),
113
+ "r"(src));
114
+ #else
115
+ CUTE_INVALID_CONTROL_PATH("Trying to use stmatrix without CUTE_ARCH_STSM_SM90_ENABLED.");
116
+ #endif
117
+ }
118
+ };
119
+
120
+ struct SM90_U16x4_STSM_T
121
+ {
122
+ using SRegisters = uint32_t[2];
123
+ using DRegisters = uint128_t[1];
124
+
125
+ CUTE_HOST_DEVICE static void
126
+ copy(uint32_t const& src0, uint32_t const& src1,
127
+ uint128_t& smem_dst)
128
+ {
129
+ #if defined(CUTE_ARCH_STSM_SM90_ENABLED)
130
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_dst);
131
+ asm volatile ("stmatrix.sync.aligned.x2.trans.m8n8.shared.b16 [%0], {%1, %2};\n"
132
+ :: "r"(smem_int_ptr),
133
+ "r"(src0), "r"(src1));
134
+ #else
135
+ CUTE_INVALID_CONTROL_PATH("Trying to use stmatrix without CUTE_ARCH_STSM_SM90_ENABLED.");
136
+ #endif
137
+ }
138
+ };
139
+
140
+ struct SM90_U16x8_STSM_T
141
+ {
142
+ using SRegisters = uint32_t[4];
143
+ using DRegisters = uint128_t[1];
144
+
145
+ CUTE_HOST_DEVICE static void
146
+ copy(uint32_t const& src0, uint32_t const& src1, uint32_t const& src2, uint32_t const& src3,
147
+ uint128_t& smem_dst)
148
+ {
149
+ #if defined(CUTE_ARCH_STSM_SM90_ENABLED)
150
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_dst);
151
+ asm volatile ("stmatrix.sync.aligned.x4.trans.m8n8.shared.b16 [%0], {%1, %2, %3, %4};\n"
152
+ :: "r"(smem_int_ptr),
153
+ "r"(src0), "r"(src1), "r"(src2), "r"(src3));
154
+ #else
155
+ CUTE_INVALID_CONTROL_PATH("Trying to use stmatrix without CUTE_ARCH_STSM_SM90_ENABLED.");
156
+ #endif
157
+ }
158
+ };
159
+
160
+ //
161
+ // Legacy STSM interfaces that aren't very useful
162
+ //
163
+
164
+ template <class T>
165
+ CUTE_HOST_DEVICE
166
+ void
167
+ copy_stsm(T const* const rmem_ptr,
168
+ uint128_t* const smem_ptr)
169
+ {
170
+ uint32_t const* reg_ptr = reinterpret_cast<uint32_t const*>(rmem_ptr);
171
+
172
+ // if constexpr
173
+ if (sizeof(T) == 4) {
174
+ SM90_U32x1_STSM_N::copy(reg_ptr[0], smem_ptr[0]);
175
+ }
176
+ else if (sizeof(T) == 8) {
177
+ SM90_U32x2_STSM_N::copy(reg_ptr[0], reg_ptr[1], smem_ptr[0]);
178
+ }
179
+ else if (sizeof(T) == 16) {
180
+ SM90_U32x4_STSM_N::copy(reg_ptr[0], reg_ptr[1], reg_ptr[2], reg_ptr[3], smem_ptr[0]);
181
+ }
182
+ else {
183
+ static_assert(sizeof(T) == 4 || sizeof(T) == 8 || sizeof(T) == 16, "sizeof(T) is not supported");
184
+ }
185
+ }
186
+
187
+ template <class T>
188
+ CUTE_HOST_DEVICE
189
+ void
190
+ copy_stsm_trans(T const* const rmem_ptr,
191
+ uint128_t* const smem_ptr)
192
+ {
193
+ uint32_t const* reg_ptr = reinterpret_cast<uint32_t const*>(rmem_ptr);
194
+
195
+ // if constexpr
196
+ if (sizeof(T) == 4) {
197
+ SM90_U16x2_STSM_T::copy(reg_ptr[0], smem_ptr[0]);
198
+ }
199
+ else if (sizeof(T) == 8) {
200
+ SM90_U16x4_STSM_T::copy(reg_ptr[0], reg_ptr[1], smem_ptr[0]);
201
+ }
202
+ else if (sizeof(T) == 16) {
203
+ SM90_U16x8_STSM_T::copy(reg_ptr[0], reg_ptr[1], reg_ptr[2], reg_ptr[3], smem_ptr[0]);
204
+ }
205
+ else {
206
+ static_assert(sizeof(T) == 4 || sizeof(T) == 8 || sizeof(T) == 16, "sizeof(T) is not supported");
207
+ }
208
+ }
209
+
210
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
211
+
212
+ } // end namespace cute
213
+
214
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
215
+
216
+ #include <cute/arch/copy_sm90_desc.hpp>
217
+ #include <cute/arch/copy_sm90_tma.hpp>
218
+
219
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm90_desc.hpp ADDED
@@ -0,0 +1,475 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include "cutlass/numeric_types.h"
34
+
35
+ #if !defined(__CUDACC_RTC__)
36
+ #include <cuda.h>
37
+ #include <cinttypes>
38
+ #endif
39
+
40
+ #include <cute/config.hpp>
41
+
42
+ #include <cute/arch/util.hpp> // cute::cast_smem_ptr_to_uint
43
+ #include <cute/arch/config.hpp> // CUTE_ARCH_TMA_SMxx_ENABLED
44
+ #include <cute/arch/copy.hpp>
45
+ #include <cute/arch/copy_sm90.hpp>
46
+
47
+ #include <cute/container/alignment.hpp>
48
+ #include <cute/container/bit_field.hpp>
49
+ #include <cute/container/array.hpp>
50
+ #include <cute/numeric/numeric_types.hpp>
51
+
52
+ namespace cute
53
+ {
54
+
55
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
56
+ /// Barriers are 64-bit of user-managed information used in broadly two types syncronization patterns
57
+ /// 1) arrive/wait on threads (usage: cp.async and warp-specialized kernels)
58
+ /// 2) transaction-based (usage: TMA transaction where a CTA issues one transaction)
59
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
60
+
61
+ // Initialize barrier present in shared memory
62
+ CUTE_HOST_DEVICE
63
+ void
64
+ initialize_barrier(uint64_t& smem_barrier, // 64 bits user-manged barrier in smem
65
+ int thread_count = 1) // Thread count expected to arrive/wait on this barrier
66
+ {
67
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
68
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_barrier);
69
+ asm volatile ("mbarrier.init.shared::cta.b64 [%0], %1;\n"
70
+ :: "r"(smem_int_ptr),
71
+ "r"(thread_count));
72
+ #endif
73
+ }
74
+
75
+ // Set the number of bytes transfered per transaction and perform an arrive operation as well
76
+ CUTE_HOST_DEVICE
77
+ void
78
+ set_barrier_transaction_bytes(uint64_t& smem_barrier, // 64 bits user-manged barrier in smem
79
+ uint32_t bytes) // Number of bytes transfered by per TMA transaction
80
+ {
81
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
82
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_barrier);
83
+ asm volatile ("mbarrier.arrive.expect_tx.shared::cta.b64 _, [%0], %1;\n"
84
+ :: "r"(smem_int_ptr),
85
+ "r"(bytes));
86
+ #endif
87
+ }
88
+
89
+ // Barrier wait
90
+ CUTE_HOST_DEVICE
91
+ void
92
+ wait_barrier(uint64_t& smem_barrier, // 64 bits user-manged barrier in smem
93
+ int phase_bit) // Current phase bit the barrier waiting to flip
94
+ {
95
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
96
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_barrier);
97
+ asm volatile(
98
+ "{\n"
99
+ ".reg .pred P1;\n"
100
+ "LAB_WAIT:\n"
101
+ "mbarrier.try_wait.parity.shared::cta.b64 P1, [%0], %1;\n"
102
+ "@P1 bra DONE;\n"
103
+ "bra LAB_WAIT;\n"
104
+ "DONE:\n"
105
+ "}\n"
106
+ :: "r"(smem_int_ptr),
107
+ "r"(phase_bit));
108
+
109
+ #endif
110
+ }
111
+
112
+ // Barrier arrive
113
+ CUTE_HOST_DEVICE
114
+ void
115
+ arrive_barrier(uint64_t& smem_barrier) // 64 bits user-manged barrier in smem
116
+ {
117
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
118
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(&smem_barrier);
119
+ asm volatile(
120
+ "{\n"
121
+ ".reg .b64 state; \n"
122
+ "mbarrier.arrive.shared::cta.b64 state, [%0];\n"
123
+ "}\n"
124
+ :: "r"(smem_int_ptr));
125
+ #endif
126
+ }
127
+
128
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
129
+ // TMA Descriptor and utilities
130
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
131
+
132
+ namespace TMA {
133
+
134
+ enum class SmemSwizzleBits : uint8_t {
135
+ DISABLE = 0,
136
+ B32 = 1,
137
+ B64 = 2,
138
+ B128 = 3,
139
+ };
140
+
141
+ enum class SmemSwizzleBase : uint8_t {
142
+ SWIZZLE_BASE_16B = 0,
143
+
144
+ SWIZZLE_BASE_32B = 1,
145
+ SWIZZLE_BASE_32B_FLIP_8B = 2,
146
+ SWIZZLE_BASE_64B = 3,
147
+
148
+ };
149
+
150
+ enum class OOBFill : uint8_t {
151
+ ZERO = 0,
152
+ CONSTANT = 1,
153
+ };
154
+
155
+ CUTE_HOST_DEVICE char const* to_string(OOBFill const& t) {
156
+ switch (t) {
157
+ case OOBFill::ZERO: return "ZERO";
158
+ case OOBFill::CONSTANT: return "CONSTANT";
159
+ }
160
+ return nullptr;
161
+ }
162
+
163
+ enum class L2Promotion : uint8_t {
164
+ DISABLE = 0,
165
+ B64 = 1,
166
+ B128 = 2,
167
+ B256 = 3,
168
+ };
169
+
170
+ CUTE_HOST_DEVICE char const* to_string(L2Promotion const& t) {
171
+ switch (t) {
172
+ case L2Promotion::DISABLE: return "DISABLE";
173
+ case L2Promotion::B64: return "B64";
174
+ case L2Promotion::B128: return "B128";
175
+ case L2Promotion::B256: return "B256";
176
+ }
177
+ return nullptr;
178
+ }
179
+
180
+ // Aux parameters which are independent with the problem size
181
+ struct DescriptorAuxParams {
182
+ OOBFill oobfill_ = OOBFill::ZERO;
183
+ L2Promotion l2promo_ = L2Promotion::DISABLE;
184
+ };
185
+
186
+ enum class CacheHintSm90 : uint64_t {
187
+ EVICT_NORMAL = 0x1000000000000000,
188
+ EVICT_FIRST = 0x12F0000000000000,
189
+ EVICT_LAST = 0x14F0000000000000,
190
+ };
191
+
192
+
193
+ enum class CacheHintSm100 : uint64_t {
194
+ EVICT_NORMAL = 0x1000000000000000,
195
+ EVICT_FIRST = 0x12F0000000000000,
196
+ EVICT_LAST = 0x14F0000000000000,
197
+ };
198
+
199
+
200
+ #if (__CUDACC_VER_MAJOR__ >= 12)
201
+
202
+ #if !defined(__CUDACC_RTC__)
203
+ /// @return The TMA descriptor datatype enum corresponding to T.
204
+ template <class T>
205
+ inline CUtensorMapDataType
206
+ to_CUtensorMapDataType() {
207
+ if constexpr (is_same_v<T, int8_t>) { return CU_TENSOR_MAP_DATA_TYPE_UINT8; } else
208
+ if constexpr (is_same_v<T, uint8_t>) { return CU_TENSOR_MAP_DATA_TYPE_UINT8; } else
209
+ if constexpr (is_same_v<T, float_e4m3_t>) { return CU_TENSOR_MAP_DATA_TYPE_UINT8; } else
210
+ if constexpr (is_same_v<T, float_e5m2_t>) { return CU_TENSOR_MAP_DATA_TYPE_UINT8; } else
211
+ if constexpr (is_same_v<T, float_ue8m0_t>) { return CU_TENSOR_MAP_DATA_TYPE_UINT8; } else
212
+ if constexpr (is_same_v<T, type_erased_dynamic_float8_t>) { return CU_TENSOR_MAP_DATA_TYPE_UINT8;} else
213
+ if constexpr (is_same_v<T, uint16_t>) { return CU_TENSOR_MAP_DATA_TYPE_UINT16; } else
214
+ if constexpr (is_same_v<T, uint32_t>) { return CU_TENSOR_MAP_DATA_TYPE_UINT32; } else
215
+ if constexpr (is_same_v<T, uint64_t>) { return CU_TENSOR_MAP_DATA_TYPE_UINT64; } else
216
+ if constexpr (is_same_v<T, int32_t>) { return CU_TENSOR_MAP_DATA_TYPE_INT32; } else
217
+ if constexpr (is_same_v<T, int64_t>) { return CU_TENSOR_MAP_DATA_TYPE_INT64; } else
218
+ if constexpr (is_same_v<T, half_t>) { return CU_TENSOR_MAP_DATA_TYPE_FLOAT16; } else
219
+ if constexpr (is_same_v<T, float>) { return CU_TENSOR_MAP_DATA_TYPE_FLOAT32; } else
220
+ if constexpr (is_same_v<T, double>) { return CU_TENSOR_MAP_DATA_TYPE_FLOAT64; } else
221
+ if constexpr (is_same_v<T, bfloat16_t>) { return CU_TENSOR_MAP_DATA_TYPE_BFLOAT16; } else
222
+ if constexpr (is_same_v<T, tfloat32_t>) { return CU_TENSOR_MAP_DATA_TYPE_TFLOAT32; } else
223
+ #if ((__CUDACC_VER_MAJOR__ > 12) || ((__CUDACC_VER_MAJOR__ == 12) && (__CUDACC_VER_MINOR__ > 6)))
224
+ if constexpr (is_same_v<T, float_e2m1_t>) { return CU_TENSOR_MAP_DATA_TYPE_16U4_ALIGN8B; } else
225
+ if constexpr (is_same_v<T, float_e2m3_t>) { return CU_TENSOR_MAP_DATA_TYPE_16U6_ALIGN16B; } else
226
+ if constexpr (is_same_v<T, float_e3m2_t>) { return CU_TENSOR_MAP_DATA_TYPE_16U6_ALIGN16B; } else
227
+ if constexpr (is_same_v<T, type_erased_dynamic_float4_t>) { return CU_TENSOR_MAP_DATA_TYPE_16U4_ALIGN8B; } else
228
+ if constexpr (is_same_v<T, type_erased_dynamic_float6_t>) { return CU_TENSOR_MAP_DATA_TYPE_16U6_ALIGN16B; } else
229
+ if constexpr (is_same_v<T, detail::float_e2m1_unpacksmem_t>) { return CU_TENSOR_MAP_DATA_TYPE_16U4_ALIGN16B; } else
230
+ if constexpr (is_same_v<T, detail::float_e2m3_unpacksmem_t>) { return CU_TENSOR_MAP_DATA_TYPE_16U6_ALIGN16B; } else
231
+ if constexpr (is_same_v<T, detail::float_e3m2_unpacksmem_t>) { return CU_TENSOR_MAP_DATA_TYPE_16U6_ALIGN16B; } else
232
+ if constexpr (is_same_v<T, detail::type_erased_dynamic_float4_unpacksmem_t>) { return CU_TENSOR_MAP_DATA_TYPE_16U4_ALIGN16B; } else
233
+ if constexpr (is_same_v<T, detail::type_erased_dynamic_float6_unpacksmem_t>) { return CU_TENSOR_MAP_DATA_TYPE_16U6_ALIGN16B; } else
234
+ #endif
235
+
236
+ { static_assert(sizeof(T) < 0, "Unknown TMA Format!"); }
237
+ }
238
+
239
+ inline CUtensorMapSwizzle
240
+ to_CUtensorMapSwizzle(SmemSwizzleBits const& t, SmemSwizzleBase const& b) {
241
+ switch (t) {
242
+ default: assert(false && "Unsupported pair of SmemSwizzleBits and SmemSwizzleBase!");
243
+ case SmemSwizzleBits::DISABLE:
244
+ assert((b == SmemSwizzleBase::SWIZZLE_BASE_16B) && "Expected 16B swizzle base for 0B swizzle bits.");
245
+ return CU_TENSOR_MAP_SWIZZLE_NONE;
246
+ case SmemSwizzleBits::B32:
247
+ assert((b == SmemSwizzleBase::SWIZZLE_BASE_16B) && "Expected 16B swizzle base for 32B swizzle bits.");
248
+ return CU_TENSOR_MAP_SWIZZLE_32B;
249
+ case SmemSwizzleBits::B64:
250
+ assert((b == SmemSwizzleBase::SWIZZLE_BASE_16B) && "Expected 16B swizzle base for 64B swizzle bits.");
251
+ return CU_TENSOR_MAP_SWIZZLE_64B;
252
+ case SmemSwizzleBits::B128:
253
+ switch (b) {
254
+ default: assert(false && "Unsupported pair of SmemSwizzleBits and SmemSwizzleBase!");
255
+ case SmemSwizzleBase::SWIZZLE_BASE_16B: return CU_TENSOR_MAP_SWIZZLE_128B;
256
+
257
+ #if ((__CUDACC_VER_MAJOR__ > 12) || ((__CUDACC_VER_MAJOR__ == 12) && (__CUDACC_VER_MINOR__ > 6)))
258
+ case SmemSwizzleBase::SWIZZLE_BASE_32B: return CU_TENSOR_MAP_SWIZZLE_128B_ATOM_32B;
259
+ case SmemSwizzleBase::SWIZZLE_BASE_64B: return CU_TENSOR_MAP_SWIZZLE_128B_ATOM_64B;
260
+ #endif
261
+ }
262
+ }
263
+ }
264
+
265
+ inline CUtensorMapFloatOOBfill
266
+ to_CUtensorMapFloatOOBfill(OOBFill const& t) {
267
+ switch(t) {
268
+ default: assert(false && "Unknown OOBFill!");
269
+ case OOBFill::ZERO: return CU_TENSOR_MAP_FLOAT_OOB_FILL_NONE;
270
+ case OOBFill::CONSTANT: return CU_TENSOR_MAP_FLOAT_OOB_FILL_NAN_REQUEST_ZERO_FMA;
271
+ }
272
+ }
273
+
274
+ inline CUtensorMapL2promotion
275
+ to_CUtensorMapL2promotion(L2Promotion const& t) {
276
+ switch(t) {
277
+ default: assert(false && "Unknown L2Promotion!");
278
+ case L2Promotion::DISABLE: return CU_TENSOR_MAP_L2_PROMOTION_NONE;
279
+ case L2Promotion::B64: return CU_TENSOR_MAP_L2_PROMOTION_L2_64B;
280
+ case L2Promotion::B128: return CU_TENSOR_MAP_L2_PROMOTION_L2_128B;
281
+ case L2Promotion::B256: return CU_TENSOR_MAP_L2_PROMOTION_L2_256B;
282
+ }
283
+ }
284
+
285
+ #endif // !defined(__CUDACC_RTC__)
286
+
287
+ #endif // (__CUDACC_VER_MAJOR__ >= 12)
288
+
289
+ } // end namespace TMA
290
+
291
+ #if (__CUDACC_VER_MAJOR__ >= 12) && !defined(__CUDACC_RTC__)
292
+ using TmaDescriptor = CUtensorMap;
293
+ using Im2ColTmaDescriptor = CUtensorMap;
294
+ #else
295
+ using TmaDescriptor = struct alignas(64) { char bytes[128]; };
296
+ using Im2ColTmaDescriptor = struct alignas(64) { char bytes[128]; };
297
+ #endif
298
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
299
+ /// Initiates a TensorMap Prefetch
300
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
301
+
302
+ CUTE_HOST_DEVICE
303
+ void
304
+ prefetch_tma_descriptor(TmaDescriptor const* desc_ptr)
305
+ {
306
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
307
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
308
+ // Prefetch TMA Descriptor using generic addressing (i.e. no specific state space: const or param)
309
+ asm volatile (
310
+ "prefetch.tensormap [%0];"
311
+ :
312
+ : "l"(gmem_int_desc)
313
+ : "memory");
314
+ #else
315
+ CUTE_INVALID_CONTROL_PATH("Trying to use TMA Descriptor Prefetch without CUTE_ARCH_TMA_SM90_ENABLED.");
316
+ #endif
317
+ }
318
+
319
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
320
+ /// Perform a TensorMap modification (by each field)
321
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
322
+
323
+ // Replace tensor pointer directly in GMEM
324
+ CUTE_HOST_DEVICE
325
+ void
326
+ tma_descriptor_replace_addr_in_global_mem(TmaDescriptor const* desc_ptr,
327
+ void const* const new_tensor_ptr)
328
+ {
329
+ #if defined(CUTE_ARCH_DEVICE_MODIFIABLE_TMA_SM90_ENABLED)
330
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
331
+ uint64_t const new_desc_addr = reinterpret_cast<uint64_t>(new_tensor_ptr);
332
+ asm volatile (
333
+ "tensormap.replace.tile.global_address.global.b1024.b64 [%0], %1;"
334
+ :: "l"(gmem_int_desc), "l"(new_desc_addr));
335
+ #else
336
+ CUTE_INVALID_CONTROL_PATH("Using TMA Descriptor modification without CUTE_ARCH_DEVICE_MODIFIABLE_TMA_SM90_ENABLED and CUDA 12.3");
337
+ #endif
338
+ }
339
+
340
+ // Replace tensor pointer by bringing the tensormap from GMEM into the shared memory
341
+ CUTE_HOST_DEVICE
342
+ void
343
+ tma_descriptor_replace_addr_in_shared_mem(TmaDescriptor& smem_desc,
344
+ void const* const new_tensor_ptr)
345
+ {
346
+ #if defined(CUTE_ARCH_DEVICE_MODIFIABLE_TMA_SM90_ENABLED)
347
+ uint32_t smem_int_desc = cast_smem_ptr_to_uint(&smem_desc);
348
+ uint64_t const new_desc_addr = reinterpret_cast<uint64_t>(new_tensor_ptr);
349
+ asm volatile (
350
+ "tensormap.replace.tile.global_address.shared::cta.b1024.b64 [%0], %1;"
351
+ :: "r"(smem_int_desc), "l"(new_desc_addr));
352
+ #else
353
+ CUTE_INVALID_CONTROL_PATH("Using TMA Descriptor modification without CUTE_ARCH_DEVICE_MODIFIABLE_TMA_SM90_ENABLED and CUDA 12.3");
354
+ #endif
355
+ }
356
+
357
+ // Replace tensor dims and strides for GEMMs by bringing the tensormap from GMEM into the shared memory
358
+ CUTE_HOST_DEVICE
359
+ void
360
+ tma_descriptor_replace_dims_strides_in_shared_mem(TmaDescriptor & smem_desc,
361
+ cute::array<uint32_t, 5> const& prob_shape,
362
+ cute::array<uint64_t, 5> const& prob_stride)
363
+ {
364
+ #if defined(CUTE_ARCH_DEVICE_MODIFIABLE_TMA_SM90_ENABLED)
365
+ uint32_t smem_int_desc = cast_smem_ptr_to_uint(&smem_desc);
366
+ uint64_t const smem_int64_desc = 0;
367
+ asm volatile (
368
+ "cvt.u64.u32 %0, %1;"
369
+ :: "l"(smem_int64_desc), "r"(smem_int_desc));
370
+ asm volatile (
371
+ "tensormap.replace.tile.global_dim.shared::cta.b1024.b32 [%0], 0, %1;"
372
+ :: "l"(smem_int64_desc), "r"(prob_shape[0]));
373
+ asm volatile (
374
+ "tensormap.replace.tile.global_dim.shared::cta.b1024.b32 [%0], 1, %1;"
375
+ :: "l"(smem_int64_desc), "r"(prob_shape[1]));
376
+ asm volatile (
377
+ "tensormap.replace.tile.global_dim.shared::cta.b1024.b32 [%0], 2, %1;"
378
+ :: "l"(smem_int64_desc), "r"(prob_shape[2]));
379
+ asm volatile (
380
+ "tensormap.replace.tile.global_dim.shared::cta.b1024.b32 [%0], 3, %1;"
381
+ :: "l"(smem_int64_desc), "r"(prob_shape[3]));
382
+ asm volatile (
383
+ "tensormap.replace.tile.global_dim.shared::cta.b1024.b32 [%0], 4, %1;"
384
+ :: "l"(smem_int64_desc), "r"(prob_shape[4]));
385
+ // Strides must be a multiple of 16. Also, stride for the intermost dimension is implicitly 1
386
+ #if ((__CUDACC_VER_MAJOR__ > 12) || ((__CUDACC_VER_MAJOR__ == 12) && (__CUDACC_VER_MINOR__ >= 5)))
387
+ asm volatile (
388
+ "tensormap.replace.tile.global_stride.shared::cta.b1024.b64 [%0], 0, %1;"
389
+ :: "l"(smem_int64_desc), "l"(prob_stride[1]));
390
+ asm volatile (
391
+ "tensormap.replace.tile.global_stride.shared::cta.b1024.b64 [%0], 1, %1;"
392
+ :: "l"(smem_int64_desc), "l"(prob_stride[2]));
393
+ asm volatile (
394
+ "tensormap.replace.tile.global_stride.shared::cta.b1024.b64 [%0], 2, %1;"
395
+ :: "l"(smem_int64_desc), "l"(prob_stride[3]));
396
+ asm volatile (
397
+ "tensormap.replace.tile.global_stride.shared::cta.b1024.b64 [%0], 3, %1;"
398
+ :: "l"(smem_int64_desc), "l"(prob_stride[4]));
399
+ #else
400
+ // 4 LSBs are not included
401
+ asm volatile (
402
+ "tensormap.replace.tile.global_stride.shared::cta.b1024.b64 [%0], 0, %1;"
403
+ :: "l"(smem_int64_desc), "l"(prob_stride[1] >> 4));
404
+ asm volatile (
405
+ "tensormap.replace.tile.global_stride.shared::cta.b1024.b64 [%0], 1, %1;"
406
+ :: "l"(smem_int64_desc), "l"(prob_stride[2] >> 4));
407
+ asm volatile (
408
+ "tensormap.replace.tile.global_stride.shared::cta.b1024.b64 [%0], 2, %1;"
409
+ :: "l"(smem_int64_desc), "l"(prob_stride[3] >> 4));
410
+ asm volatile (
411
+ "tensormap.replace.tile.global_stride.shared::cta.b1024.b64 [%0], 3, %1;"
412
+ :: "l"(smem_int64_desc), "l"(prob_stride[4] >> 4));
413
+ #endif
414
+ #else
415
+ CUTE_INVALID_CONTROL_PATH("Using TMA Descriptor modification without CUTE_ARCH_DEVICE_MODIFIABLE_TMA_SM90_ENABLED and CUDA 12.3");
416
+ #endif
417
+ }
418
+
419
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
420
+ /// Perform a fused copy and fence operation (needed when modifying tensormap in shared memory)
421
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
422
+
423
+ CUTE_HOST_DEVICE
424
+ void
425
+ tma_descriptor_cp_fence_release(TmaDescriptor const* gmem_desc_ptr, TmaDescriptor& smem_desc)
426
+ {
427
+ #if defined(CUTE_ARCH_DEVICE_MODIFIABLE_TMA_SM90_ENABLED)
428
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(gmem_desc_ptr);
429
+ uint32_t smem_int_desc = cast_smem_ptr_to_uint(&smem_desc);
430
+ asm volatile (
431
+ "tensormap.cp_fenceproxy.global.shared::cta.tensormap::generic.release.gpu.sync.aligned [%0], [%1], 128;"
432
+ :: "l"(gmem_int_desc), "r"(smem_int_desc));
433
+ #else
434
+ CUTE_INVALID_CONTROL_PATH("Using TMA Descriptor modification without CUTE_ARCH_DEVICE_MODIFIABLE_TMA_SM90_ENABLED and CUDA 12.3");
435
+ #endif
436
+ }
437
+
438
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
439
+ /// Perform a release fence operation (needed when modifying tensormap directly in GMEM)
440
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
441
+
442
+ CUTE_HOST_DEVICE
443
+ void
444
+ tma_descriptor_fence_release()
445
+ {
446
+ #if defined(CUTE_ARCH_DEVICE_MODIFIABLE_TMA_SM90_ENABLED)
447
+ asm volatile ("fence.proxy.tensormap::generic.release.gpu;");
448
+ #else
449
+ CUTE_INVALID_CONTROL_PATH("Using TMA Descriptor modification without CUTE_ARCH_DEVICE_MODIFIABLE_TMA_SM90_ENABLED and CUDA 12.3");
450
+ #endif
451
+ }
452
+
453
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
454
+ /// Perform a acquire fence operation
455
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
456
+
457
+ CUTE_HOST_DEVICE
458
+ void
459
+ tma_descriptor_fence_acquire(TmaDescriptor const* desc_ptr)
460
+ {
461
+ #if defined(CUTE_ARCH_DEVICE_MODIFIABLE_TMA_SM90_ENABLED)
462
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
463
+ asm volatile (
464
+ "fence.proxy.tensormap::generic.acquire.gpu [%0], 128;"
465
+ :
466
+ : "l"(gmem_int_desc)
467
+ : "memory");
468
+ #else
469
+ CUTE_INVALID_CONTROL_PATH("Using TMA Descriptor modification without CUTE_ARCH_DEVICE_MODIFIABLE_TMA_SM90_ENABLED and CUDA 12.3");
470
+ #endif
471
+ }
472
+
473
+ ///////////////////////////////////////////////////////////////////////////////
474
+
475
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/copy_sm90_tma.hpp ADDED
@@ -0,0 +1,1496 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp>
34
+
35
+ #include <cute/arch/config.hpp> // CUTE_ARCH_TMA_SMxx_ENABLED
36
+ #include <cute/arch/copy.hpp>
37
+ #include <cute/arch/copy_sm90.hpp>
38
+ #include "cutlass/arch/synclog.hpp"
39
+
40
+ namespace cute
41
+ {
42
+
43
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
44
+ /// TMA_LOAD : Initiates a TMA copy from global memory to shared memory
45
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
46
+
47
+ struct SM90_TMA_LOAD_1D
48
+ {
49
+ CUTE_HOST_DEVICE static void
50
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
51
+ void * smem_ptr,
52
+ int32_t const& crd0)
53
+ {
54
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
55
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
56
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
57
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
58
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
59
+ #if defined(CUTE_ARCH_TMA_SM120_ENABLED)
60
+ asm volatile (
61
+ "cp.async.bulk.tensor.1d.shared::cta.global.mbarrier::complete_tx::bytes.L2::cache_hint"
62
+ " [%0], [%1, {%3}], [%2], %4;"
63
+ :
64
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
65
+ "r"(crd0), "l"(cache_hint)
66
+ : "memory");
67
+ #else
68
+ asm volatile (
69
+ "cp.async.bulk.tensor.1d.shared::cluster.global.mbarrier::complete_tx::bytes.L2::cache_hint"
70
+ " [%0], [%1, {%3}], [%2], %4;"
71
+ :
72
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
73
+ "r"(crd0), "l"(cache_hint)
74
+ : "memory");
75
+ #endif
76
+ #else
77
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
78
+ #endif
79
+ }
80
+
81
+ struct PREFETCH
82
+ {
83
+ CUTE_HOST_DEVICE static void
84
+ copy(void const* desc_ptr,
85
+ int32_t const& crd0)
86
+ {
87
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
88
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
89
+ asm volatile (
90
+ "cp.async.bulk.prefetch.tensor.1d.L2.global"
91
+ " [%0, {%1}];"
92
+ :
93
+ : "l"(gmem_int_desc),
94
+ "r"(crd0)
95
+ : "memory");
96
+ #else
97
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
98
+ #endif
99
+ }
100
+ };
101
+ };
102
+
103
+ struct SM90_TMA_LOAD_2D
104
+ {
105
+ CUTE_HOST_DEVICE static void
106
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
107
+ void * smem_ptr,
108
+ int32_t const& crd0, int32_t const& crd1)
109
+ {
110
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
111
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
112
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
113
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
114
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
115
+ #if defined(CUTE_ARCH_TMA_SM120_ENABLED)
116
+ asm volatile (
117
+ "cp.async.bulk.tensor.2d.shared::cta.global.mbarrier::complete_tx::bytes.L2::cache_hint"
118
+ " [%0], [%1, {%3, %4}], [%2], %5;"
119
+ :
120
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
121
+ "r"(crd0), "r"(crd1), "l"(cache_hint)
122
+ : "memory");
123
+ #else
124
+ asm volatile (
125
+ "cp.async.bulk.tensor.2d.shared::cluster.global.mbarrier::complete_tx::bytes.L2::cache_hint"
126
+ " [%0], [%1, {%3, %4}], [%2], %5;"
127
+ :
128
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
129
+ "r"(crd0), "r"(crd1), "l"(cache_hint)
130
+ : "memory");
131
+ #endif
132
+ #else
133
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
134
+ #endif
135
+ }
136
+
137
+ struct PREFETCH
138
+ {
139
+ CUTE_HOST_DEVICE static void
140
+ copy(void const* desc_ptr,
141
+ int32_t const& crd0, int32_t const& crd1)
142
+ {
143
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
144
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
145
+ asm volatile (
146
+ "cp.async.bulk.prefetch.tensor.2d.L2.global"
147
+ " [%0, {%1, %2}];"
148
+ :
149
+ : "l"(gmem_int_desc),
150
+ "r"(crd0), "r"(crd1)
151
+ : "memory");
152
+ #else
153
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
154
+ #endif
155
+ }
156
+ };
157
+ };
158
+
159
+ struct SM90_TMA_LOAD_3D
160
+ {
161
+ CUTE_HOST_DEVICE static void
162
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
163
+ void * smem_ptr,
164
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2)
165
+ {
166
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
167
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
168
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
169
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
170
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
171
+ #if defined(CUTE_ARCH_TMA_SM120_ENABLED)
172
+ asm volatile (
173
+ "cp.async.bulk.tensor.3d.shared::cta.global.mbarrier::complete_tx::bytes.L2::cache_hint"
174
+ " [%0], [%1, {%3, %4, %5}], [%2], %6;"
175
+ :
176
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
177
+ "r"(crd0), "r"(crd1), "r"(crd2), "l"(cache_hint)
178
+ : "memory");
179
+ #else
180
+ asm volatile (
181
+ "cp.async.bulk.tensor.3d.shared::cluster.global.mbarrier::complete_tx::bytes.L2::cache_hint"
182
+ " [%0], [%1, {%3, %4, %5}], [%2], %6;"
183
+ :
184
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
185
+ "r"(crd0), "r"(crd1), "r"(crd2), "l"(cache_hint)
186
+ : "memory");
187
+ #endif
188
+ #else
189
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
190
+ #endif
191
+ }
192
+
193
+ struct PREFETCH
194
+ {
195
+ CUTE_HOST_DEVICE static void
196
+ copy(void const* desc_ptr,
197
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2)
198
+ {
199
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
200
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
201
+ asm volatile (
202
+ "cp.async.bulk.prefetch.tensor.3d.L2.global"
203
+ " [%0, {%1, %2, %3}];"
204
+ :
205
+ : "l"(gmem_int_desc),
206
+ "r"(crd0), "r"(crd1), "r"(crd2)
207
+ : "memory");
208
+ #else
209
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
210
+ #endif
211
+ }
212
+ };
213
+ };
214
+
215
+ struct SM90_TMA_LOAD_4D
216
+ {
217
+ CUTE_HOST_DEVICE static void
218
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
219
+ void * smem_ptr,
220
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3)
221
+ {
222
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
223
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
224
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
225
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
226
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
227
+ #if defined(CUTE_ARCH_TMA_SM120_ENABLED)
228
+ asm volatile (
229
+ "cp.async.bulk.tensor.4d.shared::cta.global.mbarrier::complete_tx::bytes.L2::cache_hint"
230
+ " [%0], [%1, {%3, %4, %5, %6}], [%2], %7;"
231
+ :
232
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
233
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3), "l"(cache_hint)
234
+ : "memory");
235
+ #else
236
+ asm volatile (
237
+ "cp.async.bulk.tensor.4d.shared::cluster.global.mbarrier::complete_tx::bytes.L2::cache_hint"
238
+ " [%0], [%1, {%3, %4, %5, %6}], [%2], %7;"
239
+ :
240
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
241
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3), "l"(cache_hint)
242
+ : "memory");
243
+ #endif
244
+ #else
245
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
246
+ #endif
247
+ }
248
+
249
+ struct PREFETCH
250
+ {
251
+ CUTE_HOST_DEVICE static void
252
+ copy(void const* desc_ptr,
253
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3)
254
+ {
255
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
256
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
257
+ asm volatile (
258
+ "cp.async.bulk.prefetch.tensor.4d.L2.global"
259
+ " [%0, {%1, %2, %3, %4}];"
260
+ :
261
+ : "l"(gmem_int_desc),
262
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3)
263
+ : "memory");
264
+ #else
265
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
266
+ #endif
267
+ }
268
+ };
269
+ };
270
+
271
+ struct SM90_TMA_LOAD_5D
272
+ {
273
+ CUTE_HOST_DEVICE static void
274
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
275
+ void * smem_ptr,
276
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3, int32_t const& crd4)
277
+ {
278
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
279
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
280
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
281
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
282
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
283
+ #if defined(CUTE_ARCH_TMA_SM120_ENABLED)
284
+ asm volatile (
285
+ "cp.async.bulk.tensor.5d.shared::cta.global.mbarrier::complete_tx::bytes.L2::cache_hint"
286
+ " [%0], [%1, {%3, %4, %5, %6, %7}], [%2], %8;"
287
+ :
288
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
289
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3), "r"(crd4), "l"(cache_hint)
290
+ : "memory");
291
+ #else
292
+ asm volatile (
293
+ "cp.async.bulk.tensor.5d.shared::cluster.global.mbarrier::complete_tx::bytes.L2::cache_hint"
294
+ " [%0], [%1, {%3, %4, %5, %6, %7}], [%2], %8;"
295
+ :
296
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
297
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3), "r"(crd4), "l"(cache_hint)
298
+ : "memory");
299
+ #endif
300
+ #else
301
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
302
+ #endif
303
+ }
304
+
305
+ struct PREFETCH
306
+ {
307
+ CUTE_HOST_DEVICE static void
308
+ copy(void const* desc_ptr,
309
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3, int32_t const& crd4)
310
+ {
311
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
312
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
313
+ asm volatile (
314
+ "cp.async.bulk.prefetch.tensor.5d.L2.global"
315
+ " [%0, {%1, %2, %3, %4, %5}];"
316
+ :
317
+ : "l"(gmem_int_desc),
318
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3), "r"(crd4)
319
+ : "memory");
320
+ #else
321
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
322
+ #endif
323
+ }
324
+ };
325
+ };
326
+
327
+ struct SM90_TMA_LOAD
328
+ {
329
+ CUTE_HOST_DEVICE static void
330
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
331
+ void * smem_ptr,
332
+ int32_t const& crd0)
333
+ {
334
+ return SM90_TMA_LOAD_1D::copy(desc_ptr, mbar_ptr, cache_hint, smem_ptr, crd0);
335
+ }
336
+ CUTE_HOST_DEVICE static void
337
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
338
+ void * smem_ptr,
339
+ int32_t const& crd0, int32_t const& crd1)
340
+ {
341
+ return SM90_TMA_LOAD_2D::copy(desc_ptr, mbar_ptr, cache_hint, smem_ptr, crd0, crd1);
342
+ }
343
+ CUTE_HOST_DEVICE static void
344
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
345
+ void * smem_ptr,
346
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2)
347
+ {
348
+ return SM90_TMA_LOAD_3D::copy(desc_ptr, mbar_ptr, cache_hint, smem_ptr, crd0, crd1, crd2);
349
+ }
350
+ CUTE_HOST_DEVICE static void
351
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
352
+ void * smem_ptr,
353
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3)
354
+ {
355
+ return SM90_TMA_LOAD_4D::copy(desc_ptr, mbar_ptr, cache_hint, smem_ptr, crd0, crd1, crd2, crd3);
356
+ }
357
+ CUTE_HOST_DEVICE static void
358
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint64_t cache_hint,
359
+ void * smem_ptr,
360
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3, int32_t const& crd4)
361
+ {
362
+ return SM90_TMA_LOAD_5D::copy(desc_ptr, mbar_ptr, cache_hint, smem_ptr, crd0, crd1, crd2, crd3, crd4);
363
+ }
364
+
365
+ struct PREFETCH
366
+ {
367
+ CUTE_HOST_DEVICE static void
368
+ copy(void const* desc_ptr,
369
+ int32_t const& crd0)
370
+ {
371
+ return SM90_TMA_LOAD_1D::PREFETCH::copy(desc_ptr, crd0);
372
+ }
373
+ CUTE_HOST_DEVICE static void
374
+ copy(void const* desc_ptr,
375
+ int32_t const& crd0, int32_t const& crd1)
376
+ {
377
+ return SM90_TMA_LOAD_2D::PREFETCH::copy(desc_ptr, crd0, crd1);
378
+ }
379
+ CUTE_HOST_DEVICE static void
380
+ copy(void const* desc_ptr,
381
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2)
382
+ {
383
+ return SM90_TMA_LOAD_3D::PREFETCH::copy(desc_ptr, crd0, crd1, crd2);
384
+ }
385
+ CUTE_HOST_DEVICE static void
386
+ copy(void const* desc_ptr,
387
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3)
388
+ {
389
+ return SM90_TMA_LOAD_4D::PREFETCH::copy(desc_ptr, crd0, crd1, crd2, crd3);
390
+ }
391
+ CUTE_HOST_DEVICE static void
392
+ copy(void const* desc_ptr,
393
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3, int32_t const& crd4)
394
+ {
395
+ return SM90_TMA_LOAD_5D::PREFETCH::copy(desc_ptr, crd0, crd1, crd2, crd3, crd4);
396
+ }
397
+ };
398
+ };
399
+
400
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
401
+ /// TMA_LOAD im2col: Initiates a TMA copy, in im2col mode, from global memory to shared memory
402
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
403
+
404
+ struct SM90_TMA_LOAD_IM2COL_3D
405
+ {
406
+ CUTE_HOST_DEVICE static void
407
+ copy(void const* desc_ptr, uint64_t* mbar_ptr,
408
+ void * smem_ptr,
409
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_n,
410
+ uint16_t const& offset_w)
411
+ {
412
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
413
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
414
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
415
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
416
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
417
+ // Copy from global to shared::cluster.
418
+ asm volatile (
419
+ "cp.async.bulk.tensor.3d.shared::cluster.global.im2col.mbarrier::complete_tx::bytes"
420
+ " [%0], [%1, {%3, %4, %5}], [%2], {%6};"
421
+ :
422
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
423
+ "r"(coord_c), "r"(coord_w), "r"(coord_n),
424
+ "h"(offset_w)
425
+ : "memory");
426
+ #else
427
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
428
+ #endif
429
+ }
430
+
431
+ struct PREFETCH
432
+ {
433
+ CUTE_HOST_DEVICE static void
434
+ copy(void const* desc_ptr,
435
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_n,
436
+ uint16_t const& offset_w)
437
+ {
438
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
439
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
440
+ asm volatile (
441
+ "cp.async.bulk.prefetch.tensor.3d.L2.global.im2col"
442
+ " [%0, {%1, %2, %3}], {%4};"
443
+ :
444
+ : "l"(gmem_int_desc),
445
+ "r"(coord_c), "r"(coord_w), "r"(coord_n),
446
+ "h"(offset_w)
447
+ : "memory");
448
+ #else
449
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
450
+ #endif
451
+ }
452
+ };
453
+ };
454
+
455
+ struct SM90_TMA_LOAD_IM2COL_4D
456
+ {
457
+ CUTE_HOST_DEVICE static void
458
+ copy(void const* desc_ptr, uint64_t* mbar_ptr,
459
+ void * smem_ptr,
460
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_n,
461
+ uint16_t const& offset_w, uint16_t const& offset_h)
462
+ {
463
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
464
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
465
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
466
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
467
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
468
+ // Copy from global to shared::cluster.
469
+ asm volatile (
470
+ "cp.async.bulk.tensor.4d.shared::cluster.global.im2col.mbarrier::complete_tx::bytes"
471
+ " [%0], [%1, {%3, %4, %5, %6}], [%2], {%7, %8};"
472
+ :
473
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
474
+ "r"(coord_c), "r"(coord_w), "r"(coord_h), "r"(coord_n),
475
+ "h"(offset_w), "h"(offset_h)
476
+ : "memory");
477
+ #else
478
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
479
+ #endif
480
+ }
481
+
482
+ struct PREFETCH
483
+ {
484
+ CUTE_HOST_DEVICE static void
485
+ copy(void const* desc_ptr,
486
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_n,
487
+ uint16_t const& offset_w, uint16_t const& offset_h)
488
+ {
489
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
490
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
491
+ asm volatile (
492
+ "cp.async.bulk.prefetch.tensor.4d.L2.global.im2col"
493
+ " [%0, {%1, %2, %3, %4}], {%5, %6};"
494
+ :
495
+ : "l"(gmem_int_desc),
496
+ "r"(coord_c), "r"(coord_w), "r"(coord_h), "r"(coord_n),
497
+ "h"(offset_w), "h"(offset_h)
498
+ : "memory");
499
+ #else
500
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
501
+ #endif
502
+ }
503
+ };
504
+ };
505
+
506
+ struct SM90_TMA_LOAD_IM2COL_5D
507
+ {
508
+ CUTE_HOST_DEVICE static void
509
+ copy(void const* desc_ptr, uint64_t* mbar_ptr,
510
+ void * smem_ptr,
511
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_d, int32_t const& coord_n,
512
+ uint16_t const& offset_w, uint16_t const& offset_h, uint16_t const& offset_d)
513
+ {
514
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
515
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
516
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
517
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
518
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
519
+ // Copy from global to shared::cluster.
520
+ asm volatile (
521
+ "cp.async.bulk.tensor.5d.shared::cluster.global.im2col.mbarrier::complete_tx::bytes"
522
+ " [%0], [%1, {%3, %4, %5, %6, %7}], [%2], {%8, %9, %10};"
523
+ :
524
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
525
+ "r"(coord_c), "r"(coord_w), "r"(coord_h), "r"(coord_d), "r"(coord_n),
526
+ "h"(offset_w), "h"(offset_h), "h"(offset_d)
527
+ : "memory");
528
+ #else
529
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
530
+ #endif
531
+ }
532
+
533
+ struct PREFETCH
534
+ {
535
+ CUTE_HOST_DEVICE static void
536
+ copy(void const* desc_ptr,
537
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_d, int32_t const& coord_n,
538
+ uint16_t const& offset_w, uint16_t const& offset_h, uint16_t const& offset_d)
539
+ {
540
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
541
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
542
+ asm volatile (
543
+ "cp.async.bulk.prefetch.tensor.5d.L2.global.im2col"
544
+ " [%0, {%1, %2, %3, %4, %5}], {%6, %7, %8};"
545
+ :
546
+ : "l"(gmem_int_desc),
547
+ "r"(coord_c), "r"(coord_w), "r"(coord_h), "r"(coord_d), "r"(coord_n),
548
+ "h"(offset_w), "h"(offset_h), "h"(offset_d)
549
+ : "memory");
550
+ #else
551
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
552
+ #endif
553
+ }
554
+ };
555
+ };
556
+
557
+ struct SM90_TMA_LOAD_IM2COL
558
+ {
559
+ CUTE_HOST_DEVICE static void
560
+ copy(void const* desc_ptr, uint64_t* mbar_ptr,
561
+ void * smem_ptr,
562
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_n,
563
+ uint16_t const& offset_w)
564
+ {
565
+ return SM90_TMA_LOAD_IM2COL_3D::copy(desc_ptr, mbar_ptr, smem_ptr,
566
+ coord_c, coord_w, coord_n,
567
+ offset_w);
568
+ }
569
+ CUTE_HOST_DEVICE static void
570
+ copy(void const* desc_ptr, uint64_t* mbar_ptr,
571
+ void * smem_ptr,
572
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_n,
573
+ uint16_t const& offset_w, uint16_t const& offset_h)
574
+ {
575
+ return SM90_TMA_LOAD_IM2COL_4D::copy(desc_ptr, mbar_ptr, smem_ptr,
576
+ coord_c, coord_w, coord_h, coord_n,
577
+ offset_w, offset_h);
578
+ }
579
+ CUTE_HOST_DEVICE static void
580
+ copy(void const* desc_ptr, uint64_t* mbar_ptr,
581
+ void * smem_ptr,
582
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_d, int32_t const& coord_n,
583
+ uint16_t const& offset_w, uint16_t const& offset_h, uint16_t const& offset_d)
584
+ {
585
+ return SM90_TMA_LOAD_IM2COL_5D::copy(desc_ptr, mbar_ptr, smem_ptr,
586
+ coord_c, coord_w, coord_h, coord_d, coord_n,
587
+ offset_w, offset_h, offset_d);
588
+ }
589
+
590
+ struct PREFETCH
591
+ {
592
+ CUTE_HOST_DEVICE static void
593
+ copy(void const* desc_ptr,
594
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_n,
595
+ uint16_t const& offset_w)
596
+ {
597
+ return SM90_TMA_LOAD_IM2COL_3D::PREFETCH::copy(desc_ptr,
598
+ coord_c, coord_w, coord_n,
599
+ offset_w);
600
+ }
601
+ CUTE_HOST_DEVICE static void
602
+ copy(void const* desc_ptr,
603
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_n,
604
+ uint16_t const& offset_w, uint16_t const& offset_h)
605
+ {
606
+ return SM90_TMA_LOAD_IM2COL_4D::PREFETCH::copy(desc_ptr,
607
+ coord_c, coord_w, coord_h, coord_n,
608
+ offset_w, offset_h);
609
+ }
610
+ CUTE_HOST_DEVICE static void
611
+ copy(void const* desc_ptr,
612
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_d, int32_t const& coord_n,
613
+ uint16_t const& offset_w, uint16_t const& offset_h, uint16_t const& offset_d)
614
+ {
615
+ return SM90_TMA_LOAD_IM2COL_5D::PREFETCH::copy(desc_ptr,
616
+ coord_c, coord_w, coord_h, coord_d, coord_n,
617
+ offset_w, offset_h, offset_d);
618
+ }
619
+ };
620
+ };
621
+
622
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
623
+ /// TMA_LOAD_MULTICAST: Initiates a TMA copy from global memory to shared memory
624
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
625
+
626
+ struct SM90_TMA_LOAD_MULTICAST_1D
627
+ {
628
+ CUTE_HOST_DEVICE static void
629
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
630
+ void * smem_ptr,
631
+ int32_t const& crd0)
632
+ {
633
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
634
+ #if defined(CUTE_ARCH_TMA_SM120_ENABLED)
635
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
636
+ #endif
637
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
638
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
639
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
640
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
641
+ asm volatile (
642
+ "cp.async.bulk.tensor.1d.shared::cluster.global.mbarrier::complete_tx::bytes.multicast::cluster.L2::cache_hint"
643
+ " [%0], [%1, {%4}], [%2], %3, %5;"
644
+ :
645
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
646
+ "h"(multicast_mask),
647
+ "r"(crd0), "l"(cache_hint)
648
+ : "memory");
649
+ #else
650
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
651
+ #endif
652
+ }
653
+ };
654
+
655
+ struct SM90_TMA_LOAD_MULTICAST_2D
656
+ {
657
+ CUTE_HOST_DEVICE static void
658
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
659
+ void * smem_ptr,
660
+ int32_t const& crd0, int32_t const& crd1)
661
+ {
662
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
663
+ #if defined(CUTE_ARCH_TMA_SM120_ENABLED)
664
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
665
+ #endif
666
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
667
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
668
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
669
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
670
+ asm volatile (
671
+ "cp.async.bulk.tensor.2d.shared::cluster.global.mbarrier::complete_tx::bytes.multicast::cluster.L2::cache_hint"
672
+ " [%0], [%1, {%4, %5}], [%2], %3, %6;"
673
+ :
674
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
675
+ "h"(multicast_mask),
676
+ "r"(crd0), "r"(crd1), "l"(cache_hint)
677
+ : "memory");
678
+ #else
679
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
680
+ #endif
681
+ }
682
+ };
683
+
684
+ struct SM90_TMA_LOAD_MULTICAST_3D
685
+ {
686
+ CUTE_HOST_DEVICE static void
687
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
688
+ void * smem_ptr,
689
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2)
690
+ {
691
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
692
+ #if defined(CUTE_ARCH_TMA_SM120_ENABLED)
693
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
694
+ #endif
695
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
696
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
697
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
698
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
699
+ asm volatile (
700
+ "cp.async.bulk.tensor.3d.shared::cluster.global.mbarrier::complete_tx::bytes.multicast::cluster.L2::cache_hint"
701
+ " [%0], [%1, {%4, %5, %6}], [%2], %3, %7;"
702
+ :
703
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
704
+ "h"(multicast_mask),
705
+ "r"(crd0), "r"(crd1), "r"(crd2), "l"(cache_hint)
706
+ : "memory");
707
+ #else
708
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
709
+ #endif
710
+ }
711
+ };
712
+
713
+ struct SM90_TMA_LOAD_MULTICAST_4D
714
+ {
715
+ CUTE_HOST_DEVICE static void
716
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
717
+ void * smem_ptr,
718
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3)
719
+ {
720
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
721
+ #if defined(CUTE_ARCH_TMA_SM120_ENABLED)
722
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
723
+ #endif
724
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
725
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
726
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
727
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
728
+ asm volatile (
729
+ "cp.async.bulk.tensor.4d.shared::cluster.global.mbarrier::complete_tx::bytes.multicast::cluster.L2::cache_hint"
730
+ " [%0], [%1, {%4, %5, %6, %7}], [%2], %3, %8;"
731
+ :
732
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
733
+ "h"(multicast_mask),
734
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3), "l"(cache_hint)
735
+ : "memory");
736
+ #else
737
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
738
+ #endif
739
+ }
740
+ };
741
+
742
+ struct SM90_TMA_LOAD_MULTICAST_5D
743
+ {
744
+ CUTE_HOST_DEVICE static void
745
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
746
+ void * smem_ptr,
747
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3, int32_t const& crd4)
748
+ {
749
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
750
+ #if defined(CUTE_ARCH_TMA_SM120_ENABLED)
751
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
752
+ #endif
753
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
754
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
755
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
756
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
757
+ asm volatile (
758
+ "cp.async.bulk.tensor.5d.shared::cluster.global.mbarrier::complete_tx::bytes.multicast::cluster.L2::cache_hint"
759
+ " [%0], [%1, {%4, %5, %6, %7, %8}], [%2], %3, %9;"
760
+ :
761
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
762
+ "h"(multicast_mask),
763
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3), "r"(crd4), "l"(cache_hint)
764
+ : "memory");
765
+ #else
766
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
767
+ #endif
768
+ }
769
+ };
770
+
771
+ struct SM90_TMA_LOAD_MULTICAST
772
+ {
773
+ CUTE_HOST_DEVICE static void
774
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
775
+ void * smem_ptr,
776
+ int32_t const& crd0)
777
+ {
778
+ return SM90_TMA_LOAD_MULTICAST_1D::copy(desc_ptr, mbar_ptr, multicast_mask, cache_hint, smem_ptr, crd0);
779
+ }
780
+ CUTE_HOST_DEVICE static void
781
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
782
+ void * smem_ptr,
783
+ int32_t const& crd0, int32_t const& crd1)
784
+ {
785
+ return SM90_TMA_LOAD_MULTICAST_2D::copy(desc_ptr, mbar_ptr, multicast_mask, cache_hint, smem_ptr, crd0, crd1);
786
+ }
787
+ CUTE_HOST_DEVICE static void
788
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
789
+ void * smem_ptr,
790
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2)
791
+ {
792
+ return SM90_TMA_LOAD_MULTICAST_3D::copy(desc_ptr, mbar_ptr, multicast_mask, cache_hint, smem_ptr, crd0, crd1, crd2);
793
+ }
794
+ CUTE_HOST_DEVICE static void
795
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
796
+ void * smem_ptr,
797
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3)
798
+ {
799
+ return SM90_TMA_LOAD_MULTICAST_4D::copy(desc_ptr, mbar_ptr, multicast_mask, cache_hint, smem_ptr, crd0, crd1, crd2, crd3);
800
+ }
801
+ CUTE_HOST_DEVICE static void
802
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask, uint64_t cache_hint,
803
+ void * smem_ptr,
804
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3, int32_t const& crd4)
805
+ {
806
+ return SM90_TMA_LOAD_MULTICAST_5D::copy(desc_ptr, mbar_ptr, multicast_mask, cache_hint, smem_ptr, crd0, crd1, crd2, crd3, crd4);
807
+ }
808
+
809
+ using PREFETCH = typename SM90_TMA_LOAD::PREFETCH;
810
+ };
811
+
812
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
813
+ /// TMA_LOAD_MULTICAST im2col: Initiates a TMA copy, in im2col mode, from global memory to shared memory
814
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
815
+
816
+ struct SM90_TMA_LOAD_IM2COL_MULTICAST_3D
817
+ {
818
+ CUTE_HOST_DEVICE static void
819
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask,
820
+ void * smem_ptr,
821
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_n,
822
+ uint16_t const& offset_w)
823
+ {
824
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
825
+ #if defined(CUTE_ARCH_TMA_SM120_ENABLED)
826
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
827
+ #endif
828
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
829
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
830
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
831
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
832
+ // Copy from global to shared::cluster.
833
+ asm volatile (
834
+ "cp.async.bulk.tensor.3d.shared::cluster.global.im2col.mbarrier::complete_tx::bytes.multicast::cluster"
835
+ " [%0], [%1, {%3, %4, %5}], [%2], {%6}, %7;"
836
+ :
837
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
838
+ "r"(coord_c), "r"(coord_w), "r"(coord_n),
839
+ "h"(offset_w),
840
+ "h"(multicast_mask)
841
+ : "memory");
842
+ #else
843
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
844
+ #endif
845
+ }
846
+ };
847
+
848
+ struct SM90_TMA_LOAD_IM2COL_MULTICAST_4D
849
+ {
850
+ CUTE_HOST_DEVICE static void
851
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask,
852
+ void * smem_ptr,
853
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_n,
854
+ uint16_t const& offset_w, uint16_t const& offset_h)
855
+ {
856
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
857
+ #if defined(CUTE_ARCH_TMA_SM120_ENABLED)
858
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
859
+ #endif
860
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
861
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
862
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
863
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
864
+ // Copy from global to shared::cluster.
865
+ asm volatile (
866
+ "cp.async.bulk.tensor.4d.shared::cluster.global.im2col.mbarrier::complete_tx::bytes.multicast::cluster"
867
+ " [%0], [%1, {%3, %4, %5, %6}], [%2], {%7, %8}, %9;"
868
+ :
869
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
870
+ "r"(coord_c), "r"(coord_w), "r"(coord_h), "r"(coord_n),
871
+ "h"(offset_w), "h"(offset_h),
872
+ "h"(multicast_mask)
873
+ : "memory");
874
+ #else
875
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
876
+ #endif
877
+ }
878
+ };
879
+
880
+ struct SM90_TMA_LOAD_IM2COL_MULTICAST_5D
881
+ {
882
+ CUTE_HOST_DEVICE static void
883
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask,
884
+ void * smem_ptr,
885
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_d, int32_t const& coord_n,
886
+ uint16_t const& offset_w, uint16_t const& offset_h, uint16_t const& offset_d)
887
+ {
888
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
889
+ #if defined(CUTE_ARCH_TMA_SM120_ENABLED)
890
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
891
+ #endif
892
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
893
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
894
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
895
+ cutlass::arch::synclog_emit_tma_load(__LINE__, gmem_int_desc, smem_int_mbar, smem_int_ptr);
896
+ // Copy from global to shared::cluster.
897
+ asm volatile (
898
+ "cp.async.bulk.tensor.5d.shared::cluster.global.im2col.mbarrier::complete_tx::bytes.multicast::cluster"
899
+ " [%0], [%1, {%3, %4, %5, %6, %7}], [%2], {%8, %9, %10}, %11;"
900
+ :
901
+ : "r"(smem_int_ptr), "l"(gmem_int_desc), "r"(smem_int_mbar),
902
+ "r"(coord_c), "r"(coord_w), "r"(coord_h), "r"(coord_d), "r"(coord_n),
903
+ "h"(offset_w), "h"(offset_h), "h"(offset_d),
904
+ "h"(multicast_mask)
905
+ : "memory");
906
+ #else
907
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
908
+ #endif
909
+ }
910
+ };
911
+
912
+ struct SM90_TMA_LOAD_IM2COL_MULTICAST
913
+ {
914
+ CUTE_HOST_DEVICE static void
915
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask,
916
+ void * smem_ptr,
917
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_n,
918
+ uint16_t const& offset_w)
919
+ {
920
+ return SM90_TMA_LOAD_IM2COL_MULTICAST_3D::copy(desc_ptr, mbar_ptr, multicast_mask,
921
+ smem_ptr,
922
+ coord_c, coord_w, coord_n,
923
+ offset_w);
924
+ }
925
+
926
+ CUTE_HOST_DEVICE static void
927
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask,
928
+ void * smem_ptr,
929
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_n,
930
+ uint16_t const& offset_w, uint16_t const& offset_h)
931
+ {
932
+ return SM90_TMA_LOAD_IM2COL_MULTICAST_4D::copy(desc_ptr, mbar_ptr, multicast_mask,
933
+ smem_ptr,
934
+ coord_c, coord_w, coord_h, coord_n,
935
+ offset_w, offset_h);
936
+ }
937
+
938
+ CUTE_HOST_DEVICE static void
939
+ copy(void const* desc_ptr, uint64_t* mbar_ptr, uint16_t multicast_mask,
940
+ void * smem_ptr,
941
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_d, int32_t const& coord_n,
942
+ uint16_t const& offset_w, uint16_t const& offset_h, uint16_t const& offset_d)
943
+ {
944
+ return SM90_TMA_LOAD_IM2COL_MULTICAST_5D::copy(desc_ptr, mbar_ptr, multicast_mask,
945
+ smem_ptr,
946
+ coord_c, coord_w, coord_h, coord_d, coord_n,
947
+ offset_w, offset_h, offset_d);
948
+ }
949
+
950
+ using PREFETCH = typename SM90_TMA_LOAD_IM2COL::PREFETCH;
951
+ };
952
+
953
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
954
+ /// TMA_STORE : Initiates a TMA copy from shared memory to global memory
955
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
956
+
957
+ struct SM90_TMA_STORE_1D
958
+ {
959
+ CUTE_HOST_DEVICE static void
960
+ copy(void const* desc_ptr,
961
+ void const* smem_ptr,
962
+ int32_t const& crd0)
963
+ {
964
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
965
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
966
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
967
+ cutlass::arch::synclog_emit_tma_store(__LINE__, gmem_int_desc, smem_int_ptr);
968
+ asm volatile (
969
+ "cp.async.bulk.tensor.1d.global.shared::cta.bulk_group [%0, {%2}], [%1];"
970
+ :
971
+ : "l"(gmem_int_desc), "r"(smem_int_ptr),
972
+ "r"(crd0)
973
+ : "memory");
974
+ #else
975
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
976
+ #endif
977
+ }
978
+ };
979
+
980
+ struct SM90_TMA_STORE_2D
981
+ {
982
+ CUTE_HOST_DEVICE static void
983
+ copy(void const* desc_ptr,
984
+ void const* smem_ptr,
985
+ int32_t const& crd0, int32_t const& crd1)
986
+ {
987
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
988
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
989
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
990
+ cutlass::arch::synclog_emit_tma_store(__LINE__, gmem_int_desc, smem_int_ptr);
991
+ asm volatile (
992
+ "cp.async.bulk.tensor.2d.global.shared::cta.bulk_group [%0, {%2, %3}], [%1];"
993
+ :
994
+ : "l"(gmem_int_desc), "r"(smem_int_ptr),
995
+ "r"(crd0), "r"(crd1)
996
+ : "memory");
997
+ #else
998
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
999
+ #endif
1000
+ }
1001
+ };
1002
+
1003
+ struct SM90_TMA_STORE_3D
1004
+ {
1005
+ CUTE_HOST_DEVICE static void
1006
+ copy(void const* desc_ptr,
1007
+ void const* smem_ptr,
1008
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2)
1009
+ {
1010
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1011
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
1012
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
1013
+ cutlass::arch::synclog_emit_tma_store(__LINE__, gmem_int_desc, smem_int_ptr);
1014
+ asm volatile (
1015
+ "cp.async.bulk.tensor.3d.global.shared::cta.bulk_group [%0, {%2, %3, %4}], [%1];"
1016
+ :
1017
+ : "l"(gmem_int_desc), "r"(smem_int_ptr),
1018
+ "r"(crd0), "r"(crd1), "r"(crd2)
1019
+ : "memory");
1020
+ #else
1021
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1022
+ #endif
1023
+ }
1024
+ };
1025
+
1026
+ struct SM90_TMA_STORE_4D
1027
+ {
1028
+ CUTE_HOST_DEVICE static void
1029
+ copy(void const* desc_ptr,
1030
+ void const* smem_ptr,
1031
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3)
1032
+ {
1033
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1034
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
1035
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
1036
+ cutlass::arch::synclog_emit_tma_store(__LINE__, gmem_int_desc, smem_int_ptr);
1037
+ asm volatile (
1038
+ "cp.async.bulk.tensor.4d.global.shared::cta.bulk_group [%0, {%2, %3, %4, %5}], [%1];"
1039
+ :
1040
+ : "l"(gmem_int_desc), "r"(smem_int_ptr),
1041
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3)
1042
+ : "memory");
1043
+ #else
1044
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1045
+ #endif
1046
+ }
1047
+ };
1048
+
1049
+ struct SM90_TMA_STORE_5D
1050
+ {
1051
+ CUTE_HOST_DEVICE static void
1052
+ copy(void const* desc_ptr,
1053
+ void const* smem_ptr,
1054
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3, int32_t const& crd4)
1055
+ {
1056
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1057
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
1058
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
1059
+ cutlass::arch::synclog_emit_tma_store(__LINE__, gmem_int_desc, smem_int_ptr);
1060
+ asm volatile (
1061
+ "cp.async.bulk.tensor.5d.global.shared::cta.bulk_group [%0, {%2, %3, %4, %5, %6}], [%1];"
1062
+ :
1063
+ : "l"(gmem_int_desc), "r"(smem_int_ptr),
1064
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3), "r"(crd4)
1065
+ : "memory");
1066
+ #else
1067
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1068
+ #endif
1069
+ }
1070
+ };
1071
+
1072
+ struct SM90_TMA_STORE
1073
+ {
1074
+ CUTE_HOST_DEVICE static void
1075
+ copy(void const* desc_ptr,
1076
+ void const* smem_ptr,
1077
+ int32_t const& crd0)
1078
+ {
1079
+ return SM90_TMA_STORE_1D::copy(desc_ptr, smem_ptr, crd0);
1080
+ }
1081
+ CUTE_HOST_DEVICE static void
1082
+ copy(void const* desc_ptr,
1083
+ void const* smem_ptr,
1084
+ int32_t const& crd0, int32_t const& crd1)
1085
+ {
1086
+ return SM90_TMA_STORE_2D::copy(desc_ptr, smem_ptr, crd0, crd1);
1087
+ }
1088
+ CUTE_HOST_DEVICE static void
1089
+ copy(void const* desc_ptr,
1090
+ void const* smem_ptr,
1091
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2)
1092
+ {
1093
+ return SM90_TMA_STORE_3D::copy(desc_ptr, smem_ptr, crd0, crd1, crd2);
1094
+ }
1095
+ CUTE_HOST_DEVICE static void
1096
+ copy(void const* desc_ptr,
1097
+ void const* smem_ptr,
1098
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3)
1099
+ {
1100
+ return SM90_TMA_STORE_4D::copy(desc_ptr, smem_ptr, crd0, crd1, crd2, crd3);
1101
+ }
1102
+ CUTE_HOST_DEVICE static void
1103
+ copy(void const* desc_ptr,
1104
+ void const* smem_ptr,
1105
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3, int32_t const& crd4)
1106
+ {
1107
+ return SM90_TMA_STORE_5D::copy(desc_ptr, smem_ptr, crd0, crd1, crd2, crd3, crd4);
1108
+ }
1109
+ };
1110
+
1111
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1112
+ /// TMA_STORE im2col: Initiates a TMA copy, in im2col mode, from shared memory to global memory
1113
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1114
+
1115
+ struct SM90_TMA_STORE_IM2COL_3D
1116
+ {
1117
+ CUTE_HOST_DEVICE static void
1118
+ copy(void const* desc_ptr,
1119
+ void const* smem_ptr,
1120
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_n)
1121
+ {
1122
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1123
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
1124
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
1125
+ cutlass::arch::synclog_emit_tma_store(__LINE__, gmem_int_desc, smem_int_ptr);
1126
+ asm volatile (
1127
+ "cp.async.bulk.tensor.3d.global.shared::cta.im2col_no_offs.bulk_group"
1128
+ " [%0, {%2, %3, %4}], [%1];"
1129
+ :
1130
+ : "l"(gmem_int_desc), "r"(smem_int_ptr),
1131
+ "r"(coord_c), "r"(coord_w), "r"(coord_n)
1132
+ : "memory");
1133
+ #else
1134
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1135
+ #endif
1136
+ }
1137
+ };
1138
+
1139
+ struct SM90_TMA_STORE_IM2COL_4D
1140
+ {
1141
+ CUTE_HOST_DEVICE static void
1142
+ copy(void const* desc_ptr,
1143
+ void const* smem_ptr,
1144
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_n)
1145
+ {
1146
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1147
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
1148
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
1149
+ cutlass::arch::synclog_emit_tma_store(__LINE__, gmem_int_desc, smem_int_ptr);
1150
+ asm volatile (
1151
+ "cp.async.bulk.tensor.4d.global.shared::cta.im2col_no_offs.bulk_group"
1152
+ " [%0, {%2, %3, %4, %5}], [%1];"
1153
+ :
1154
+ : "l"(gmem_int_desc), "r"(smem_int_ptr),
1155
+ "r"(coord_c), "r"(coord_w), "r"(coord_h), "r"(coord_n)
1156
+ : "memory");
1157
+ #else
1158
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1159
+ #endif
1160
+ }
1161
+ };
1162
+
1163
+ struct SM90_TMA_STORE_IM2COL_5D
1164
+ {
1165
+ CUTE_HOST_DEVICE static void
1166
+ copy(void const* desc_ptr,
1167
+ void const* smem_ptr,
1168
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_d, int32_t const& coord_n)
1169
+ {
1170
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1171
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
1172
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
1173
+ cutlass::arch::synclog_emit_tma_store(__LINE__, gmem_int_desc, smem_int_ptr);
1174
+ asm volatile (
1175
+ "cp.async.bulk.tensor.5d.global.shared::cta.im2col_no_offs.bulk_group"
1176
+ " [%0, {%2, %3, %4, %5, %6}], [%1];"
1177
+ :
1178
+ : "l"(gmem_int_desc), "r"(smem_int_ptr),
1179
+ "r"(coord_c), "r"(coord_w), "r"(coord_h), "r"(coord_d), "r"(coord_n)
1180
+ : "memory");
1181
+ #else
1182
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1183
+ #endif
1184
+ }
1185
+ };
1186
+
1187
+ struct SM90_TMA_STORE_IM2COL
1188
+ {
1189
+ CUTE_HOST_DEVICE static void
1190
+ copy(void const* desc_ptr,
1191
+ void const* smem_ptr,
1192
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_n)
1193
+ {
1194
+ return SM90_TMA_STORE_IM2COL_3D::copy(desc_ptr, smem_ptr, coord_c, coord_w, coord_n);
1195
+ }
1196
+ CUTE_HOST_DEVICE static void
1197
+ copy(void const* desc_ptr,
1198
+ void const* smem_ptr,
1199
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_n)
1200
+ {
1201
+ return SM90_TMA_STORE_IM2COL_4D::copy(desc_ptr, smem_ptr, coord_c, coord_w, coord_h, coord_n);
1202
+ }
1203
+ CUTE_HOST_DEVICE static void
1204
+ copy(void const* desc_ptr,
1205
+ void const* smem_ptr,
1206
+ int32_t const& coord_c, int32_t const& coord_w, int32_t const& coord_h, int32_t const& coord_d, int32_t const& coord_n)
1207
+ {
1208
+ return SM90_TMA_STORE_IM2COL_5D::copy(desc_ptr, smem_ptr, coord_c, coord_w, coord_h, coord_d, coord_n);
1209
+ }
1210
+ };
1211
+
1212
+ // Fence for smem stores for subsequent TMA_STORE
1213
+ CUTE_HOST_DEVICE static void
1214
+ tma_store_fence() {
1215
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1216
+ cutlass::arch::synclog_emit_fence_view_async_shared(__LINE__);
1217
+ asm volatile ("fence.proxy.async.shared::cta;");
1218
+ #elif defined(__CUDA_ARCH__)
1219
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1220
+ #endif
1221
+ }
1222
+
1223
+ // Indicate arrival of warp issuing TMA_STORE
1224
+ CUTE_HOST_DEVICE static void
1225
+ tma_store_arrive() {
1226
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1227
+ cutlass::arch::synclog_emit_tma_store_arrive(__LINE__);
1228
+ asm volatile("cp.async.bulk.commit_group;");
1229
+ #else
1230
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1231
+ #endif
1232
+ }
1233
+
1234
+
1235
+ CUTE_HOST_DEVICE static void
1236
+ tma_desc_commit_group() {
1237
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1238
+ asm volatile("cp.async.bulk.commit_group;");
1239
+ #else
1240
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1241
+ #endif
1242
+ }
1243
+
1244
+
1245
+ // Wait until at most Count committed TMA_STOREs are pending and all prior commits are complete
1246
+ template <int Count>
1247
+ CUTE_HOST_DEVICE static void
1248
+ tma_store_wait() {
1249
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1250
+ asm volatile(
1251
+ "cp.async.bulk.wait_group.read %0;"
1252
+ :
1253
+ : "n"(Count)
1254
+ : "memory");
1255
+ cutlass::arch::synclog_emit_tma_store_wait(__LINE__, Count);
1256
+ #else
1257
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1258
+ #endif
1259
+ }
1260
+
1261
+
1262
+ // Wait until all TMA descriptor previously issued are safe to be modified after tma_desc_commit_group()
1263
+ CUTE_HOST_DEVICE static void
1264
+ tma_desc_wait_group() {
1265
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1266
+ asm volatile(
1267
+ "cp.async.bulk.wait_group.read %0;"
1268
+ :
1269
+ : "n"(0)
1270
+ : "memory");
1271
+ #else
1272
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1273
+ #endif
1274
+ }
1275
+
1276
+
1277
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1278
+ /// TMA_REDUCE_ADD : Initiates a TMA reduce-add from shared memory to global memory
1279
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1280
+
1281
+ struct SM90_TMA_REDUCE_ADD_1D
1282
+ {
1283
+ CUTE_HOST_DEVICE static void
1284
+ copy(void const* const desc_ptr,
1285
+ void const* const smem_ptr,
1286
+ int32_t const& crd0)
1287
+ {
1288
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1289
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
1290
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
1291
+ cutlass::arch::synclog_emit_tma_store(__LINE__, gmem_int_desc, smem_int_ptr);
1292
+ asm volatile (
1293
+ "cp.reduce.async.bulk.tensor.1d.global.shared::cta.add.bulk_group [%0, {%2}], [%1];"
1294
+ :
1295
+ : "l"(gmem_int_desc), "r"(smem_int_ptr),
1296
+ "r"(crd0)
1297
+ : "memory");
1298
+ #else
1299
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1300
+ #endif
1301
+ }
1302
+ };
1303
+
1304
+ struct SM90_TMA_REDUCE_ADD_2D
1305
+ {
1306
+ CUTE_HOST_DEVICE static void
1307
+ copy(void const* const desc_ptr,
1308
+ void const* const smem_ptr,
1309
+ int32_t const& crd0, int32_t const& crd1)
1310
+ {
1311
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1312
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
1313
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
1314
+ cutlass::arch::synclog_emit_tma_store(__LINE__, gmem_int_desc, smem_int_ptr);
1315
+ asm volatile (
1316
+ "cp.reduce.async.bulk.tensor.2d.global.shared::cta.add.bulk_group [%0, {%2, %3}], [%1];"
1317
+ :
1318
+ : "l"(gmem_int_desc), "r"(smem_int_ptr),
1319
+ "r"(crd0), "r"(crd1)
1320
+ : "memory");
1321
+ #else
1322
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1323
+ #endif
1324
+ }
1325
+ };
1326
+
1327
+ struct SM90_TMA_REDUCE_ADD_3D
1328
+ {
1329
+ CUTE_HOST_DEVICE static void
1330
+ copy(void const* const desc_ptr,
1331
+ void const* const smem_ptr,
1332
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2)
1333
+ {
1334
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1335
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
1336
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
1337
+ cutlass::arch::synclog_emit_tma_store(__LINE__, gmem_int_desc, smem_int_ptr);
1338
+ asm volatile (
1339
+ "cp.reduce.async.bulk.tensor.3d.global.shared::cta.add.bulk_group [%0, {%2, %3, %4}], [%1];"
1340
+ :
1341
+ : "l"(gmem_int_desc), "r"(smem_int_ptr),
1342
+ "r"(crd0), "r"(crd1), "r"(crd2)
1343
+ : "memory");
1344
+ #else
1345
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1346
+ #endif
1347
+ }
1348
+ };
1349
+
1350
+ struct SM90_TMA_REDUCE_ADD_4D
1351
+ {
1352
+ CUTE_HOST_DEVICE static void
1353
+ copy(void const* const desc_ptr,
1354
+ void const* const smem_ptr,
1355
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3)
1356
+ {
1357
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1358
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
1359
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
1360
+ cutlass::arch::synclog_emit_tma_store(__LINE__, gmem_int_desc, smem_int_ptr);
1361
+ asm volatile (
1362
+ "cp.reduce.async.bulk.tensor.4d.global.shared::cta.add.bulk_group [%0, {%2, %3, %4, %5}], [%1];"
1363
+ :
1364
+ : "l"(gmem_int_desc), "r"(smem_int_ptr),
1365
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3)
1366
+ : "memory");
1367
+ #else
1368
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1369
+ #endif
1370
+ }
1371
+ };
1372
+
1373
+ struct SM90_TMA_REDUCE_ADD_5D
1374
+ {
1375
+ CUTE_HOST_DEVICE static void
1376
+ copy(void const* const desc_ptr,
1377
+ void const* const smem_ptr,
1378
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3, int32_t const& crd4)
1379
+ {
1380
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1381
+ uint64_t gmem_int_desc = reinterpret_cast<uint64_t>(desc_ptr);
1382
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
1383
+ cutlass::arch::synclog_emit_tma_store(__LINE__, gmem_int_desc, smem_int_ptr);
1384
+ asm volatile (
1385
+ "cp.reduce.async.bulk.tensor.5d.global.shared::cta.add.bulk_group [%0, {%2, %3, %4, %5, %6}], [%1];"
1386
+ :
1387
+ : "l"(gmem_int_desc), "r"(smem_int_ptr),
1388
+ "r"(crd0), "r"(crd1), "r"(crd2), "r"(crd3), "r"(crd4)
1389
+ : "memory");
1390
+ #else
1391
+ CUTE_INVALID_CONTROL_PATH("Trying to use tma without CUTE_ARCH_TMA_SM90_ENABLED.");
1392
+ #endif
1393
+ }
1394
+ };
1395
+
1396
+ struct SM90_TMA_REDUCE_ADD
1397
+ {
1398
+ CUTE_HOST_DEVICE static void
1399
+ copy(void const* const desc_ptr,
1400
+ void const* const smem_ptr,
1401
+ int32_t const& crd0)
1402
+ {
1403
+ return SM90_TMA_REDUCE_ADD_1D::copy(desc_ptr, smem_ptr, crd0);
1404
+ }
1405
+ CUTE_HOST_DEVICE static void
1406
+ copy(void const* const desc_ptr,
1407
+ void const* const smem_ptr,
1408
+ int32_t const& crd0, int32_t const& crd1)
1409
+ {
1410
+ return SM90_TMA_REDUCE_ADD_2D::copy(desc_ptr, smem_ptr, crd0, crd1);
1411
+ }
1412
+ CUTE_HOST_DEVICE static void
1413
+ copy(void const* const desc_ptr,
1414
+ void const* const smem_ptr,
1415
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2)
1416
+ {
1417
+ return SM90_TMA_REDUCE_ADD_3D::copy(desc_ptr, smem_ptr, crd0, crd1, crd2);
1418
+ }
1419
+ CUTE_HOST_DEVICE static void
1420
+ copy(void const* const desc_ptr,
1421
+ void const* const smem_ptr,
1422
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3)
1423
+ {
1424
+ return SM90_TMA_REDUCE_ADD_4D::copy(desc_ptr, smem_ptr, crd0, crd1, crd2, crd3);
1425
+ }
1426
+ CUTE_HOST_DEVICE static void
1427
+ copy(void const* const desc_ptr,
1428
+ void const* const smem_ptr,
1429
+ int32_t const& crd0, int32_t const& crd1, int32_t const& crd2, int32_t const& crd3, int32_t const& crd4)
1430
+ {
1431
+ return SM90_TMA_REDUCE_ADD_5D::copy(desc_ptr, smem_ptr, crd0, crd1, crd2, crd3, crd4);
1432
+ }
1433
+ };
1434
+
1435
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1436
+ /// BULK_COPY : Copy a bulk of memory between shared memory and global memory
1437
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1438
+
1439
+ struct SM90_BULK_COPY_G2S
1440
+ {
1441
+ CUTE_HOST_DEVICE static void
1442
+ copy(void const* gmem_ptr, uint64_t* mbar_ptr,
1443
+ void * smem_ptr, int32_t load_bytes)
1444
+ {
1445
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1446
+ uint32_t smem_int_mbar = cast_smem_ptr_to_uint(mbar_ptr);
1447
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
1448
+ asm volatile("cp.async.bulk.shared::cluster.global.mbarrier::complete_tx::bytes [%0], [%1], %2, [%3];\n"
1449
+ :
1450
+ : "r"(smem_int_ptr), "l"(gmem_ptr), "r"(load_bytes), "r"(smem_int_mbar)
1451
+ : "memory");
1452
+ #else
1453
+ CUTE_INVALID_CONTROL_PATH("Trying to use BULK_COPY without CUTE_ARCH_TMA_SM90_ENABLED.");
1454
+ #endif
1455
+ }
1456
+
1457
+ struct PREFETCH
1458
+ {
1459
+ CUTE_HOST_DEVICE static void
1460
+ copy(void const* gmem_ptr, int32_t load_bytes)
1461
+ {
1462
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1463
+ asm volatile("cp.async.bulk.prefetch.L2.global [%0], %1;\n"
1464
+ :
1465
+ : "l"(gmem_ptr), "r"(load_bytes)
1466
+ : "memory");
1467
+ #else
1468
+ CUTE_INVALID_CONTROL_PATH("Trying to use BULK_COPY without CUTE_ARCH_TMA_SM90_ENABLED.");
1469
+ #endif
1470
+ }
1471
+ };
1472
+ };
1473
+
1474
+ struct SM90_BULK_COPY_S2G
1475
+ {
1476
+ CUTE_HOST_DEVICE static void
1477
+ copy(void const* smem_ptr,
1478
+ void * gmem_ptr, int32_t store_bytes)
1479
+ {
1480
+ #if defined(CUTE_ARCH_TMA_SM90_ENABLED)
1481
+ uint32_t smem_int_ptr = cast_smem_ptr_to_uint(smem_ptr);
1482
+ asm volatile("cp.async.bulk.global.shared::cta.bulk_group [%0], [%1], %2;\n"
1483
+ :
1484
+ : "l"(gmem_ptr), "r"(smem_int_ptr), "r"(store_bytes)
1485
+ : "memory");
1486
+ #else
1487
+ CUTE_INVALID_CONTROL_PATH("Trying to use BULK_COPY without CUTE_ARCH_TMA_SM90_ENABLED.");
1488
+ #endif
1489
+ }
1490
+ };
1491
+
1492
+ struct SM90_BULK_COPY_AUTO {};
1493
+
1494
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1495
+
1496
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma.hpp ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp> // CUTE_HOST_DEVICE
34
+ #include <cute/numeric/complex.hpp> // cute::fma
35
+ #include <cute/numeric/real.hpp> // cute::fma
36
+
37
+ namespace cute
38
+ {
39
+
40
+ //
41
+ // Direct FMA for any type
42
+ //
43
+
44
+ template <class D, class A = D, class B = A, class C = D>
45
+ struct UniversalFMA
46
+ {
47
+ using DRegisters = D[1];
48
+ using ARegisters = A[1];
49
+ using BRegisters = B[1];
50
+ using CRegisters = C[1];
51
+
52
+ CUTE_HOST_DEVICE static constexpr void
53
+ fma(D & d,
54
+ A const& a,
55
+ B const& b,
56
+ C const& c)
57
+ {
58
+ // Forward to an ADL/cute free function for these types
59
+ using cute::fma;
60
+ fma(d, a, b, c);
61
+ }
62
+ };
63
+
64
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm100.hpp ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ //
32
+
33
+ //
34
+
35
+ #pragma once
36
+
37
+ #include <cute/arch/config.hpp>
38
+ #include <cute/arch/mma.hpp>
39
+
40
+ namespace cute {
41
+
42
+ } // namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm100_desc.hpp ADDED
@@ -0,0 +1,651 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ //
32
+
33
+ //
34
+
35
+ #pragma once
36
+
37
+ #if !defined(__CUDACC_RTC__)
38
+ #include <cinttypes>
39
+ #endif
40
+
41
+ #include <cute/arch/config.hpp>
42
+
43
+ #include <cute/arch/mma.hpp>
44
+
45
+ #include <cute/container/bit_field.hpp>
46
+ #include <cute/container/array.hpp> // cute::array
47
+
48
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
49
+
50
+ namespace cute {
51
+
52
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
53
+ // UMMA Descriptor and utilities
54
+
55
+ // UMMA enums and utilities
56
+ namespace UMMA
57
+ {
58
+
59
+ enum class Major : uint8_t {
60
+ K = 0,
61
+ MN = 1
62
+ };
63
+
64
+ enum class ScaleIn : uint8_t {
65
+ One = 0,
66
+ Neg = 1
67
+ };
68
+
69
+ enum class ScaleOut : uint8_t {
70
+ Zero = 0,
71
+ One = 1
72
+ };
73
+
74
+ enum class Saturate : uint8_t {
75
+ False = 0,
76
+ True = 1
77
+ };
78
+
79
+ enum class LayoutType : uint8_t {
80
+ SWIZZLE_NONE = 0,
81
+ SWIZZLE_128B_BASE32B = 1,
82
+ SWIZZLE_128B = 2,
83
+ SWIZZLE_64B = 4,
84
+ SWIZZLE_32B = 6
85
+ };
86
+
87
+ CUTE_HOST_DEVICE char const* to_string(LayoutType const& t) {
88
+ switch (t) {
89
+ case LayoutType::SWIZZLE_NONE: return "SWIZZLE_NONE";
90
+ case LayoutType::SWIZZLE_128B_BASE32B: return "SWIZZLE_128B_BASE32B";
91
+ case LayoutType::SWIZZLE_128B: return "SWIZZLE_128B";
92
+ case LayoutType::SWIZZLE_64B: return "SWIZZLE_64B";
93
+ case LayoutType::SWIZZLE_32B: return "SWIZZLE_32B";
94
+ }
95
+ return nullptr;
96
+ }
97
+
98
+ union SmemDescriptor
99
+ {
100
+ uint64_t desc_ = 0;
101
+ // Bitfield implementation avoids the need for shifts in assignment
102
+ struct {
103
+ // start_address, bit [0,14), 4LSB not included
104
+ uint16_t start_address_ : 14, : 2; // 14 bits [0,14), 2 bits unused
105
+ // leading dimension byte offset, bit [16,30), 4LSB not included
106
+ uint16_t leading_byte_offset_ : 14, : 2; // 14 bits [0,14), 2 bits unused
107
+ // stride dimension byte offset, bit [32,46), 4LSB not included
108
+ uint16_t stride_byte_offset_ : 14, version_ : 2; // 14 bits [0,14), 2 bits [14,16)
109
+ // base_offset, bit [49,52). leading_byte_offset_mode, bit [52,53).
110
+ uint8_t : 1, base_offset_ : 3, lbo_mode_ : 1, : 3; // 1 bit unused, 3 bits [1,4), 1 bit [4,5), 3 bits unused
111
+ // layout type, bit [61,64), SWIZZLE_NONE matrix descriptor = 0, SWIZZLE_128B matrix descriptor = 2, SWIZZLE_64B descriptor = 4, SWIZZLE_32B descriptor = 6, SWIZZLE_128B_BASE32B = 1, N/A = 3, N/A = 5, N/A = 7
112
+ uint8_t : 5, layout_type_ : 3; // 6 bits unused, 3 bits [5,8)
113
+ };
114
+ // Seperate the field, as we may only update one part of desc
115
+ struct {
116
+ uint32_t lo;
117
+ uint32_t hi;
118
+ };
119
+
120
+ // Decay to a uint64_t
121
+ CUTE_HOST_DEVICE constexpr
122
+ operator uint64_t() const noexcept { return desc_; }
123
+ };
124
+
125
+ enum class F16F32Format : uint8_t {
126
+ F16 = 0,
127
+ BF16 = 1,
128
+ TF32 = 2,
129
+ };
130
+
131
+ CUTE_HOST_DEVICE char const* to_string(F16F32Format const& t) {
132
+ switch (t) {
133
+ case F16F32Format::F16: return "F16";
134
+ case F16F32Format::BF16: return "BF16";
135
+ case F16F32Format::TF32: return "TF32";
136
+ }
137
+ return nullptr;
138
+ }
139
+
140
+ template <class T>
141
+ CUTE_HOST_DEVICE constexpr F16F32Format to_F16F32Format() {
142
+ if constexpr (is_same_v<T, half_t>) { return F16F32Format::F16; } else
143
+ if constexpr (is_same_v<T, bfloat16_t>) { return F16F32Format::BF16; } else
144
+ if constexpr (is_same_v<T, tfloat32_t>) { return F16F32Format::TF32; } else
145
+ { static_assert(sizeof(T) == 0, "Unknown type for F16F32Format"); }
146
+ }
147
+
148
+ enum class S8Format : uint8_t {
149
+ UINT8 = 0,
150
+ INT8 = 1,
151
+ };
152
+
153
+ CUTE_HOST_DEVICE char const* to_string(S8Format const& t) {
154
+ switch (t) {
155
+ case S8Format::UINT8: return "UINT8";
156
+ case S8Format::INT8: return "INT8";
157
+ }
158
+ return nullptr;
159
+ }
160
+
161
+ template <class T>
162
+ CUTE_HOST_DEVICE constexpr S8Format to_S8Format() {
163
+ if constexpr (is_same_v<T, uint8_t>) { return S8Format::UINT8; } else
164
+ if constexpr (is_same_v<T, int8_t>) { return S8Format::INT8; } else
165
+ { static_assert(sizeof(T) == 0, "Unknown type for S8Format"); }
166
+ }
167
+
168
+ enum class MXF8F6F4Format : uint8_t {
169
+ E4M3 = 0,
170
+ E5M2 = 1,
171
+ E2M3 = 3,
172
+ E3M2 = 4,
173
+ E2M1 = 5,
174
+ INVALID = 7 // an invalid datatype for runtime proxy type
175
+ };
176
+
177
+ CUTE_HOST_DEVICE char const* to_string(MXF8F6F4Format const& t) {
178
+ switch (t) {
179
+ case MXF8F6F4Format::E4M3: return "E4M3";
180
+ case MXF8F6F4Format::E5M2: return "E5M2";
181
+ case MXF8F6F4Format::E2M3: return "E2M3";
182
+ case MXF8F6F4Format::E3M2: return "E3M2";
183
+ case MXF8F6F4Format::E2M1: return "E2M1";
184
+ case MXF8F6F4Format::INVALID: return "INVALID";
185
+ }
186
+ return nullptr;
187
+ }
188
+
189
+ template <class T>
190
+ CUTE_HOST_DEVICE constexpr MXF8F6F4Format to_MXF8F6F4Format() {
191
+ if constexpr (is_same_v<T, float_e4m3_t>) { return MXF8F6F4Format::E4M3; } else
192
+ if constexpr (is_same_v<T, float_e5m2_t>) { return MXF8F6F4Format::E5M2; } else
193
+ if constexpr (is_same_v<T, detail::float_e2m3_unpacksmem_t>) { return MXF8F6F4Format::E2M3; } else
194
+ if constexpr (is_same_v<T, detail::float_e3m2_unpacksmem_t>) { return MXF8F6F4Format::E3M2; } else
195
+ if constexpr (is_same_v<T, detail::float_e2m1_unpacksmem_t>) { return MXF8F6F4Format::E2M1; } else
196
+ { static_assert(sizeof(T) == 0, "Unknown type for MXF8F6F4Format"); }
197
+ }
198
+
199
+ enum class MXF4Format : uint8_t {
200
+ E2M1 = 1,
201
+ };
202
+
203
+ CUTE_HOST_DEVICE char const* to_string(MXF4Format const& t) {
204
+ switch (t) {
205
+ case MXF4Format::E2M1: return "E2M1";
206
+ }
207
+ return nullptr;
208
+ }
209
+
210
+ template <class T>
211
+ CUTE_HOST_DEVICE constexpr MXF4Format to_MXF4Format() {
212
+ if constexpr (is_same_v<T, float_e2m1_t>) { return MXF4Format::E2M1; } else
213
+ { static_assert(sizeof(T) == 0, "Unknown type for MXF4Format"); }
214
+ }
215
+
216
+ enum class ScaleFormat : uint8_t {
217
+ UE4M3 = 0,
218
+ UE8M0 = 1,
219
+ };
220
+
221
+ CUTE_HOST_DEVICE char const* to_string(ScaleFormat const& t) {
222
+ switch (t) {
223
+ case ScaleFormat::UE4M3: return "UE4M3";
224
+ case ScaleFormat::UE8M0: return "UE8M0";
225
+ }
226
+ return nullptr;
227
+ }
228
+
229
+ template <class T>
230
+ CUTE_HOST_DEVICE constexpr ScaleFormat to_ScaleFormat() {
231
+ if constexpr (is_same_v<T, float_ue4m3_t>) { return ScaleFormat::UE4M3; } else
232
+ if constexpr (is_same_v<T, float_ue8m0_t>) { return ScaleFormat::UE8M0; } else
233
+ { static_assert(sizeof(T) == 0, "Unknown type for ScaleFormat"); }
234
+ }
235
+
236
+ enum class CFormat : uint8_t {
237
+ F16 = 0,
238
+ F32 = 1,
239
+ S32 = 2,
240
+ };
241
+
242
+ CUTE_HOST_DEVICE char const* to_string(CFormat const& t) {
243
+ switch (t) {
244
+ case CFormat::F16: return "F16";
245
+ case CFormat::F32: return "F32";
246
+ case CFormat::S32: return "S32";
247
+ }
248
+ return nullptr;
249
+ }
250
+
251
+ enum class MaxShift : uint8_t {
252
+ NoShift = 0,
253
+ MaxShift8 = 1,
254
+ MaxShift16 = 2,
255
+ MaxShift32 = 3
256
+ };
257
+
258
+ enum class BMatrixBufferId : uint8_t {
259
+ Zero = 0u,
260
+ One = 1u,
261
+ Two = 2u,
262
+ Three = 3u
263
+ };
264
+
265
+ enum class BMatrixBufferReuse : uint8_t {
266
+ Keep = 1u,
267
+ Reuse = 2u,
268
+ ReuseAndKeep = 3u
269
+ };
270
+
271
+ // using MaskAndShiftB = uint32_t[2];
272
+ union MaskAndShiftB
273
+ {
274
+ uint32_t uri[2];
275
+
276
+ struct {
277
+ // Bitfield implementation avoids the need for shifts in assignment
278
+ uint8_t start_count_ [4]; // bit [ 0:32) : 8 bits each. Specifies the start count for mask generation.
279
+ uint32_t first_span_ : 4, // bit [32:36) : 1 bit each. 0 = start where B is used. 1 = start with where B is skipped(0 value is used).
280
+ : 3, //
281
+ nzm_ : 1, // bit [39:40) : 0 = Enable the mask. 1 = Disable the mask.
282
+ skip_span_ : 8, // bit [40:48) : Count-1 (zero encoded in this field specifies use span of 1) of consecutive columns where 0 value is used.
283
+ use_span_ : 8, // bit [48:55) : Count-1 (zero encoded in this field specifies use span of 1) of consecutive columns where B matrix data is used.
284
+ shift_ : 6, // bit [56:62) : Shift value for B matrix data.
285
+ : 2;
286
+ };
287
+ };
288
+
289
+ template <typename ShapeType, int FLT_S, int CTA_M, int CTA_N>
290
+ CUTE_HOST_DEVICE constexpr auto
291
+ make_column_zero_mask(ShapeType conv_q, int32_t cta_coord_q, int32_t num_pixels_skip_left) {
292
+
293
+ static_assert(cute::is_same_v<ShapeType, cutlass::FastDivmod> || cute::is_integral<ShapeType>::value);
294
+
295
+ cute::array<MaskAndShiftB, FLT_S> column_zero_masks{};
296
+
297
+ static_assert(FLT_S == 3, "Filter size not supported.");
298
+ constexpr int MAX_USE_SPAN_COUNT = 256;
299
+ constexpr int MAX_SKIP_SPAN_COUNT = 256;
300
+
301
+ // conv_q_int used for non-divmod case (add/minus/..)
302
+ // conv_q used for divmod case (div/mod/...)
303
+ int32_t conv_q_int = int(conv_q);
304
+ auto [_, cta_q] = divmod(cta_coord_q * CTA_N, conv_q);
305
+
306
+ int step_q = CTA_M == 128 ? CTA_N / 1
307
+ : CTA_M == 64 ? CTA_N / 2
308
+ : CTA_M == 32 ? CTA_N / 4
309
+ : 0;
310
+
311
+ for (int mask_iter = 0; mask_iter < int(CTA_N / step_q); ++mask_iter) {
312
+
313
+ for (int s_iter = 0; s_iter < FLT_S; s_iter += 1) {
314
+
315
+ int32_t skip_span{0}, use_span{0}, nzm{1}, first_span{0}, start_count{0}, shift{0};
316
+
317
+ shift = s_iter;
318
+
319
+ // Examples for CZM setting
320
+ // CASE0: (skip_span_ < 0)
321
+ // | padding |<- conv_q ->|
322
+ // |skip_span_|<- use_span ->|skip_span_|
323
+ // -skip_span 0 ^cta_q conv_q-1
324
+ // 0 ^index
325
+ //
326
+ // CASE1: (skip_span_ > 0)
327
+ // |<- conv_q ->|
328
+ // |skip_span_|<- use_span ->|skip_span_|
329
+ // 0 ^cta_q conv_q-1
330
+ // 0 ^index
331
+ //
332
+ // line 0 an input vector from 0 to conv_q with the padding
333
+ // line 1 shows the different spans we need to skip or load
334
+ // lines 2-3 show the different coordinates of different boundaries.
335
+ // CTQ_q is the coordinate of the present cta.
336
+
337
+ int32_t skip_span_ = num_pixels_skip_left - shift;
338
+ int32_t index{0};
339
+ if (skip_span_ > 0) {
340
+ auto [_, index_mod] = divmod(cta_q, conv_q);
341
+ index = index_mod;
342
+ } else if (skip_span_ < 0) {
343
+ auto [_, index_mod] = divmod((cta_q - skip_span_), conv_q);
344
+ index = index_mod;
345
+ } else {
346
+ nzm = 0;
347
+ }
348
+ skip_span = cute::max(cute::abs(skip_span_), 1);
349
+ use_span = cute::min(conv_q_int - static_cast<int32_t>(skip_span), MAX_USE_SPAN_COUNT);
350
+ if (use_span > 0) {
351
+ first_span = index >= skip_span ? 0 : 1;
352
+ if ((first_span == 0) && (index + CTA_N < conv_q_int + skip_span)) {
353
+ nzm = 0;
354
+ } else {
355
+ start_count = first_span == 0 ? (use_span - (conv_q_int - index)) : index;
356
+ }
357
+ } else {
358
+ skip_span = MAX_SKIP_SPAN_COUNT;
359
+ use_span = 1;
360
+ first_span = 1;
361
+ start_count = 0;
362
+ }
363
+
364
+ column_zero_masks[s_iter].start_count_[mask_iter] = start_count;
365
+ column_zero_masks[s_iter].first_span_ |= first_span << mask_iter;
366
+ column_zero_masks[s_iter].nzm_ |= nzm;
367
+ column_zero_masks[s_iter].skip_span_ = skip_span - 1;
368
+ column_zero_masks[s_iter].use_span_ = use_span - 1;
369
+ column_zero_masks[s_iter].shift_ = shift;
370
+
371
+ }
372
+
373
+ cta_q += step_q;
374
+ }
375
+
376
+ return column_zero_masks;
377
+ }
378
+
379
+ template <class T>
380
+ CUTE_HOST_DEVICE constexpr auto to_UMMAFormat() {
381
+ if constexpr (is_same_v<T, half_t>) { return F16F32Format::F16; } else
382
+ if constexpr (is_same_v<T, bfloat16_t>) { return F16F32Format::BF16; } else
383
+ if constexpr (is_same_v<T, tfloat32_t>) { return F16F32Format::TF32; } else
384
+ if constexpr (is_same_v<T, uint8_t>) { return S8Format::UINT8; } else
385
+ if constexpr (is_same_v<T, int8_t>) { return S8Format::INT8; } else
386
+ if constexpr (is_same_v<T, type_erased_dynamic_float8_t>) {return MXF8F6F4Format::INVALID; } else
387
+
388
+ if constexpr (is_same_v<T, type_erased_dynamic_float6_t>) {return MXF8F6F4Format::INVALID; } else
389
+ if constexpr (is_same_v<T, type_erased_dynamic_float4_t>) {return MXF8F6F4Format::INVALID; } else
390
+ if constexpr (is_same_v<T, detail::type_erased_dynamic_float4_unpacksmem_t>) {return MXF8F6F4Format::INVALID; } else
391
+
392
+ if constexpr (is_same_v<T, float_e4m3_t>) { return MXF8F6F4Format::E4M3; } else
393
+ if constexpr (is_same_v<T, float_e5m2_t>) { return MXF8F6F4Format::E5M2; } else
394
+ if constexpr (is_same_v<T, detail::type_erased_dynamic_float6_unpacksmem_t>) {return MXF8F6F4Format::INVALID; } else
395
+ if constexpr (is_same_v<T, detail::float_e2m3_unpacksmem_t>) { return MXF8F6F4Format::E2M3; } else
396
+ if constexpr (is_same_v<T, detail::float_e3m2_unpacksmem_t>) { return MXF8F6F4Format::E3M2; } else
397
+ if constexpr (is_same_v<T, float_e2m3_t>) { return MXF8F6F4Format::E2M3; } else
398
+ if constexpr (is_same_v<T, float_e3m2_t>) { return MXF8F6F4Format::E3M2; } else
399
+ if constexpr (is_same_v<T, detail::float_e2m1_unpacksmem_t>) { return MXF8F6F4Format::E2M1; } else
400
+ if constexpr (is_same_v<T, float_e2m1_t>) { return MXF4Format::E2M1; } else
401
+ { static_assert(sizeof(T) == 0, "Unknown type for UMMAFormat"); }
402
+ }
403
+
404
+ template <class T>
405
+ CUTE_HOST_DEVICE constexpr CFormat to_CFormat() {
406
+ if constexpr (is_same_v<T, half_t>) { return CFormat::F16; } else
407
+ if constexpr (is_same_v<T, float>) { return CFormat::F32; } else
408
+ if constexpr (is_same_v<T, int32_t>) { return CFormat::S32; } else
409
+ { static_assert(sizeof(T) == 0, "Unknown type for CFormat"); }
410
+ }
411
+
412
+ union InstrDescriptor
413
+ {
414
+ uint32_t desc_;
415
+
416
+ struct {
417
+ // Bitfield implementation avoids the need for shifts in assignment
418
+ uint16_t sparse_id2_ : 2, // bit [ 0, 2) : Sparse meta data id2
419
+ sparse_flag_ : 1, // bit [ 2, 3) : 0 = dense. 1 = sparse. 1 value valid only for F32F16/S8/MXF8F6F4
420
+ saturate_ : 1, // bit [ 3, 4) : 0 = no saturate. 1 = saturate. 1 value valid only for S8
421
+ c_format_ : 2, // bit [ 4, 6) : 0 = F16. 1 = F32, 2 = S32
422
+ : 1, //
423
+ a_format_ : 3, // bit [ 7,10) : MXF8F6F4Format:0 = E4M3, 1 = E5M2, 3 = E2M3, 4 = E3M2, 5 = E2M1. F32F16Format: 0 = F16, 1 = BF16, 2 = TF32. S8: 0 unsigned 8 bit, 1 signed 8 bit. Boolean MMA: 0 Boolean
424
+ b_format_ : 3, // bit [10,13) : MXF8F6F4Format:0 = E4M3, 1 = E5M2, 3 = E2M3, 4 = E3M2, 5 = E2M1. F32F16Format: 0 = F16, 1 = BF16, 2 = TF32. S8: 0 unsigned 8 bit, 1 signed 8 bit. Boolean MMA: 0 Boolean
425
+ a_negate_ : 1, // bit [13,14) : 0 = no negate. 1 = negate. 1 value valid only for F32F16Format and MXF8F6F4Format
426
+ b_negate_ : 1, // bit [14,15) : 0 = no negate. 1 = negate. 1 value valid only for F32F16Format and MXF8F6F4Format
427
+ a_major_ : 1; // bit [15,16) : 0 = K-major. 1 = MN-major. Major value of 1 is only valid for E4M3, E5M2, INT8 (signed and unsigned), F16, BF16 and TF32 source formats
428
+ uint16_t b_major_ : 1, // bit [16,17) : 0 = K-major. 1 = MN-major. Major value of 1 is only valid for E4M3, E5M2, INT8 (signed and unsigned), F16, BF16 and TF32 source formats
429
+ n_dim_ : 6, // bit [17,23) : 3 LSBs not included. Valid values range from 1 (N=8) to 32 (N=256). All values are not valid for all instruction formats
430
+ : 1, //
431
+ m_dim_ : 5, // bit [24,29) : 4 LSBs not included. Valid values are: 4 (M=64), 8 (M=128), 16 (M=256)
432
+ : 1, //
433
+ max_shift_ : 2; // bit [30,32) : Maximum shift for WS instruction. Encoded as follows: 0 = no shift, 1 = maximum shift of 8, 2 = maximum shift of 16, 3 = maximum shift of 32.
434
+ };
435
+
436
+ // Decay to a uint32_t
437
+ CUTE_HOST_DEVICE constexpr explicit
438
+ operator uint32_t() const noexcept { return desc_; }
439
+ };
440
+
441
+ union InstrDescriptorBlockScaled
442
+ {
443
+ uint32_t desc_;
444
+
445
+ struct {
446
+ // Bitfield implementation avoids the need for shifts in assignment
447
+ uint16_t sparse_id2_ : 2, // bit [ 0, 2) : Sparse meta data id2
448
+ sparse_flag_ : 1, // bit [ 2, 3) : 0 = dense. 1 = sparse. 1 value valid only for F32F16/S8/MXF8F6F4
449
+ : 1, //
450
+ b_sf_id_ : 2, // bit [ 4, 6) : Matrix B Scale Factor ID
451
+ : 1, //
452
+ a_format_ : 3, // bit [ 7, 9) : MXF8F6F4Format:0 = E4M3, 1 = E5M2, 3 = E2M3, 4 = E3M2, 5 = E2M1. F32F16Format: 0 = F16, 1 = BF16, 2 = TF32. S8: 0 unsigned 8 bit, 1 signed 8 bit. BMMA: 0 Boolean
453
+ b_format_ : 3, // bit [10,12) : MXF8F6F4Format:0 = E4M3, 1 = E5M2, 3 = E2M3, 4 = E3M2, 5 = E2M1. F32F16Format: 0 = F16, 1 = BF16, 2 = TF32. S8: 0 unsigned 8 bit, 1 signed 8 bit. BMMA: 0 Boolean
454
+ a_negate_ : 1, // bit [13,14) : 0 = no negate. 1 = negate. 1 value valid only for F32F16Format and MXF8F6F4Format
455
+ b_negate_ : 1, // bit [14,15) : 0 = no negate. 1 = negate. 1 value valid only for F32F16Format and MXF8F6F4Format
456
+ a_major_ : 1; // bit [15,16) : 0 = K-major. 1 = MN-major. Major value of 1 is only valid for E4M3, E5M2, INT8 (signed and unsigned), F16, BF16 and TF32 source formats
457
+ uint16_t b_major_ : 1, // bit [16,17) : 0 = K-major. 1 = MN-major. Major value of 1 is only valid for E4M3, E5M2, INT8 (signed and unsigned), F16, BF16 and TF32 source formats
458
+ n_dim_ : 6, // bit [17,23) : 3 LSBs not included. Valid values range from 1 (N=8) to 32 (N=256). All values are not valid for all instruction formats
459
+ scale_format_ : 1, // bit [23,24) : 0=E4M3, 1=E8M0
460
+ m_dim_ : 5, // bit [24,29) : 4 LSBs not included. Valid values are: 4 (M=64), 8 (M=128), 16 (M=256)
461
+ a_sf_id_ : 2, // bit [29,31) : Matrix A Scale Factor ID
462
+ : 1; //
463
+ };
464
+
465
+ // Decay to a uint32_t
466
+ CUTE_HOST_DEVICE constexpr
467
+ operator uint32_t() const noexcept { return desc_; }
468
+ };
469
+
470
+ template <class a_type, class b_type, class c_type,
471
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
472
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
473
+ UMMA::Saturate c_sat = UMMA::Saturate::False,
474
+ bool is_sparse = false,
475
+ UMMA::MaxShift max_shift = UMMA::MaxShift::NoShift>
476
+ CUTE_HOST_DEVICE constexpr
477
+ UMMA::InstrDescriptor
478
+ make_instr_desc()
479
+ {
480
+ UMMA::InstrDescriptor desc_i = {};
481
+
482
+ desc_i.a_format_ = uint8_t(UMMA::to_UMMAFormat<a_type>());
483
+ desc_i.b_format_ = uint8_t(UMMA::to_UMMAFormat<b_type>());
484
+ desc_i.c_format_ = uint8_t(UMMA::to_CFormat<c_type>());
485
+
486
+ desc_i.m_dim_ = (M >> 4);
487
+ desc_i.n_dim_ = (N >> 3);
488
+
489
+ desc_i.a_major_ = uint8_t(a_major);
490
+ desc_i.b_major_ = uint8_t(b_major);
491
+
492
+ desc_i.a_negate_ = uint8_t(a_neg);
493
+ desc_i.b_negate_ = uint8_t(b_neg);
494
+ desc_i.saturate_ = uint8_t(c_sat);
495
+
496
+ desc_i.sparse_flag_ = is_sparse; // 1 = Sparse
497
+ desc_i.sparse_id2_ = 0;
498
+
499
+ desc_i.max_shift_ = uint8_t(max_shift);
500
+
501
+ return desc_i;
502
+ }
503
+
504
+ template <class a_type, class b_type, class c_type,
505
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
506
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
507
+ UMMA::Saturate c_sat = UMMA::Saturate::False,
508
+ bool is_sparse = false,
509
+ UMMA::MaxShift max_shift = UMMA::MaxShift::NoShift>
510
+ CUTE_HOST_DEVICE
511
+ constexpr uint64_t
512
+ make_runtime_instr_desc(uint16_t sparse_id2 = 0u, uint32_t tmem_e = 0u) {
513
+ UMMA::InstrDescriptor desc_i = UMMA::make_instr_desc<
514
+ a_type, b_type, c_type, M, N, a_major, b_major, a_neg, b_neg, c_sat, is_sparse,
515
+ max_shift>();
516
+
517
+ if constexpr (is_sparse) {
518
+ desc_i.sparse_id2_ = sparse_id2;
519
+ }
520
+ else {
521
+ assert(sparse_id2 == 0u);
522
+ }
523
+ // In current compiler exposure, idescE is a uint64_t. It should contain:
524
+ // - Lower 32b URe: Specifies the tmem address that stores the sparse metadata.
525
+ // Only needed for Sparse MMA instructions. Otherwise, ignored.
526
+ // - Upper 32b URh: Specifies the instruction descriptor.
527
+ uint64_t idescE = (static_cast<uint64_t>(static_cast<uint32_t>(desc_i)) << 32);
528
+
529
+ return idescE;
530
+ }
531
+
532
+ template <bool is_sparse = false>
533
+ CUTE_HOST_DEVICE
534
+ constexpr uint64_t
535
+ make_runtime_instr_desc(UMMA::InstrDescriptor desc_i, uint16_t sparse_id2 = 0u, uint32_t tmem_e = 0u)
536
+ {
537
+ if constexpr (is_sparse) {
538
+ desc_i.sparse_id2_ = sparse_id2;
539
+ }
540
+ else {
541
+ assert(sparse_id2 == 0u);
542
+ }
543
+ // In current compiler exposure, idescE is a uint64_t. It should contain:
544
+ // - Lower 32b URe: Specifies the tmem address that stores the sparse metadata.
545
+ // Only needed for Sparse MMA instructions. Otherwise, ignored.
546
+ // - Upper 32b URh: Specifies the instruction descriptor.
547
+ uint64_t idescE = (static_cast<uint64_t>(static_cast<uint32_t>(desc_i)) << 32);
548
+
549
+ return idescE;
550
+ }
551
+
552
+ template <class a_type, class b_type, class c_type, class sf_type,
553
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
554
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
555
+ bool is_sparse = false
556
+ >
557
+ CUTE_HOST_DEVICE constexpr
558
+ UMMA::InstrDescriptorBlockScaled
559
+ make_instr_desc_block_scaled()
560
+ {
561
+ UMMA::InstrDescriptorBlockScaled desc_i = {};
562
+
563
+ desc_i.a_format_ = uint8_t(UMMA::to_UMMAFormat<a_type>());
564
+ desc_i.b_format_ = uint8_t(UMMA::to_UMMAFormat<b_type>());
565
+
566
+ desc_i.scale_format_ = uint8_t(UMMA::to_ScaleFormat<sf_type>());
567
+ desc_i.a_sf_id_ = 0;
568
+ desc_i.b_sf_id_ = 0;
569
+
570
+ desc_i.m_dim_ = (M >> 4);
571
+ desc_i.n_dim_ = (N >> 3);
572
+
573
+ desc_i.a_major_ = uint8_t(a_major);
574
+ desc_i.b_major_ = uint8_t(b_major);
575
+
576
+ desc_i.a_negate_ = uint8_t(a_neg);
577
+ desc_i.b_negate_ = uint8_t(b_neg);
578
+ desc_i.sparse_flag_ = is_sparse; // 1 = Sparse
579
+ desc_i.sparse_id2_ = 0;
580
+
581
+ // Below would bring some warnings.
582
+ #if defined(__GNUC__)
583
+ # pragma GCC diagnostic ignored "-Wconversion"
584
+ #endif
585
+ return desc_i;
586
+ }
587
+
588
+ template <class a_type, class b_type, class c_type, class sf_type,
589
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
590
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
591
+ bool is_sparse = false>
592
+ CUTE_HOST_DEVICE
593
+ constexpr uint64_t
594
+ make_runtime_instr_desc_block_scaled(uint32_t const tmem_sfa_addr, uint32_t const tmem_sfb_addr,
595
+ uint16_t const sparse_id2 = 0u, uint32_t const tmem_e = 0u)
596
+ {
597
+ UMMA::InstrDescriptorBlockScaled desc_i = UMMA::make_instr_desc_block_scaled<
598
+ a_type, b_type, c_type, sf_type, M, N,
599
+ a_major, b_major,
600
+ a_neg, b_neg,
601
+ is_sparse>();
602
+
603
+ // The first 2-bits of TMEM address includes byte address.
604
+ desc_i.a_sf_id_ = (tmem_sfa_addr & 0xC0000000) >> 30;
605
+ desc_i.b_sf_id_ = (tmem_sfb_addr & 0xC0000000) >> 30;
606
+
607
+ if constexpr (is_sparse) {
608
+ desc_i.sparse_id2_ = sparse_id2;
609
+ }
610
+ else {
611
+ assert(sparse_id2 == 0u);
612
+ }
613
+
614
+ // In current compiler exposure, idescE is a uint64_t. It should contain:
615
+ // - Lower 32b URe: Specifies the tmem address that stores the sparse metadata.
616
+ // Only needed for Sparse MMA instructions. Otherwise, ignored.
617
+ // - Upper 32b URh: Specifies the instruction descriptor.
618
+ uint64_t idescE = (static_cast<uint64_t>(static_cast<uint32_t>(desc_i)) << 32);
619
+
620
+ return idescE;
621
+ }
622
+
623
+ template <bool is_sparse = false>
624
+ CUTE_HOST_DEVICE
625
+ constexpr uint64_t
626
+ make_runtime_instr_desc_block_scaled(UMMA::InstrDescriptorBlockScaled desc_i,
627
+ uint32_t const tmem_sfa_addr, uint32_t const tmem_sfb_addr,
628
+ uint16_t const sparse_id2 = 0u, uint32_t const tmem_e = 0u)
629
+ {
630
+ // The first 2-bits of TMEM address includes byte address.
631
+ desc_i.a_sf_id_ = (tmem_sfa_addr & 0xC0000000) >> 30;
632
+ desc_i.b_sf_id_ = (tmem_sfb_addr & 0xC0000000) >> 30;
633
+
634
+ if constexpr (is_sparse) {
635
+ desc_i.sparse_id2_ = sparse_id2;
636
+ }
637
+ else {
638
+ assert(sparse_id2 == 0u);
639
+ }
640
+
641
+ // In current compiler exposure, idescE is a uint64_t. It should contain:
642
+ // - Lower 32b URe: Specifies the tmem address that stores the sparse metadata.
643
+ // Only needed for Sparse MMA instructions. Otherwise, ignored.
644
+ // - Upper 32b URh: Specifies the instruction descriptor.
645
+ uint64_t idescE = (static_cast<uint64_t>(static_cast<uint32_t>(desc_i)) << 32);
646
+
647
+ return idescE;
648
+ }
649
+
650
+ } // end namespace UMMA
651
+ } // namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm100_umma.hpp ADDED
@@ -0,0 +1,1616 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+
32
+ #pragma once
33
+
34
+ #include <cute/arch/config.hpp>
35
+ #include <cute/arch/mma.hpp>
36
+ #include <cute/arch/mma_sm100.hpp>
37
+ #include <cute/arch/mma_sm100_desc.hpp>
38
+ #include <cute/arch/cluster_sm90.hpp>
39
+
40
+ namespace cute
41
+ {
42
+
43
+ template <class a_type, class b_type, class c_type,
44
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
45
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
46
+ struct SM100_MMA_TF32_SS
47
+ {
48
+ static_assert(M == 64 || M == 128, "SM100_MMA_TF32 M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
49
+ static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
50
+ (M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
51
+ "SM100_MMA_TF32 N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
52
+ or a multiple of 16 between 16 and 256 for M=128.");
53
+
54
+ using DRegisters = void;
55
+ using ARegisters = uint64_t[1];
56
+ using BRegisters = uint64_t[1];
57
+ using CRegisters = uint32_t[1];
58
+
59
+ CUTE_HOST_DEVICE static void
60
+ fma(uint64_t const& desc_a,
61
+ uint64_t const& desc_b,
62
+ uint32_t const& tmem_c,
63
+ uint32_t const& scaleC,
64
+ uint64_t const& idescE)
65
+ {
66
+ #if defined(CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED)
67
+ if (cute::elect_one_sync()) {
68
+ uint32_t mask[4] = {0, 0, 0, 0};
69
+ asm volatile(
70
+ "{\n\t"
71
+ ".reg .pred p;\n\t"
72
+ "setp.ne.b32 p, %4, 0;\n\t"
73
+ "tcgen05.mma.cta_group::1.kind::tf32 [%0], %1, %2, %3, {%5, %6, %7, %8}, p; \n\t"
74
+ "}\n"
75
+ :
76
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
77
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]));
78
+ }
79
+ #else
80
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_TF32_SS without CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED");
81
+ #endif
82
+ }
83
+ };
84
+
85
+ template <class a_type, class b_type, class c_type,
86
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
87
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
88
+ struct SM100_MMA_F16BF16_SS
89
+ {
90
+ static_assert(M == 64 || M == 128, "SM100_MMA_F16BF16 M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
91
+ static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
92
+ (M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
93
+ "SM100_MMA_F16BF16 N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
94
+ or a multiple of 16 between 16 and 256 for M=128.");
95
+
96
+ using DRegisters = void;
97
+ using ARegisters = uint64_t[1];
98
+ using BRegisters = uint64_t[1];
99
+ using CRegisters = uint32_t[1];
100
+
101
+ CUTE_HOST_DEVICE static void
102
+ fma(uint64_t const& desc_a,
103
+ uint64_t const& desc_b,
104
+ uint32_t const& tmem_c,
105
+ uint32_t const& scaleC,
106
+ uint64_t const& idescE)
107
+ {
108
+ #if defined(CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED)
109
+ if (cute::elect_one_sync()) {
110
+ uint32_t mask[4] = {0, 0, 0, 0};
111
+ asm volatile(
112
+ "{\n\t"
113
+ ".reg .pred p;\n\t"
114
+ "setp.ne.b32 p, %4, 0;\n\t"
115
+ "tcgen05.mma.cta_group::1.kind::f16 [%0], %1, %2, %3, {%5, %6, %7, %8}, p; \n\t"
116
+ "}\n"
117
+ :
118
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
119
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]));
120
+ }
121
+ #else
122
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_SS without CUTE_ARCH_MMA_SM100A_ENABLED");
123
+ #endif
124
+ }
125
+ };
126
+
127
+ template <class a_type, class b_type, class c_type,
128
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
129
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
130
+ UMMA::Saturate c_sat = UMMA::Saturate::False>
131
+ struct SM100_MMA_TF32_TS
132
+ {
133
+ static_assert(M == 64 || M == 128, "SM100_MMA_TF32 M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
134
+ static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
135
+ (M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
136
+ "SM100_MMA_TF32 N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
137
+ or a multiple of 16 between 16 and 256 for M=128.");
138
+ static_assert(a_major == UMMA::Major::K, "SM100_MMA_TF32 A from TMEM can't be transposed");
139
+
140
+ using DRegisters = void;
141
+ using ARegisters = uint32_t[1];
142
+ using BRegisters = uint64_t[1];
143
+ using CRegisters = uint32_t[1];
144
+
145
+ CUTE_HOST_DEVICE static void
146
+ fma(uint32_t const& tmem_a,
147
+ uint64_t const& desc_b,
148
+ uint32_t const& tmem_c,
149
+ uint32_t const& scaleC,
150
+ uint64_t const& idescE)
151
+ {
152
+ #if defined(CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED)
153
+ uint32_t mask[4] = {0, 0, 0, 0};
154
+ if (cute::elect_one_sync()) {
155
+ asm volatile(
156
+ "{\n\t"
157
+ ".reg .pred p;\n\t"
158
+ "setp.ne.b32 p, %4, 0;\n\t"
159
+ "tcgen05.mma.cta_group::1.kind::tf32 [%0], [%1], %2, %3, {%5, %6, %7, %8}, p; \n\t"
160
+ "}\n"
161
+ :
162
+ : "r"(tmem_c), "r"(tmem_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
163
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]));
164
+ }
165
+ #else
166
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_TF32_TS without CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED");
167
+ #endif
168
+ }
169
+ };
170
+
171
+ template <class a_type, class b_type, class c_type,
172
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
173
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
174
+ UMMA::Saturate c_sat = UMMA::Saturate::False>
175
+ struct SM100_MMA_F16BF16_TS
176
+ {
177
+ static_assert(M == 64 || M == 128, "SM100_MMA_F16BF16 M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
178
+ static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
179
+ (M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
180
+ "SM100_MMA_F16BF16 N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
181
+ or a multiple of 16 between 16 and 256 for M=128.");
182
+ static_assert(a_major == UMMA::Major::K, "SM100_MMA_F16BF16 A from TMEM can't be transposed");
183
+
184
+ using DRegisters = void;
185
+ using ARegisters = uint32_t[1];
186
+ using BRegisters = uint64_t[1];
187
+ using CRegisters = uint32_t[1];
188
+
189
+ CUTE_HOST_DEVICE static void
190
+ fma(uint32_t const& tmem_a,
191
+ uint64_t const& desc_b,
192
+ uint32_t const& tmem_c,
193
+ uint32_t const& scaleC,
194
+ uint64_t const& idescE)
195
+ {
196
+ #if defined(CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED)
197
+ uint32_t mask[4] = {0, 0, 0, 0};
198
+ if (cute::elect_one_sync()) {
199
+ asm volatile(
200
+ "{\n\t"
201
+ ".reg .pred p;\n\t"
202
+ "setp.ne.b32 p, %4, 0;\n\t"
203
+ "tcgen05.mma.cta_group::1.kind::f16 [%0], [%1], %2, %3, {%5, %6, %7, %8}, p; \n\t"
204
+ "}\n"
205
+ :
206
+ : "r"(tmem_c), "r"(tmem_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
207
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]));
208
+ }
209
+ #else
210
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_TS without CUTE_ARCH_MMA_SM100A_ENABLED");
211
+ #endif
212
+ }
213
+ };
214
+
215
+ template <class a_type, class b_type, class c_type,
216
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major, uint32_t ScaleC,
217
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
218
+ struct SM100_MMA_F16BF16_SS_SCALED
219
+ {
220
+ static_assert(M == 64 || M == 128, "SM100_MMA_F16BF16_SS_SCALED M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
221
+ static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
222
+ (M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
223
+ "SM100_MMA_F16BF16_SS_SCALED N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
224
+ or a multiple of 16 between 16 and 256 for M=128.");
225
+
226
+ using DRegisters = void;
227
+ using ARegisters = uint64_t[1];
228
+ using BRegisters = uint64_t[1];
229
+ using CRegisters = uint32_t[1];
230
+
231
+ CUTE_HOST_DEVICE static void
232
+ fma(uint64_t const& desc_a,
233
+ uint64_t const& desc_b,
234
+ uint32_t const& tmem_c,
235
+ uint32_t const& accumulate,
236
+ uint64_t const& idescE)
237
+ {
238
+ #if defined(CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED)
239
+ if (cute::elect_one_sync()) {
240
+ // ScaleC input should be a literal or compile time constant
241
+ uint32_t mask[4] = {0, 0, 0, 0};
242
+ asm volatile(
243
+ "{\n\t"
244
+ ".reg .pred p;\n\t"
245
+ "setp.ne.b32 p, %4, 0;\n\t"
246
+ "tcgen05.mma.cta_group::1.kind::f16 [%0], %1, %2, %3, {%5, %6, %7, %8}, p, %9; \n\t"
247
+ "}\n"
248
+ :
249
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(accumulate),
250
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]), "n"(ScaleC));
251
+ }
252
+ #else
253
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_SS without CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED");
254
+ #endif
255
+ }
256
+ };
257
+
258
+ template <class a_type, class b_type, class c_type,
259
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major, uint32_t ScaleC,
260
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
261
+ UMMA::Saturate c_sat = UMMA::Saturate::False>
262
+ struct SM100_MMA_F16BF16_TS_SCALED
263
+ {
264
+ static_assert(M == 64 || M == 128, "SM100_MMA_F16BF16_TS_SCALED M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
265
+ static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
266
+ (M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
267
+ "SM100_MMA_F16BF16_TS_SCALED N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
268
+ or a multiple of 16 between 16 and 256 for M=128.");
269
+ static_assert(a_major == UMMA::Major::K, "SM100_MMA_F16BF16_TS_SCALED A from TMEM can't be transposed");
270
+
271
+ using DRegisters = void;
272
+ using ARegisters = uint32_t[1];
273
+ using BRegisters = uint64_t[1];
274
+ using CRegisters = uint32_t[1];
275
+
276
+ CUTE_HOST_DEVICE static void
277
+ fma(uint32_t const& tmem_a,
278
+ uint64_t const& desc_b,
279
+ uint32_t const& tmem_c,
280
+ uint32_t const& accumulate,
281
+ uint64_t const& idescE)
282
+ {
283
+ #if defined(CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED)
284
+ if (cute::elect_one_sync()) {
285
+ // ScaleC input should be a literal or compile time constant
286
+ uint32_t mask[4] = {0, 0, 0, 0};
287
+ asm volatile(
288
+ "{\n\t"
289
+ ".reg .pred p;\n\t"
290
+ "setp.ne.b32 p, %4, 0;\n\t"
291
+ "tcgen05.mma.cta_group::1.kind::f16 [%0], [%1], %2, %3, {%5, %6, %7, %8}, p, %9; \n\t"
292
+ "}\n"
293
+ :
294
+ : "r"(tmem_c), "r"(tmem_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(accumulate),
295
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]), "n"(ScaleC));
296
+ }
297
+ #else
298
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_TS_SCALED without CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED");
299
+ #endif
300
+ }
301
+ };
302
+
303
+ template <class a_type, class b_type, class c_type,
304
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
305
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
306
+ struct SM100_MMA_TF32_SS_SPARSE
307
+ {
308
+ static_assert(M == 64 || M == 128, "SM100_MMA_TF32_SS_SPARSE M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
309
+ static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
310
+ (M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
311
+ "SM100_MMA_TF32_SS_SPARSE N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
312
+ or a multiple of 16 between 16 and 256 for M=128.");
313
+
314
+ using DRegisters = void;
315
+ using ARegisters = uint64_t[1];
316
+ using BRegisters = uint64_t[1];
317
+ using CRegisters = uint32_t[1];
318
+
319
+ CUTE_HOST_DEVICE static void
320
+ fma(uint64_t const& desc_a,
321
+ uint64_t const& desc_b,
322
+ uint32_t const& tmem_c,
323
+ uint32_t const& scaleC,
324
+ uint64_t const& idescE,
325
+ uint32_t const& tmem_e)
326
+ {
327
+ #if defined(CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED)
328
+ if (cute::elect_one_sync()) {
329
+ uint32_t mask[4] = {0, 0, 0, 0};
330
+ asm volatile(
331
+ "{\n\t"
332
+ ".reg .pred p;\n\t"
333
+ "setp.ne.b32 p, %4, 0;\n\t"
334
+ "tcgen05.mma.sp.cta_group::1.kind::tf32 [%0], %1, %2, [%9], %3, {%5, %6, %7, %8}, p; \n\t"
335
+ "}\n"
336
+ :
337
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
338
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]), "r"(tmem_e));
339
+ }
340
+ #else
341
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_TF32_SS_SPARSE without CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED");
342
+ #endif
343
+ }
344
+ };
345
+
346
+ template <class a_type, class b_type, class c_type,
347
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
348
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
349
+ struct SM100_MMA_F16BF16_SS_SPARSE
350
+ {
351
+ static_assert(M == 64 || M == 128, "SM100_MMA_F16BF16_SS_SPARSE M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
352
+ static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
353
+ (M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
354
+ "SM100_MMA_F16BF16_SS_SPARSE N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
355
+ or a multiple of 16 between 16 and 256 for M=128.");
356
+
357
+ using DRegisters = void;
358
+ using ARegisters = uint64_t[1];
359
+ using BRegisters = uint64_t[1];
360
+ using CRegisters = uint32_t[1];
361
+
362
+ CUTE_HOST_DEVICE static void
363
+ fma(uint64_t const& desc_a,
364
+ uint64_t const& desc_b,
365
+ uint32_t const& tmem_c,
366
+ uint32_t const& scaleC,
367
+ uint64_t const& idescE,
368
+ uint32_t const& tmem_e)
369
+ {
370
+ #if defined(CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED)
371
+ if (cute::elect_one_sync()) {
372
+ uint32_t mask[4] = {0, 0, 0, 0};
373
+ asm volatile(
374
+ "{\n\t"
375
+ ".reg .pred p;\n\t"
376
+ "setp.ne.b32 p, %4, 0;\n\t"
377
+ "tcgen05.mma.sp.cta_group::1.kind::f16 [%0], %1, %2, [%9], %3, {%5, %6, %7, %8}, p; \n\t"
378
+ "}\n"
379
+ :
380
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
381
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]), "r"(tmem_e));
382
+ }
383
+ #else
384
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_SS_SPARSE without CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED");
385
+ #endif
386
+ }
387
+ };
388
+
389
+ template <class a_type, class b_type, class c_type,
390
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
391
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
392
+ struct SM100_MMA_TF32_2x1SM_SS
393
+ {
394
+ static_assert(M == 128 || M == 256, "SM100_MMA_TF32_2x1SM_SS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
395
+ static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_TF32_2x1SM_SS N-mode size should be a multiple of 32 between 32 and 256.");
396
+
397
+ using DRegisters = void;
398
+ using ARegisters = uint64_t[1];
399
+ using BRegisters = uint64_t[1];
400
+ using CRegisters = uint32_t[1];
401
+
402
+ CUTE_HOST_DEVICE static void
403
+ fma(uint64_t const& desc_a,
404
+ uint64_t const& desc_b,
405
+ uint32_t const& tmem_c,
406
+ uint32_t const& scaleC,
407
+ uint64_t const& idescE)
408
+ {
409
+ #if defined(CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED)
410
+ if (cute::elect_one_sync()) {
411
+ uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
412
+ asm volatile(
413
+ "{\n\t"
414
+ ".reg .pred p;\n\t"
415
+ "setp.ne.b32 p, %4, 0;\n\t"
416
+ "tcgen05.mma.cta_group::2.kind::tf32 [%0], %1, %2, %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p; \n\t"
417
+ "}\n"
418
+ :
419
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
420
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
421
+ "r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]));
422
+ }
423
+ #else
424
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_TF32_2x1SM_SS without CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED");
425
+ #endif
426
+ }
427
+ };
428
+
429
+ template <class a_type, class b_type, class c_type,
430
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
431
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
432
+ struct SM100_MMA_F16BF16_2x1SM_SS
433
+ {
434
+ static_assert(M == 128 || M == 256, "SM100_MMA_F16BF16_2x1SM_SS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
435
+ static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_F16BF16_2x1SM_SS N-mode size should be a multiple of 32 between 32 and 256.");
436
+
437
+ using DRegisters = void;
438
+ using ARegisters = uint64_t[1];
439
+ using BRegisters = uint64_t[1];
440
+ using CRegisters = uint32_t[1];
441
+
442
+ CUTE_HOST_DEVICE static void
443
+ fma(uint64_t const& desc_a,
444
+ uint64_t const& desc_b,
445
+ uint32_t const& tmem_c,
446
+ uint32_t const& scaleC,
447
+ uint64_t const& idescE)
448
+ {
449
+ #if defined(CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED)
450
+ if (cute::elect_one_sync()) {
451
+ uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
452
+ asm volatile(
453
+ "{\n\t"
454
+ ".reg .pred p;\n\t"
455
+ "setp.ne.b32 p, %4, 0;\n\t"
456
+ "tcgen05.mma.cta_group::2.kind::f16 [%0], %1, %2, %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p; \n\t"
457
+ "}\n"
458
+ :
459
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
460
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
461
+ "r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]));
462
+ }
463
+ #else
464
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_2x1SM_SS without CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED");
465
+ #endif
466
+ }
467
+ };
468
+
469
+ template <class a_type, class b_type, class c_type,
470
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
471
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
472
+ UMMA::Saturate c_sat = UMMA::Saturate::False>
473
+ struct SM100_MMA_TF32_2x1SM_TS
474
+ {
475
+ static_assert(M == 128 || M == 256, "SM100_MMA_TF32_2x1SM_TS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
476
+ static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_TF32_2x1SM_TS N-mode size should be a multiple of 32 between 32 and 256.");
477
+ static_assert(a_major == UMMA::Major::K, "SM100_MMA_TF32_2x1SM_TS A from TMEM can't be transposed");
478
+
479
+ using DRegisters = void;
480
+ using ARegisters = uint32_t[1];
481
+ using BRegisters = uint64_t[1];
482
+ using CRegisters = uint32_t[1];
483
+
484
+ CUTE_HOST_DEVICE static void
485
+ fma(uint32_t const& tmem_a,
486
+ uint64_t const& desc_b,
487
+ uint32_t const& tmem_c,
488
+ uint32_t const& scaleC,
489
+ uint64_t const& idescE)
490
+ {
491
+ #if defined(CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED)
492
+ if (cute::elect_one_sync()) {
493
+ uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
494
+ asm volatile(
495
+ "{\n\t"
496
+ ".reg .pred p;\n\t"
497
+ "setp.ne.b32 p, %4, 0;\n\t"
498
+ "tcgen05.mma.cta_group::2.kind::tf32 [%0], [%1], %2, %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p; \n\t"
499
+ "}\n"
500
+ :
501
+ : "r"(tmem_c), "r"(tmem_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
502
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
503
+ "r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]));
504
+ }
505
+ #else
506
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_TF32_2x1SM_TS without CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED");
507
+ #endif
508
+ }
509
+ };
510
+
511
+ template <class a_type, class b_type, class c_type,
512
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
513
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
514
+ UMMA::Saturate c_sat = UMMA::Saturate::False>
515
+ struct SM100_MMA_F16BF16_2x1SM_TS
516
+ {
517
+ static_assert(M == 128 || M == 256, "SM100_MMA_F16BF16_2x1SM_TS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
518
+ static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_F16BF16_2x1SM_TS N-mode size should be a multiple of 32 between 32 and 256.");
519
+ static_assert(a_major == UMMA::Major::K, "SM100_MMA_F16BF16_2x1SM_TS A from TMEM can't be transposed");
520
+
521
+ using DRegisters = void;
522
+ using ARegisters = uint32_t[1];
523
+ using BRegisters = uint64_t[1];
524
+ using CRegisters = uint32_t[1];
525
+
526
+ CUTE_HOST_DEVICE static void
527
+ fma(uint32_t const& tmem_a,
528
+ uint64_t const& desc_b,
529
+ uint32_t const& tmem_c,
530
+ uint32_t const& scaleC,
531
+ uint64_t const& idescE)
532
+ {
533
+ #if defined(CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED)
534
+ if (cute::elect_one_sync()) {
535
+ uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
536
+ asm volatile(
537
+ "{\n\t"
538
+ ".reg .pred p;\n\t"
539
+ "setp.ne.b32 p, %4, 0;\n\t"
540
+ "tcgen05.mma.cta_group::2.kind::f16 [%0], [%1], %2, %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p; \n\t"
541
+ "}\n"
542
+ :
543
+ : "r"(tmem_c), "r"(tmem_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
544
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
545
+ "r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]));
546
+ }
547
+ #else
548
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_2x1SM_TS without CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED");
549
+ #endif
550
+ }
551
+ };
552
+
553
+ template <class a_type, class b_type, class c_type,
554
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major, uint32_t ScaleC,
555
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
556
+ struct SM100_MMA_F16BF16_2x1SM_SS_SCALED
557
+ {
558
+ static_assert(M == 128 || M == 256, "SM100_MMA_F16BF16_2x1SM_SS_SCALED M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
559
+ static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_F16BF16_2x1SM_SS_SCALED N-mode size should be a multiple of 32 between 32 and 256.");
560
+
561
+ using DRegisters = void;
562
+ using ARegisters = uint64_t[1];
563
+ using BRegisters = uint64_t[1];
564
+ using CRegisters = uint32_t[1];
565
+
566
+ CUTE_HOST_DEVICE static void
567
+ fma(uint64_t const& desc_a,
568
+ uint64_t const& desc_b,
569
+ uint32_t const& tmem_c,
570
+ uint32_t const& accumulate,
571
+ uint64_t const& idescE)
572
+ {
573
+ #if defined(CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED)
574
+ if (cute::elect_one_sync()) {
575
+ // ScaleC input should be a literal or compile time constant
576
+ uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
577
+ asm volatile(
578
+ "{\n\t"
579
+ ".reg .pred p;\n\t"
580
+ "setp.ne.b32 p, %4, 0;\n\t"
581
+ "tcgen05.mma.cta_group::2.kind::f16 [%0], %1, %2, %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p, %13; \n\t"
582
+ "}\n"
583
+ :
584
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(accumulate),
585
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
586
+ "r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]), "n"(ScaleC));
587
+ }
588
+ #else
589
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_2x1SM_SS_SCALED without CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED");
590
+ #endif
591
+ }
592
+ };
593
+
594
+ template <class a_type, class b_type, class c_type,
595
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major, uint32_t ScaleC,
596
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
597
+ UMMA::Saturate c_sat = UMMA::Saturate::False>
598
+ struct SM100_MMA_F16BF16_2x1SM_TS_SCALED
599
+ {
600
+ static_assert(M == 128 || M == 256, "SM100_MMA_F16BF16_2x1SM_TS_SCALED M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
601
+ static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_F16BF16_2x1SM_TS_SCALED N-mode size should be a multiple of 32 between 32 and 256.");
602
+ static_assert(a_major == UMMA::Major::K, "SM100_MMA_F16BF16_2x1SM_TS_SCALED A from TMEM can't be transposed");
603
+
604
+ using DRegisters = void;
605
+ using ARegisters = uint32_t[1];
606
+ using BRegisters = uint64_t[1];
607
+ using CRegisters = uint32_t[1];
608
+
609
+ CUTE_HOST_DEVICE static void
610
+ fma(uint32_t const& tmem_a,
611
+ uint64_t const& desc_b,
612
+ uint32_t const& tmem_c,
613
+ uint32_t const& accumulate,
614
+ uint64_t idescE)
615
+ {
616
+ #if defined(CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED)
617
+ if (cute::elect_one_sync()) {
618
+ // ScaleC input should be a literal or compile time constant
619
+ uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
620
+ asm volatile(
621
+ "{\n\t"
622
+ ".reg .pred p;\n\t"
623
+ "setp.ne.b32 p, %4, 0;\n\t"
624
+ "tcgen05.mma.cta_group::2.kind::f16 [%0], [%1], %2, %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p, %13; \n\t"
625
+ "}\n"
626
+ :
627
+ : "r"(tmem_c), "r"(tmem_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(accumulate),
628
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
629
+ "r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]), "n"(ScaleC));
630
+ }
631
+ #else
632
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_2x1SM_TS_SCALED without CUTE_ARCH_TCGEN05_F16BF16_MMA_SCALED_ENABLED");
633
+ #endif
634
+ }
635
+ };
636
+
637
+ template <class a_type, class b_type, class c_type,
638
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
639
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
640
+ struct SM100_MMA_TF32_2x1SM_SS_SPARSE
641
+ {
642
+ static_assert(M == 128 || M == 256, "SM100_MMA_TF32_2x1SM_SS_SPARSE M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
643
+ static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_TF32_2x1SM_SS_SPARSE N-mode size should be a multiple of 32 between 32 and 256.");
644
+
645
+ using DRegisters = void;
646
+ using ARegisters = uint64_t[1];
647
+ using BRegisters = uint64_t[1];
648
+ using CRegisters = uint32_t[1];
649
+
650
+ CUTE_HOST_DEVICE static void
651
+ fma(uint64_t const& desc_a,
652
+ uint64_t const& desc_b,
653
+ uint32_t const& tmem_c,
654
+ uint32_t const& scaleC,
655
+ uint64_t const& idescE,
656
+ uint32_t const& tmem_e)
657
+ {
658
+ #if defined(CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED)
659
+ if (cute::elect_one_sync()) {
660
+ uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
661
+ asm volatile(
662
+ "{\n\t"
663
+ ".reg .pred p;\n\t"
664
+ "setp.ne.b32 p, %4, 0;\n\t"
665
+ "tcgen05.mma.sp.cta_group::2.kind::tf32 [%0], %1, %2, [%13], %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p; \n\t"
666
+ "}\n"
667
+ :
668
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
669
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
670
+ "r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]), "r"(tmem_e));
671
+ }
672
+ #else
673
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_TF32_2x1SM_SS_SPARSE without CUTE_ARCH_TCGEN05_TF32_MMA_ENABLED");
674
+ #endif
675
+ }
676
+ };
677
+
678
+ template <class a_type, class b_type, class c_type,
679
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
680
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
681
+ struct SM100_MMA_F16BF16_2x1SM_SS_SPARSE
682
+ {
683
+ static_assert(M == 128 || M == 256, "SM100_MMA_F16BF16_2x1SM_SS_SPARSE M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
684
+ static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_F16BF16_2x1SM_SS_SPARSE N-mode size should be a multiple of 32 between 32 and 256.");
685
+
686
+ using DRegisters = void;
687
+ using ARegisters = uint64_t[1];
688
+ using BRegisters = uint64_t[1];
689
+ using CRegisters = uint32_t[1];
690
+
691
+ CUTE_HOST_DEVICE static void
692
+ fma(uint64_t const& desc_a,
693
+ uint64_t const& desc_b,
694
+ uint32_t const& tmem_c,
695
+ uint32_t const& scaleC,
696
+ uint64_t const& idescE,
697
+ uint32_t const& tmem_e)
698
+ {
699
+ #if defined(CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED)
700
+ if (cute::elect_one_sync()) {
701
+ uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
702
+ asm volatile(
703
+ "{\n\t"
704
+ ".reg .pred p;\n\t"
705
+ "setp.ne.b32 p, %4, 0;\n\t"
706
+ "tcgen05.mma.sp.cta_group::2.kind::f16 [%0], %1, %2, [%13], %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p; \n\t"
707
+ "}\n"
708
+ :
709
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
710
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
711
+ "r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]), "r"(tmem_e));
712
+ }
713
+ #else
714
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F16BF16_2x1SM_SS_SPARSE without CUTE_ARCH_TCGEN05_F16F32_MMA_ENABLED");
715
+ #endif
716
+ }
717
+ };
718
+
719
+ template <class a_type, class b_type, class c_type,
720
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
721
+ UMMA::Saturate c_sat = UMMA::Saturate::False>
722
+ struct SM100_MMA_S8_SS
723
+ {
724
+ static_assert(is_same_v<c_type, int32_t>, "SM100_MMA_S8_SS result type can only be int32_t.");
725
+ static_assert(M == 64 || M == 128, "SM100_MMA_S8_SS M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
726
+ static_assert(N == 8 || ((N % 16 == 0) && (16 <= N) && (N <= 256)), "SM100_MMA_S8_SS N-mode size should be 8 or a multiple of 16 between 16 and 256.");
727
+
728
+ using DRegisters = void;
729
+ using ARegisters = uint64_t[1];
730
+ using BRegisters = uint64_t[1];
731
+ using CRegisters = uint32_t[1];
732
+
733
+ CUTE_HOST_DEVICE static void
734
+ fma(uint64_t const& desc_a,
735
+ uint64_t const& desc_b,
736
+ uint32_t const& tmem_c,
737
+ uint32_t const& scaleC,
738
+ uint64_t const& idescE)
739
+ {
740
+ #if defined(CUTE_ARCH_TCGEN05_S8_MMA_ENABLED)
741
+ if (cute::elect_one_sync()) {
742
+ uint32_t mask[4] = {0, 0, 0, 0};
743
+ asm volatile(
744
+ "{\n\t"
745
+ ".reg .pred p;\n\t"
746
+ "setp.ne.b32 p, %4, 0;\n\t"
747
+ "tcgen05.mma.cta_group::1.kind::i8 [%0], %1, %2, %3, {%5, %6, %7, %8}, p; \n\t"
748
+ "}\n"
749
+ :
750
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
751
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]));
752
+ }
753
+ #else
754
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_S8_SS without CUTE_ARCH_TCGEN05_S8_MMA_ENABLED");
755
+ #endif
756
+ }
757
+ };
758
+
759
+ template <class a_type, class b_type, class c_type,
760
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
761
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
762
+ UMMA::Saturate c_sat = UMMA::Saturate::False>
763
+ struct SM100_MMA_S8_TS
764
+ {
765
+ static_assert(M == 64 || M == 128, "SM100_MMA_S8_TS M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
766
+ static_assert(N == 8 || ((N % 16 == 0) && (16 <= N) && (N <= 256)), "SM100_MMA_S8_TS N-mode size should be 8 or a multiple of 16 between 16 and 256.");
767
+ static_assert(a_major == UMMA::Major::K, "SM100_MMA_S8_TS A from TMEM can't be transposed");
768
+
769
+ using DRegisters = void;
770
+ using ARegisters = uint32_t[1];
771
+ using BRegisters = uint64_t[1];
772
+ using CRegisters = uint32_t[1];
773
+
774
+ CUTE_HOST_DEVICE static void
775
+ fma(uint32_t const& tmem_a,
776
+ uint64_t const& desc_b,
777
+ uint32_t const& tmem_c,
778
+ uint32_t const& scaleC,
779
+ uint64_t const& idescE)
780
+ {
781
+ #if defined(CUTE_ARCH_TCGEN05_S8_MMA_ENABLED)
782
+ if (cute::elect_one_sync()) {
783
+ uint32_t mask[4] = {0, 0, 0, 0};
784
+ asm volatile(
785
+ "{\n\t"
786
+ ".reg .pred p;\n\t"
787
+ "setp.ne.b32 p, %4, 0;\n\t"
788
+ "tcgen05.mma.cta_group::1.kind::i8 [%0], [%1], %2, %3, {%5, %6, %7, %8}, p; \n\t"
789
+ "}\n"
790
+ :
791
+ : "r"(tmem_c), "r"(tmem_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
792
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]));
793
+ }
794
+ #else
795
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_S8_TS without CUTE_ARCH_TCGEN05_S8_MMA_ENABLED");
796
+ #endif
797
+ }
798
+ };
799
+
800
+ template <class a_type, class b_type, class c_type,
801
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
802
+ UMMA::Saturate c_sat = UMMA::Saturate::False>
803
+ struct SM100_MMA_S8_SS_SPARSE
804
+ {
805
+ static_assert(is_same_v<c_type, int32_t>, "SM100_MMA_S8_SS_SPARSE result type can only be int32_t.");
806
+ static_assert(M == 64 || M == 128, "SM100_MMA_S8_SS_SPARSE M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
807
+ static_assert(N == 8 || ((N % 16 == 0) && (16 <= N) && (N <= 256)), "SM100_MMA_S8_SS_SPARSE N-mode size should be 8 or a multiple of 16 between 16 and 256.");
808
+
809
+ using DRegisters = void;
810
+ using ARegisters = uint64_t[1];
811
+ using BRegisters = uint64_t[1];
812
+ using CRegisters = uint32_t[1];
813
+
814
+ CUTE_HOST_DEVICE static void
815
+ fma(uint64_t const& desc_a,
816
+ uint64_t const& desc_b,
817
+ uint32_t const& tmem_c,
818
+ uint32_t const& scaleC,
819
+ uint64_t const& idescE,
820
+ uint32_t const& tmem_e)
821
+ {
822
+ #if defined(CUTE_ARCH_TCGEN05_S8_MMA_ENABLED)
823
+ if (cute::elect_one_sync()) {
824
+ uint32_t mask[4] = {0, 0, 0, 0};
825
+ asm volatile(
826
+ "{\n\t"
827
+ ".reg .pred p;\n\t"
828
+ "setp.ne.b32 p, %4, 0;\n\t"
829
+ "tcgen05.mma.sp.cta_group::1.kind::i8 [%0], %1, %2, [%9], %3, {%5, %6, %7, %8}, p; \n\t"
830
+ "}\n"
831
+ :
832
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
833
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]), "r"(tmem_e));
834
+ }
835
+ #else
836
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_S8_SS_SPARSE without CUTE_ARCH_TCGEN05_S8_MMA_ENABLED");
837
+ #endif
838
+ }
839
+ };
840
+
841
+ template <class a_type, class b_type, class c_type,
842
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
843
+ UMMA::Saturate c_sat = UMMA::Saturate::False>
844
+ struct SM100_MMA_S8_2x1SM_SS
845
+ {
846
+ static_assert(M == 128 || M == 256, "SM100_MMA_S8_2x1SM_SS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
847
+ static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_S8_2x1SM_SS N-mode size should be a multiple of 32 between 32 and 256.");
848
+
849
+ using DRegisters = void;
850
+ using ARegisters = uint64_t[1];
851
+ using BRegisters = uint64_t[1];
852
+ using CRegisters = uint32_t[1];
853
+
854
+ CUTE_HOST_DEVICE static void
855
+ fma(uint64_t const& desc_a,
856
+ uint64_t const& desc_b,
857
+ uint32_t const& tmem_c,
858
+ uint32_t const& scaleC,
859
+ uint64_t const& idescE)
860
+ {
861
+ #if defined(CUTE_ARCH_TCGEN05_S8_MMA_ENABLED)
862
+ if (cute::elect_one_sync()) {
863
+ uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
864
+ asm volatile(
865
+ "{\n\t"
866
+ ".reg .pred p;\n\t"
867
+ "setp.ne.b32 p, %4, 0;\n\t"
868
+ "tcgen05.mma.cta_group::2.kind::i8 [%0], %1, %2, %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p; \n\t"
869
+ "}\n"
870
+ :
871
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
872
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
873
+ "r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]));
874
+ }
875
+ #else
876
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_S8_2x1SM_SS without CUTE_ARCH_TCGEN05_S8_MMA_ENABLED");
877
+ #endif
878
+ }
879
+ };
880
+
881
+ template <class a_type, class b_type, class c_type,
882
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
883
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
884
+ UMMA::Saturate c_sat = UMMA::Saturate::False>
885
+ struct SM100_MMA_S8_2x1SM_TS
886
+ {
887
+ static_assert(M == 128 || M == 256, "SM100_MMA_S8_2x1SM_TS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
888
+ static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_S8_2x1SM_TS N-mode size should be a multiple of 32 between 32 and 256.");
889
+ static_assert(a_major == UMMA::Major::K, "SM100_MMA_S8_2x1SM_TS A from TMEM can't be transposed");
890
+
891
+ using DRegisters = void;
892
+ using ARegisters = uint32_t[1];
893
+ using BRegisters = uint64_t[1];
894
+ using CRegisters = uint32_t[1];
895
+
896
+ CUTE_HOST_DEVICE static void
897
+ fma(uint32_t const& tmem_a,
898
+ uint64_t const& desc_b,
899
+ uint32_t const& tmem_c,
900
+ uint32_t const& scaleC,
901
+ uint64_t const& idescE)
902
+ {
903
+ #if defined(CUTE_ARCH_TCGEN05_S8_MMA_ENABLED)
904
+ if (cute::elect_one_sync()) {
905
+ uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
906
+ asm volatile(
907
+ "{\n\t"
908
+ ".reg .pred p;\n\t"
909
+ "setp.ne.b32 p, %4, 0;\n\t"
910
+ "tcgen05.mma.cta_group::2.kind::i8 [%0], [%1], %2, %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p; \n\t"
911
+ "}\n"
912
+ :
913
+ : "r"(tmem_c), "r"(tmem_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
914
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
915
+ "r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]));
916
+ }
917
+ #else
918
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_S8_2x1SM_TS without CUTE_ARCH_TCGEN05_S8_MMA_ENABLED");
919
+ #endif
920
+ }
921
+ };
922
+
923
+ template <class a_type, class b_type, class c_type,
924
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
925
+ UMMA::Saturate c_sat = UMMA::Saturate::False>
926
+ struct SM100_MMA_S8_2x1SM_SS_SPARSE
927
+ {
928
+ static_assert(M == 128 || M == 256, "SM100_MMA_S8 M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
929
+ static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_S8 N-mode size should be a multiple of 32 between 32 and 256.");
930
+
931
+ using DRegisters = void;
932
+ using ARegisters = uint64_t[1];
933
+ using BRegisters = uint64_t[1];
934
+ using CRegisters = uint32_t[1];
935
+
936
+ CUTE_HOST_DEVICE static void
937
+ fma(uint64_t const& desc_a,
938
+ uint64_t const& desc_b,
939
+ uint32_t const& tmem_c,
940
+ uint32_t const& scaleC,
941
+ uint64_t const& idescE,
942
+ uint32_t const& tmem_e)
943
+ {
944
+ #if defined(CUTE_ARCH_TCGEN05_S8_MMA_ENABLED)
945
+ if (cute::elect_one_sync()) {
946
+ uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
947
+ asm volatile(
948
+ "{\n\t"
949
+ ".reg .pred p;\n\t"
950
+ "setp.ne.b32 p, %4, 0;\n\t"
951
+ "tcgen05.mma.sp.cta_group::2.kind::i8 [%0], %1, %2, [%13], %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p; \n\t"
952
+ "}\n"
953
+ :
954
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
955
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
956
+ "r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]), "r"(tmem_e));
957
+ }
958
+ #else
959
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_S8_2x1SM_SS_SPARSE without CUTE_ARCH_TCGEN05_S8_MMA_ENABLED");
960
+ #endif
961
+ }
962
+ };
963
+
964
+ struct SM100_MMA_F8F6F4_SS
965
+ {
966
+ using DRegisters = void;
967
+ using ARegisters = uint64_t[1];
968
+ using BRegisters = uint64_t[1];
969
+ using CRegisters = uint32_t[1];
970
+
971
+ CUTE_HOST_DEVICE static void
972
+ fma(uint64_t const& desc_a,
973
+ uint64_t const& desc_b,
974
+ uint32_t const& tmem_c,
975
+ uint32_t const& scaleC,
976
+ uint64_t const& idescE)
977
+ {
978
+ #if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
979
+ if (cute::elect_one_sync()) {
980
+ uint32_t mask[4] = {0, 0, 0, 0};
981
+ asm volatile(
982
+ "{\n\t"
983
+ ".reg .pred p;\n\t"
984
+ "setp.ne.b32 p, %4, 0;\n\t"
985
+ "tcgen05.mma.cta_group::1.kind::f8f6f4 [%0], %1, %2, %3, {%5, %6, %7, %8}, p; \n\t"
986
+ "}\n"
987
+ :
988
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
989
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]));
990
+ }
991
+ #else
992
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_SS without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
993
+ #endif
994
+ }
995
+ };
996
+
997
+ template <class a_type, class b_type, class c_type, class sf_type,
998
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
999
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
1000
+ struct SM100_MMA_MXF8F6F4_SS
1001
+ {
1002
+ static_assert(M == 128, "SM100_MMA_MXF8F6F4_SS M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
1003
+ static_assert((N % 8 == 0) && (8 <= N) && (N <= 256), "SM100_MMA_MXF8F6F4_SS N-mode size should be a multiple of 8 between 8 and 256.");
1004
+
1005
+ using DRegisters = void;
1006
+ using ARegisters = uint64_t[1];
1007
+ using BRegisters = uint64_t[1];
1008
+ using CRegisters = uint32_t[1];
1009
+ using SFARegisters = uint32_t[1];
1010
+ using SFBRegisters = uint32_t[1];
1011
+
1012
+ CUTE_HOST_DEVICE static void
1013
+ fma(uint64_t const& desc_a,
1014
+ uint64_t const& desc_b,
1015
+ uint32_t const& tmem_c,
1016
+ uint32_t const& scaleC,
1017
+ uint64_t const& idescE,
1018
+ uint32_t const& tsfa_addr,
1019
+ uint32_t const& tsfb_addr)
1020
+ {
1021
+ #if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
1022
+ if (cute::elect_one_sync()) {
1023
+ asm volatile(
1024
+ "{\n\t"
1025
+ ".reg .pred p;\n\t"
1026
+ "setp.ne.b32 p, %4, 0;\n\t"
1027
+ "tcgen05.mma.cta_group::1.kind::mxf8f6f4.block_scale [%0], %1, %2, %3, [%5], [%6], p; \n\t"
1028
+ "}\n"
1029
+ :
1030
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC), "r"(tsfa_addr), "r"(tsfb_addr));
1031
+ }
1032
+ #else
1033
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_SS without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
1034
+ #endif
1035
+ }
1036
+ };
1037
+
1038
+ template <class a_type, class b_type, class c_type,
1039
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
1040
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
1041
+ UMMA::Saturate c_sat = UMMA::Saturate::False>
1042
+ struct SM100_MMA_F8F6F4_TS
1043
+ {
1044
+ static_assert(M == 64 || M == 128, "SM100_MMA_F8F6F4_TS M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
1045
+ static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
1046
+ (M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
1047
+ "SM100_MMA_F8F6F4_TS N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
1048
+ or a multiple of 16 between 16 and 256 for M=128.");
1049
+ static_assert(a_major == UMMA::Major::K, "SM100_MMA_F8F6F4_TS A from TMEM can't be transposed");
1050
+
1051
+ using DRegisters = void;
1052
+ using ARegisters = uint32_t[1];
1053
+ using BRegisters = uint64_t[1];
1054
+ using CRegisters = uint32_t[1];
1055
+
1056
+ CUTE_HOST_DEVICE static void
1057
+ fma(uint32_t const& tmem_a,
1058
+ uint64_t const& desc_b,
1059
+ uint32_t const& tmem_c,
1060
+ uint32_t const& scaleC,
1061
+ uint64_t const& idescE)
1062
+ {
1063
+ #if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
1064
+ if (cute::elect_one_sync()) {
1065
+ uint32_t mask[4] = {0, 0, 0, 0};
1066
+ asm volatile(
1067
+ "{\n\t"
1068
+ ".reg .pred p;\n\t"
1069
+ "setp.ne.b32 p, %4, 0;\n\t"
1070
+ "tcgen05.mma.cta_group::1.kind::f8f6f4 [%0], [%1], %2, %3, {%5, %6, %7, %8}, p; \n\t"
1071
+ "}\n"
1072
+ :
1073
+ : "r"(tmem_c), "r"(tmem_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
1074
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]));
1075
+ }
1076
+ #else
1077
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_TS without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
1078
+ #endif
1079
+ }
1080
+ };
1081
+
1082
+ template <class a_type, class b_type, class c_type,
1083
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
1084
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One,
1085
+ UMMA::Saturate c_sat = UMMA::Saturate::False>
1086
+ struct SM100_MMA_F8F6F4_2x1SM_TS
1087
+ {
1088
+ static_assert(M == 128 || M == 256, "SM100_MMA_F8F6F4_2x1SM_TS M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
1089
+ static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_F8F6F4_2x1SM_TS N-mode size should be a multiple of 32 between 32 and 256.");
1090
+ static_assert(a_major == UMMA::Major::K, "SM100_MMA_F8F6F4_2x1SM_TS A from TMEM can't be transposed");
1091
+
1092
+ using DRegisters = void;
1093
+ using ARegisters = uint32_t[1];
1094
+ using BRegisters = uint64_t[1];
1095
+ using CRegisters = uint32_t[1];
1096
+
1097
+ CUTE_HOST_DEVICE static void
1098
+ fma(uint32_t const& tmem_a,
1099
+ uint64_t const& desc_b,
1100
+ uint32_t const& tmem_c,
1101
+ uint32_t const& scaleC,
1102
+ uint64_t const& idescE)
1103
+ {
1104
+ #if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
1105
+ if (cute::elect_one_sync()) {
1106
+ uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1107
+ asm volatile(
1108
+ "{\n\t"
1109
+ ".reg .pred p;\n\t"
1110
+ "setp.ne.b32 p, %4, 0;\n\t"
1111
+ "tcgen05.mma.cta_group::2.kind::f8f6f4 [%0], [%1], %2, %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p; \n\t"
1112
+ "}\n"
1113
+ :
1114
+ : "r"(tmem_c), "r"(tmem_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
1115
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
1116
+ "r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]));
1117
+ }
1118
+ #else
1119
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_TS without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
1120
+ #endif
1121
+ }
1122
+ };
1123
+
1124
+ template <class a_type, class b_type, class c_type,
1125
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
1126
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
1127
+ struct SM100_MMA_F8F6F4_SS_SPARSE
1128
+ {
1129
+ static_assert(M == 64 || M == 128, "SM100_MMA_F8F6F4_SS_SPARSE M-mode size should be 64 or 128 for 1 CTA cluster MMA.");
1130
+ static_assert((M == 64 && (N % 8 == 0) && (8 <= N) && (N <= 256)) ||
1131
+ (M == 128 && (N % 16 == 0) && (16 <= N) && (N <= 256)),
1132
+ "SM100_MMA_F8F6F4_SS_SPARSE N-mode size should be a multiple of 8 between 8 and 256 for M=64,\
1133
+ or a multiple of 16 between 16 and 256 for M=128.");
1134
+
1135
+ using DRegisters = void;
1136
+ using ARegisters = uint64_t[1];
1137
+ using BRegisters = uint64_t[1];
1138
+ using CRegisters = uint32_t[1];
1139
+
1140
+ CUTE_HOST_DEVICE static void
1141
+ fma(uint64_t const& desc_a,
1142
+ uint64_t const& desc_b,
1143
+ uint32_t const& tmem_c,
1144
+ uint32_t const& scaleC,
1145
+ uint64_t const& idescE,
1146
+ uint32_t const& tmem_e)
1147
+ {
1148
+ #if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
1149
+ if (cute::elect_one_sync()) {
1150
+ uint32_t mask[4] = {0, 0, 0, 0}; // %5, %6, %7, %8
1151
+ asm volatile(
1152
+ "{\n\t"
1153
+ ".reg .pred p;\n\t"
1154
+ "setp.ne.b32 p, %4, 0;\n\t"
1155
+ "tcgen05.mma.sp.cta_group::1.kind::f8f6f4 [%0], %1, %2, [%9], %3, {%5, %6, %7, %8}, p; \n\t"
1156
+ "}\n"
1157
+ :
1158
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
1159
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]), "r"(tmem_e));
1160
+ }
1161
+ #else
1162
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_SS_SPARSE without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
1163
+ #endif
1164
+ }
1165
+ };
1166
+
1167
+ template <class a_type, class b_type, class c_type, class sf_type,
1168
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
1169
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
1170
+ struct SM100_MMA_MXF8F6F4_SS_SPARSE
1171
+ {
1172
+ static_assert(M == 128, "SM100_MMA_MXF8F6F4_SS_SPARSE M-mode size should be 128 for 1 CTA cluster MMA.");
1173
+ static_assert((N % 8 == 0) && (8 <= N) && (N <= 256), "SM100_MMA_MXF8F6F4_SS_SPARSE N-mode size should be a multiple of 8 between 8 and 256.");
1174
+
1175
+ using DRegisters = void;
1176
+ using ARegisters = uint64_t[1];
1177
+ using BRegisters = uint64_t[1];
1178
+ using CRegisters = uint32_t[1];
1179
+ using SFARegisters = uint32_t[1];
1180
+ using SFBRegisters = uint32_t[1];
1181
+
1182
+ CUTE_HOST_DEVICE static void
1183
+ fma(uint64_t const& desc_a,
1184
+ uint64_t const& desc_b,
1185
+ uint32_t const& tmem_c,
1186
+ uint32_t const& scaleC,
1187
+ uint64_t const& idescE,
1188
+ uint32_t const& tsfa_addr,
1189
+ uint32_t const& tsfb_addr,
1190
+ uint32_t const& tmem_e)
1191
+ {
1192
+ #if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
1193
+ if (cute::elect_one_sync()) {
1194
+ asm volatile(
1195
+ "{\n\t"
1196
+ ".reg .pred p;\n\t"
1197
+ "setp.ne.b32 p, %4, 0;\n\t"
1198
+ "tcgen05.mma.sp.cta_group::1.kind::mxf8f6f4.block_scale [%0], %1, %2, [%7], %3, [%5], [%6], p; \n\t"
1199
+ "}\n"
1200
+ :
1201
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC), "r"(tsfa_addr), "r"(tsfb_addr), "r"(tmem_e));
1202
+ }
1203
+ #else
1204
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_MXF8F6F4_SS_SPARSE without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
1205
+ #endif
1206
+ }
1207
+ };
1208
+
1209
+ struct SM100_MMA_F8F6F4_2x1SM_SS
1210
+ {
1211
+ using DRegisters = void;
1212
+ using ARegisters = uint64_t[1];
1213
+ using BRegisters = uint64_t[1];
1214
+ using CRegisters = uint32_t[1];
1215
+
1216
+ CUTE_HOST_DEVICE static void
1217
+ fma(uint64_t const& desc_a,
1218
+ uint64_t const& desc_b,
1219
+ uint32_t const& tmem_c,
1220
+ uint32_t const& scaleC,
1221
+ uint64_t const& idescE)
1222
+ {
1223
+ #if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
1224
+ if (cute::elect_one_sync()) {
1225
+ uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1226
+ asm volatile(
1227
+ "{\n\t"
1228
+ ".reg .pred p;\n\t"
1229
+ "setp.ne.b32 p, %4, 0;\n\t"
1230
+ "tcgen05.mma.cta_group::2.kind::f8f6f4 [%0], %1, %2, %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p; \n\t"
1231
+ "}\n"
1232
+ :
1233
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
1234
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
1235
+ "r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]));
1236
+ }
1237
+ #else
1238
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_2x1SM_SS without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
1239
+ #endif
1240
+ }
1241
+ };
1242
+
1243
+ template <class a_type, class b_type, class c_type, class sf_type,
1244
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
1245
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
1246
+ struct SM100_MMA_MXF8F6F4_2x1SM_SS_SPARSE
1247
+ {
1248
+ static_assert(M == 256, "SM100_MMA_MXF8F6F4_2x1SM_SS_SPARSE M-mode size should be 256 for 2 CTA cluster MMA.");
1249
+ static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_MXF8F6F4_2x1SM_SS_SPARSE N-mode size should be a multiple of 16 between 16 and 256.");
1250
+
1251
+ using DRegisters = void;
1252
+ using ARegisters = uint64_t[1];
1253
+ using BRegisters = uint64_t[1];
1254
+ using CRegisters = uint32_t[1];
1255
+
1256
+ CUTE_HOST_DEVICE static void
1257
+ fma(uint64_t const& desc_a,
1258
+ uint64_t const& desc_b,
1259
+ uint32_t const& tmem_c,
1260
+ uint32_t const& scaleC,
1261
+ uint64_t const& idescE,
1262
+ uint32_t const& tsfa_addr,
1263
+ uint32_t const& tsfb_addr,
1264
+ uint32_t const& tmem_e)
1265
+ {
1266
+ #if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
1267
+ if (cute::elect_one_sync()) {
1268
+ asm volatile(
1269
+ "{\n\t"
1270
+ ".reg .pred p;\n\t"
1271
+ "setp.ne.b32 p, %4, 0;\n\t"
1272
+ "tcgen05.mma.sp.cta_group::2.kind::mxf8f6f4.block_scale [%0], %1, %2, [%7], %3, [%5], [%6], p; \n\t"
1273
+ "}\n"
1274
+ :
1275
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
1276
+ "r"(tsfa_addr), "r"(tsfb_addr), "r"(tmem_e));
1277
+ }
1278
+ #else
1279
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_MXF8F6F4_2x1SM_SS_SPARSE without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
1280
+ #endif
1281
+ }
1282
+ };
1283
+
1284
+ template <class a_type, class b_type, class c_type, class sf_type,
1285
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
1286
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
1287
+ struct SM100_MMA_MXF8F6F4_2x1SM_SS
1288
+ {
1289
+ static_assert(M == 256, "SM100_MMA_MXF8F6F4_2x1SM_SS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
1290
+ static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_MXF8F6F4_2x1SM_SS N-mode size should be a multiple of 16 between 16 and 256.");
1291
+
1292
+ using DRegisters = void;
1293
+ using ARegisters = uint64_t[1];
1294
+ using BRegisters = uint64_t[1];
1295
+ using CRegisters = uint32_t[1];
1296
+
1297
+ CUTE_HOST_DEVICE static void
1298
+ fma(uint64_t const& desc_a,
1299
+ uint64_t const& desc_b,
1300
+ uint32_t const& tmem_c,
1301
+ uint32_t const& scaleC,
1302
+ uint64_t const& idescE,
1303
+ uint32_t const& tsfa_addr,
1304
+ uint32_t const& tsfb_addr)
1305
+ {
1306
+ #if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
1307
+ if (cute::elect_one_sync()) {
1308
+ asm volatile(
1309
+ "{\n\t"
1310
+ ".reg .pred p;\n\t"
1311
+ "setp.ne.b32 p, %4, 0;\n\t"
1312
+ "tcgen05.mma.cta_group::2.kind::mxf8f6f4.block_scale [%0], %1, %2, %3, [%5], [%6], p; \n\t"
1313
+ "}\n"
1314
+ :
1315
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
1316
+ "r"(tsfa_addr), "r"(tsfb_addr));
1317
+ }
1318
+ #else
1319
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_MXF8F6F4_2x1SM_SS without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
1320
+ #endif
1321
+ }
1322
+ };
1323
+
1324
+ template <class a_type, class b_type, class c_type,
1325
+ int M, int N, UMMA::Major a_major, UMMA::Major b_major,
1326
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
1327
+ struct SM100_MMA_F8F6F4_2x1SM_SS_SPARSE
1328
+ {
1329
+ static_assert(M == 128 || M == 256, "SM100_MMA_F8F6F4_2x1SM_SS_SPARSE M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
1330
+ static_assert((N % 32 == 0) && (32 <= N) && (N <= 256), "SM100_MMA_F8F6F4_2x1SM_SS_SPARSE N-mode size should be a multiple of 32 between 32 and 256.");
1331
+
1332
+ using DRegisters = void;
1333
+ using ARegisters = uint64_t[1];
1334
+ using BRegisters = uint64_t[1];
1335
+ using CRegisters = uint32_t[1];
1336
+
1337
+ CUTE_HOST_DEVICE static void
1338
+ fma(uint64_t const& desc_a,
1339
+ uint64_t const& desc_b,
1340
+ uint32_t const& tmem_c,
1341
+ uint32_t const& scaleC,
1342
+ uint64_t const& idescE,
1343
+ uint32_t const& tmem_e)
1344
+ {
1345
+ #if defined(CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED)
1346
+ if (cute::elect_one_sync()) {
1347
+ uint32_t mask[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1348
+ asm volatile(
1349
+ "{\n\t"
1350
+ ".reg .pred p;\n\t"
1351
+ "setp.ne.b32 p, %4, 0;\n\t"
1352
+ "tcgen05.mma.sp.cta_group::2.kind::f8f6f4 [%0], %1, %2, [%13], %3, {%5, %6, %7, %8, %9, %10, %11, %12}, p; \n\t"
1353
+ "}\n"
1354
+ :
1355
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
1356
+ "r"(mask[0]), "r"(mask[1]), "r"(mask[2]), "r"(mask[3]),
1357
+ "r"(mask[4]), "r"(mask[5]), "r"(mask[6]), "r"(mask[7]), "r"(tmem_e));
1358
+ }
1359
+ #else
1360
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_F8F6F4_2x1SM_SS_SPARSE without CUTE_ARCH_TCGEN05_MXF8F6F4_MMA_ENABLED");
1361
+ #endif
1362
+ }
1363
+ };
1364
+
1365
+ template <class a_type, class b_type, class c_type, class sf_type,
1366
+ int M, int N, int VS, UMMA::Major a_major, UMMA::Major b_major,
1367
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
1368
+ struct SM100_MMA_MXF4_SS
1369
+ {
1370
+ static_assert(M == 128, "SM100_MMA_MXF4_SS M-mode size should be 128 for 1 CTA cluster MMA.");
1371
+ static_assert((N % 8 == 0) && (8 <= N) && (N <= 256), "SM100_MMA_MXF4_SS N-mode size should be a multiple of 8 between 8 and 256.");
1372
+ static_assert((VS == 16) || (VS == 32), "SM100_MMA_MXF4_SS Vector size can only be 16 or 32.");
1373
+
1374
+ using DRegisters = void;
1375
+ using ARegisters = uint64_t[1];
1376
+ using BRegisters = uint64_t[1];
1377
+ using CRegisters = uint32_t[1];
1378
+ using SFARegisters = uint32_t[1];
1379
+ using SFBRegisters = uint32_t[1];
1380
+
1381
+ CUTE_HOST_DEVICE static void
1382
+ fma(uint64_t const& desc_a,
1383
+ uint64_t const& desc_b,
1384
+ uint32_t const& tmem_c,
1385
+ uint32_t const& scaleC,
1386
+ uint64_t const& idescE,
1387
+ uint32_t const& tsfa_addr,
1388
+ uint32_t const& tsfb_addr)
1389
+ {
1390
+ if constexpr (VS == 16) {
1391
+ #if defined(CUTE_ARCH_TCGEN05_MXF4NVF4_MMA_ENABLED)
1392
+ if (cute::elect_one_sync()) {
1393
+ asm volatile(
1394
+ "{\n\t"
1395
+ ".reg .pred p;\n\t"
1396
+ "setp.ne.b32 p, %4, 0;\n\t"
1397
+ "tcgen05.mma.cta_group::1.kind::mxf4nvf4.block_scale.scale_vec::4X [%0], %1, %2, %3, [%5], [%6], p; \n\t"
1398
+ "}\n"
1399
+ :
1400
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
1401
+ "r"(tsfa_addr), "r"(tsfb_addr));
1402
+ }
1403
+ #else
1404
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_MXF4_SS (VS = 16) without CUTE_ARCH_TCGEN05_MXF4NVF4_MMA_ENABLED");
1405
+ #endif
1406
+ }
1407
+ if constexpr (VS == 32) {
1408
+ #if defined(CUTE_ARCH_TCGEN05_MXF4_MMA_ENABLED)
1409
+ if (cute::elect_one_sync()) {
1410
+ asm volatile(
1411
+ "{\n\t"
1412
+ ".reg .pred p;\n\t"
1413
+ "setp.ne.b32 p, %4, 0;\n\t"
1414
+ "tcgen05.mma.cta_group::1.kind::mxf4.block_scale.scale_vec::2X [%0], %1, %2, %3, [%5], [%6], p; \n\t"
1415
+ "}\n"
1416
+ :
1417
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
1418
+ "r"(tsfa_addr), "r"(tsfb_addr));
1419
+ }
1420
+ #else
1421
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_MXF4_SS (VS = 32) without CUTE_ARCH_TCGEN05_MXF4_MMA_ENABLED");
1422
+ #endif
1423
+ }
1424
+ }
1425
+
1426
+ };
1427
+
1428
+ template <class a_type, class b_type, class c_type, class sf_type,
1429
+ int M, int N, int VS, UMMA::Major a_major, UMMA::Major b_major,
1430
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
1431
+ struct SM100_MMA_MXF4NVF4_SS_SPARSE
1432
+ {
1433
+ static_assert(M == 128, "SM100_MMA_MXF4NVF4_SS_SPARSE M-mode size should be 128 for 1 CTA cluster MMA.");
1434
+ static_assert((N % 8 == 0) && (8 <= N) && (N <= 256), "SM100_MMA_MXF4NVF4_SS_SPARSE N-mode size should be a multiple of 8 between 8 and 256.");
1435
+
1436
+ using DRegisters = void;
1437
+ using ARegisters = uint64_t[1];
1438
+ using BRegisters = uint64_t[1];
1439
+ using CRegisters = uint32_t[1];
1440
+ using SFARegisters = uint32_t[1];
1441
+ using SFBRegisters = uint32_t[1];
1442
+
1443
+ CUTE_HOST_DEVICE static void
1444
+ fma(uint64_t const& desc_a,
1445
+ uint64_t const& desc_b,
1446
+ uint32_t const& tmem_c,
1447
+ uint32_t const& scaleC,
1448
+ uint64_t const& idescE,
1449
+ uint32_t const& tsfa_addr,
1450
+ uint32_t const& tsfb_addr,
1451
+ uint32_t const& tmem_e)
1452
+ {
1453
+ if constexpr (VS == 32) {
1454
+ #if defined(CUTE_ARCH_TCGEN05_MXF4NVF4_MMA_ENABLED)
1455
+ if (cute::elect_one_sync()) {
1456
+ asm volatile(
1457
+ "{\n\t"
1458
+ ".reg .pred p;\n\t"
1459
+ "setp.ne.b32 p, %4, 0;\n\t"
1460
+ "tcgen05.mma.sp.cta_group::1.kind::mxf4nvf4.block_scale.scale_vec::4X [%0], %1, %2, [%7], %3, [%5], [%6], p; \n\t"
1461
+ "}\n"
1462
+ :
1463
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
1464
+ "r"(tsfa_addr), "r"(tsfb_addr), "r"(tmem_e));
1465
+ }
1466
+ #else
1467
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_MXF4NVF4_SS_SPARSE (VS = 32) without CUTE_ARCH_TCGEN05_MXF4NVF4_MMA_ENABLED");
1468
+ #endif
1469
+ }
1470
+
1471
+ if constexpr (VS == 64) {
1472
+ #if defined(CUTE_ARCH_TCGEN05_MXF4_MMA_ENABLED)
1473
+ if (cute::elect_one_sync()) {
1474
+ asm volatile(
1475
+ "{\n\t"
1476
+ ".reg .pred p;\n\t"
1477
+ "setp.ne.b32 p, %4, 0;\n\t"
1478
+ "tcgen05.mma.sp.cta_group::1.kind::mxf4.block_scale.scale_vec::2X [%0], %1, %2, [%7], %3, [%5], [%6], p; \n\t"
1479
+ "}\n"
1480
+ :
1481
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
1482
+ "r"(tsfa_addr), "r"(tsfb_addr), "r"(tmem_e));
1483
+ }
1484
+ #else
1485
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_MXF4NVF4_SS_SPARSE (VS = 64) without CUTE_ARCH_TCGEN05_MXF4_MMA_ENABLED");
1486
+ #endif
1487
+ }
1488
+ }
1489
+ };
1490
+
1491
+ template <class a_type, class b_type, class c_type, class sf_type,
1492
+ int M, int N, int VS, UMMA::Major a_major, UMMA::Major b_major,
1493
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
1494
+ struct SM100_MMA_MXF4_2x1SM_SS
1495
+ {
1496
+ static_assert(M == 128 || M == 256, "SM100_MMA_MXF4_2x1SM_SS M-mode size should be 128 or 256 for 2 CTA cluster MMA.");
1497
+ static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_MXF4_2x1SM_SS N-mode size should be a multiple of 16 between 16 and 256.");
1498
+ static_assert((VS == 16) || (VS == 32), "SM100_MMA_MXF4_2x1SM_SS Vector size can only be 16 or 32.");
1499
+
1500
+ using DRegisters = void;
1501
+ using ARegisters = uint64_t[1];
1502
+ using BRegisters = uint64_t[1];
1503
+ using CRegisters = uint32_t[1];
1504
+ using SFARegisters = uint32_t[1];
1505
+ using SFBRegisters = uint32_t[1];
1506
+
1507
+ CUTE_HOST_DEVICE static void
1508
+ fma(uint64_t const& desc_a,
1509
+ uint64_t const& desc_b,
1510
+ uint32_t const& tmem_c,
1511
+ uint32_t const& scaleC,
1512
+ uint64_t const& idescE,
1513
+ uint32_t const& tsfa_addr,
1514
+ uint32_t const& tsfb_addr)
1515
+ {
1516
+ if constexpr (VS == 16) {
1517
+ #if defined(CUTE_ARCH_TCGEN05_MXF4NVF4_MMA_ENABLED)
1518
+ if (cute::elect_one_sync()) {
1519
+ asm volatile(
1520
+ "{\n\t"
1521
+ ".reg .pred p;\n\t"
1522
+ "setp.ne.b32 p, %4, 0;\n\t"
1523
+ "tcgen05.mma.cta_group::2.kind::mxf4nvf4.block_scale.scale_vec::4X [%0], %1, %2, %3, [%5], [%6], p; \n\t"
1524
+ "}\n"
1525
+ :
1526
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
1527
+ "r"(tsfa_addr), "r"(tsfb_addr));
1528
+ }
1529
+ #else
1530
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_MXF4_2x1SM_SS (VS = 16) without CUTE_ARCH_TCGEN05_MXF4NVF4_MMA_ENABLED");
1531
+ #endif
1532
+ }
1533
+ if constexpr (VS == 32) {
1534
+ #if defined(CUTE_ARCH_TCGEN05_MXF4_MMA_ENABLED)
1535
+ if (cute::elect_one_sync()) {
1536
+ asm volatile(
1537
+ "{\n\t"
1538
+ ".reg .pred p;\n\t"
1539
+ "setp.ne.b32 p, %4, 0;\n\t"
1540
+ "tcgen05.mma.cta_group::2.kind::mxf4.block_scale.scale_vec::2X [%0], %1, %2, %3, [%5], [%6], p; \n\t"
1541
+ "}\n"
1542
+ :
1543
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
1544
+ "r"(tsfa_addr), "r"(tsfb_addr));
1545
+ }
1546
+ #else
1547
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_MXF4_2x1SM_SS (VS = 32) without CUTE_ARCH_TCGEN05_MXF4_MMA_ENABLED");
1548
+ #endif
1549
+ }
1550
+ }
1551
+ };
1552
+
1553
+ template <class a_type, class b_type, class c_type, class sf_type,
1554
+ int M, int N, int VS, UMMA::Major a_major, UMMA::Major b_major,
1555
+ UMMA::ScaleIn a_neg = UMMA::ScaleIn::One, UMMA::ScaleIn b_neg = UMMA::ScaleIn::One>
1556
+ struct SM100_MMA_MXF4NVF4_2x1SM_SS_SPARSE
1557
+ {
1558
+ static_assert((N % 16 == 0) && (16 <= N) && (N <= 256), "SM100_MMA_MXF4NVF4_2x1SM_SS_SPARSE N-mode size should be a multiple of 16 between 16 and 256.");
1559
+ static_assert((VS == 32) || (VS == 64), "SM100_MMA_MXF4NVF4_2x1SM_SS_SPARSE Vector size can only be 32 or 64.");
1560
+
1561
+ using DRegisters = void;
1562
+ using ARegisters = uint64_t[1];
1563
+ using BRegisters = uint64_t[1];
1564
+ using CRegisters = uint32_t[1];
1565
+ using SFARegisters = uint32_t[1];
1566
+ using SFBRegisters = uint32_t[1];
1567
+
1568
+ CUTE_HOST_DEVICE static void
1569
+ fma(uint64_t const& desc_a,
1570
+ uint64_t const& desc_b,
1571
+ uint32_t const& tmem_c,
1572
+ uint32_t const& scaleC,
1573
+ uint64_t const& idescE,
1574
+ uint32_t const& tsfa_addr,
1575
+ uint32_t const& tsfb_addr,
1576
+ uint32_t const& tmem_e)
1577
+ {
1578
+ if constexpr (VS == 32) {
1579
+ #if defined(CUTE_ARCH_TCGEN05_MXF4NVF4_MMA_ENABLED)
1580
+ if (cute::elect_one_sync()) {
1581
+ asm volatile(
1582
+ "{\n\t"
1583
+ ".reg .pred p;\n\t"
1584
+ "setp.ne.b32 p, %4, 0;\n\t"
1585
+ "tcgen05.mma.sp.cta_group::2.kind::mxf4nvf4.block_scale.scale_vec::4X [%0], %1, %2, [%7], %3, [%5], [%6], p; \n\t"
1586
+ "}\n"
1587
+ :
1588
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
1589
+ "r"(tsfa_addr), "r"(tsfb_addr), "r"(tmem_e));
1590
+ }
1591
+ #else
1592
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_MXF4NVF4_2x1SM_SS_SPARSE (VS = 32) without CUTE_ARCH_TCGEN05_MXF4NVF4_MMA_ENABLED");
1593
+ #endif
1594
+ }
1595
+
1596
+ if constexpr (VS == 64) {
1597
+ #if defined(CUTE_ARCH_TCGEN05_MXF4_MMA_ENABLED)
1598
+ if (cute::elect_one_sync()) {
1599
+ asm volatile(
1600
+ "{\n\t"
1601
+ ".reg .pred p;\n\t"
1602
+ "setp.ne.b32 p, %4, 0;\n\t"
1603
+ "tcgen05.mma.sp.cta_group::2.kind::mxf4.block_scale.scale_vec::2X [%0], %1, %2, [%7], %3, [%5], [%6], p; \n\t"
1604
+ "}\n"
1605
+ :
1606
+ : "r"(tmem_c), "l"(desc_a), "l"(desc_b), "r"(uint32_t(idescE>>32)), "r"(scaleC),
1607
+ "r"(tsfa_addr), "r"(tsfb_addr), "r"(tmem_e));
1608
+ }
1609
+ #else
1610
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM100_MMA_MXF4NVF4_2x1SM_SS_SPARSE (VS = 64) without CUTE_ARCH_TCGEN05_MXF4_MMA_ENABLED");
1611
+ #endif
1612
+ }
1613
+ }
1614
+ };
1615
+
1616
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm120.hpp ADDED
The diff for this file is too large to render. See raw diff
 
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm120_sparse.hpp ADDED
The diff for this file is too large to render. See raw diff
 
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm61.hpp ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+
32
+ #pragma once
33
+
34
+ #include <cute/config.hpp>
35
+ #include <cute/arch/mma.hpp>
36
+
37
+ // Config
38
+ #if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 610))
39
+ # define CUTE_ARCH_MMA_SM61_ENABLED
40
+ #endif
41
+
42
+ namespace cute
43
+ {
44
+
45
+ struct SM61_DP4A
46
+ {
47
+ using DRegisters = int32_t[1];
48
+ using ARegisters = uint32_t[1];
49
+ using BRegisters = uint32_t[1];
50
+ using CRegisters = int32_t[1];
51
+
52
+ // Register asm fma
53
+ CUTE_HOST_DEVICE static void
54
+ fma(int32_t& d, uint32_t const& a, uint32_t const& b, int32_t const& c)
55
+ {
56
+ #if defined(CUTE_ARCH_MMA_SM61_ENABLED)
57
+ asm volatile("dp4a.s32.s32 %0, %1, %2, %3;"
58
+ : "=r"(d)
59
+ : "r"(a), "r"(b), "r"(c));
60
+ #else
61
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM61_DP4A without CUTE_ARCH_MMA_SM61_ENABLED");
62
+ #endif
63
+ }
64
+ };
65
+
66
+ struct SM61_DP2A
67
+ {
68
+ using DRegisters = int32_t[1];
69
+ using ARegisters = uint32_t[1];
70
+ using BRegisters = uint32_t[1];
71
+ using CRegisters = int32_t[1];
72
+
73
+ // Register asm fma
74
+ CUTE_HOST_DEVICE static void
75
+ fma(int32_t& d, uint32_t const& a, uint32_t const& b, int32_t const& c)
76
+ {
77
+ #if defined(CUTE_ARCH_MMA_SM61_ENABLED)
78
+ asm volatile("dp2a.s32.s32 %0, %1, %2, %3;"
79
+ : "=r"(d)
80
+ : "r"(a), "r"(b), "r"(c));
81
+ #else
82
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM61_DP2A without CUTE_ARCH_MMA_SM61_ENABLED");
83
+ #endif
84
+ }
85
+ };
86
+
87
+ } // namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm70.hpp ADDED
@@ -0,0 +1,329 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp>
34
+
35
+ #include <cute/arch/mma.hpp>
36
+
37
+ // Config
38
+ #if ((__CUDACC_VER_MAJOR__ > 10) || (__CUDACC_VER_MAJOR__ == 10 && __CUDACC_VER_MINOR__ >= 1))
39
+ # define CUTE_ARCH_MMA_SM70_SUPPORTED
40
+ # if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 700))
41
+ # define CUTE_ARCH_MMA_SM70_ENABLED
42
+ # endif
43
+ #endif
44
+
45
+ namespace cute
46
+ {
47
+
48
+ //
49
+ // SM70 MMA 884 F16F16F16
50
+ //
51
+
52
+ struct SM70_8x8x4_F16F16F16F16_TN
53
+ {
54
+ using DRegisters = uint32_t[4];
55
+ using ARegisters = uint32_t[2];
56
+ using BRegisters = uint32_t[2];
57
+ using CRegisters = uint32_t[4];
58
+
59
+ // Register asm fma
60
+ CUTE_HOST_DEVICE static void
61
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
62
+ uint32_t const& a0, uint32_t const& a1,
63
+ uint32_t const& b0, uint32_t const& b1,
64
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
65
+ {
66
+ #if defined(CUTE_ARCH_MMA_SM70_ENABLED)
67
+ asm volatile("mma.sync.aligned.m8n8k4.row.col.f16.f16.f16.f16"
68
+ "{%0, %1, %2, %3},"
69
+ "{%4, %5},"
70
+ "{%6, %7},"
71
+ "{%8, %9, %10, %11};\n"
72
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
73
+ : "r"(a0), "r"(a1),
74
+ "r"(b0), "r"(b1),
75
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
76
+ #else
77
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM70_8x8x4_F16F16F16F16_TN without CUTE_ARCH_MMA_SM70_ENABLED");
78
+ #endif
79
+ }
80
+ };
81
+
82
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
83
+
84
+ struct SM70_8x8x4_F16F16F16F16_NT
85
+ {
86
+ using DRegisters = uint32_t[4];
87
+ using ARegisters = uint32_t[2];
88
+ using BRegisters = uint32_t[2];
89
+ using CRegisters = uint32_t[4];
90
+
91
+ // Register asm fma
92
+ CUTE_HOST_DEVICE static void
93
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
94
+ uint32_t const& a0, uint32_t const& a1,
95
+ uint32_t const& b0, uint32_t const& b1,
96
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
97
+ {
98
+ #if defined(CUTE_ARCH_MMA_SM70_ENABLED)
99
+ asm volatile("mma.sync.aligned.m8n8k4.col.row.f16.f16.f16.f16"
100
+ "{%0, %1, %2, %3},"
101
+ "{%4, %5},"
102
+ "{%6, %7},"
103
+ "{%8, %9, %10, %11};\n"
104
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
105
+ : "r"(a0), "r"(a1),
106
+ "r"(b0), "r"(b1),
107
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
108
+ #else
109
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM70_8x8x4_F16F16F16F16_NT without CUTE_ARCH_MMA_SM70_ENABLED");
110
+ #endif
111
+ }
112
+ };
113
+
114
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
115
+
116
+ struct SM70_8x8x4_F16F16F16F16_NN
117
+ {
118
+ using DRegisters = uint32_t[4];
119
+ using ARegisters = uint32_t[2];
120
+ using BRegisters = uint32_t[2];
121
+ using CRegisters = uint32_t[4];
122
+
123
+ // Register asm fma
124
+ CUTE_HOST_DEVICE static void
125
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
126
+ uint32_t const& a0, uint32_t const& a1,
127
+ uint32_t const& b0, uint32_t const& b1,
128
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
129
+ {
130
+ #if defined(CUTE_ARCH_MMA_SM70_ENABLED)
131
+ asm volatile("mma.sync.aligned.m8n8k4.col.col.f16.f16.f16.f16"
132
+ "{%0, %1, %2, %3},"
133
+ "{%4, %5},"
134
+ "{%6, %7},"
135
+ "{%8, %9, %10, %11};\n"
136
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
137
+ : "r"(a0), "r"(a1),
138
+ "r"(b0), "r"(b1),
139
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
140
+ #else
141
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM70_8x8x4_F16F16F16F16_NN without CUTE_ARCH_MMA_SM70_ENABLED");
142
+ #endif
143
+ }
144
+ };
145
+
146
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
147
+
148
+ struct SM70_8x8x4_F16F16F16F16_TT
149
+ {
150
+ using DRegisters = uint32_t[4];
151
+ using ARegisters = uint32_t[2];
152
+ using BRegisters = uint32_t[2];
153
+ using CRegisters = uint32_t[4];
154
+
155
+ // Register asm fma
156
+ CUTE_HOST_DEVICE static void
157
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
158
+ uint32_t const& a0, uint32_t const& a1,
159
+ uint32_t const& b0, uint32_t const& b1,
160
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
161
+ {
162
+ #if defined(CUTE_ARCH_MMA_SM70_ENABLED)
163
+ asm volatile("mma.sync.aligned.m8n8k4.row.row.f16.f16.f16.f16"
164
+ "{%0, %1, %2, %3},"
165
+ "{%4, %5},"
166
+ "{%6, %7},"
167
+ "{%8, %9, %10, %11};\n"
168
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
169
+ : "r"(a0), "r"(a1),
170
+ "r"(b0), "r"(b1),
171
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
172
+ #else
173
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM70_8x8x4_F16F16F16F16_TT without CUTE_ARCH_MMA_SM70_ENABLED");
174
+ #endif
175
+ }
176
+ };
177
+
178
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
179
+
180
+ //
181
+ // SM70 MMA 884 F16F16F32
182
+ //
183
+
184
+ struct SM70_8x8x4_F32F16F16F32_TN
185
+ {
186
+ using DRegisters = float[8];
187
+ using ARegisters = uint32_t[2];
188
+ using BRegisters = uint32_t[2];
189
+ using CRegisters = float[8];
190
+
191
+ // Register asm fma
192
+ CUTE_HOST_DEVICE static void
193
+ fma(float & d0, float & d1, float & d2, float & d3,
194
+ float & d4, float & d5, float & d6, float & d7,
195
+ uint32_t const& a0, uint32_t const& a1,
196
+ uint32_t const& b0, uint32_t const& b1,
197
+ float const& c0, float const& c1, float const& c2, float const& c3,
198
+ float const& c4, float const& c5, float const& c6, float const& c7)
199
+ {
200
+ #if defined(CUTE_ARCH_MMA_SM70_ENABLED)
201
+ asm volatile("mma.sync.aligned.m8n8k4.row.col.f32.f16.f16.f32"
202
+ "{%0, %1, %2, %3, %4, %5, %6, %7},"
203
+ "{%8, %9},"
204
+ "{%10, %11},"
205
+ "{%12, %13, %14, %15, %16, %17, %18, %19};\n"
206
+ : "=f"(d0), "=f"(d1), "=f"(d2), "=f"(d3),
207
+ "=f"(d4), "=f"(d5), "=f"(d6), "=f"(d7)
208
+ : "r"(a0), "r"(a1),
209
+ "r"(b0), "r"(b1),
210
+ "f"(c0), "f"(c1), "f"(c2), "f"(c3),
211
+ "f"(c4), "f"(c5), "f"(c6), "f"(c7));
212
+ #else
213
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM70_8x8x4_F32F16F16F32_TN without CUTE_ARCH_MMA_SM70_ENABLED");
214
+ #endif
215
+ }
216
+ };
217
+
218
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
219
+
220
+ struct SM70_8x8x4_F32F16F16F32_NT
221
+ {
222
+ using DRegisters = float[8];
223
+ using ARegisters = uint32_t[2];
224
+ using BRegisters = uint32_t[2];
225
+ using CRegisters = float[8];
226
+
227
+ // Register asm fma
228
+ CUTE_HOST_DEVICE static void
229
+ fma(float & d0, float & d1, float & d2, float & d3,
230
+ float & d4, float & d5, float & d6, float & d7,
231
+ uint32_t const& a0, uint32_t const& a1,
232
+ uint32_t const& b0, uint32_t const& b1,
233
+ float const& c0, float const& c1, float const& c2, float const& c3,
234
+ float const& c4, float const& c5, float const& c6, float const& c7)
235
+ {
236
+ #if defined(CUTE_ARCH_MMA_SM70_ENABLED)
237
+ asm volatile("mma.sync.aligned.m8n8k4.col.row.f32.f16.f16.f32"
238
+ "{%0, %1, %2, %3, %4, %5, %6, %7},"
239
+ "{%8, %9},"
240
+ "{%10, %11},"
241
+ "{%12, %13, %14, %15, %16, %17, %18, %19};"
242
+ : "=f"(d0), "=f"(d1), "=f"(d2), "=f"(d3),
243
+ "=f"(d4), "=f"(d5), "=f"(d6), "=f"(d7)
244
+ : "r"(a0), "r"(a1),
245
+ "r"(b0), "r"(b1),
246
+ "f"(c0), "f"(c1), "f"(c2), "f"(c3),
247
+ "f"(c4), "f"(c5), "f"(c6), "f"(c7));
248
+ #else
249
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM70_8x8x4_F32F16F16F32_NT without CUTE_ARCH_MMA_SM70_ENABLED");
250
+ #endif
251
+ }
252
+ };
253
+
254
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
255
+
256
+ struct SM70_8x8x4_F32F16F16F32_NN
257
+ {
258
+ using DRegisters = float[8];
259
+ using ARegisters = uint32_t[2];
260
+ using BRegisters = uint32_t[2];
261
+ using CRegisters = float[8];
262
+
263
+ // Register asm fma
264
+ CUTE_HOST_DEVICE static void
265
+ fma(float & d0, float & d1, float & d2, float & d3,
266
+ float & d4, float & d5, float & d6, float & d7,
267
+ uint32_t const& a0, uint32_t const& a1,
268
+ uint32_t const& b0, uint32_t const& b1,
269
+ float const& c0, float const& c1, float const& c2, float const& c3,
270
+ float const& c4, float const& c5, float const& c6, float const& c7)
271
+ {
272
+ #if defined(CUTE_ARCH_MMA_SM70_ENABLED)
273
+ asm volatile("mma.sync.aligned.m8n8k4.col.col.f32.f16.f16.f32"
274
+ "{%0, %1, %2, %3, %4, %5, %6, %7},"
275
+ "{%8, %9},"
276
+ "{%10, %11},"
277
+ "{%12, %13, %14, %15, %16, %17, %18, %19};"
278
+ : "=f"(d0), "=f"(d1), "=f"(d2), "=f"(d3),
279
+ "=f"(d4), "=f"(d5), "=f"(d6), "=f"(d7)
280
+ : "r"(a0), "r"(a1),
281
+ "r"(b0), "r"(b1),
282
+ "f"(c0), "f"(c1), "f"(c2), "f"(c3),
283
+ "f"(c4), "f"(c5), "f"(c6), "f"(c7));
284
+ #else
285
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM70_8x8x4_F32F16F16F32_NN without CUTE_ARCH_MMA_SM70_ENABLED");
286
+ #endif
287
+ }
288
+ };
289
+
290
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
291
+
292
+ struct SM70_8x8x4_F32F16F16F32_TT
293
+ {
294
+ using DRegisters = float[8];
295
+ using ARegisters = uint32_t[2];
296
+ using BRegisters = uint32_t[2];
297
+ using CRegisters = float[8];
298
+
299
+ // Register asm fma
300
+ CUTE_HOST_DEVICE static void
301
+ fma(float & d0, float & d1, float & d2, float & d3,
302
+ float & d4, float & d5, float & d6, float & d7,
303
+ uint32_t const& a0, uint32_t const& a1,
304
+ uint32_t const& b0, uint32_t const& b1,
305
+ float const& c0, float const& c1, float const& c2, float const& c3,
306
+ float const& c4, float const& c5, float const& c6, float const& c7)
307
+ {
308
+ #if defined(CUTE_ARCH_MMA_SM70_ENABLED)
309
+ asm volatile("mma.sync.aligned.m8n8k4.row.row.f32.f16.f16.f32"
310
+ "{%0, %1, %2, %3, %4, %5, %6, %7},"
311
+ "{%8, %9},"
312
+ "{%10, %11},"
313
+ "{%12, %13, %14, %15, %16, %17, %18, %19};"
314
+ : "=f"(d0), "=f"(d1), "=f"(d2), "=f"(d3),
315
+ "=f"(d4), "=f"(d5), "=f"(d6), "=f"(d7)
316
+ : "r"(a0), "r"(a1),
317
+ "r"(b0), "r"(b1),
318
+ "f"(c0), "f"(c1), "f"(c2), "f"(c3),
319
+ "f"(c4), "f"(c5), "f"(c6), "f"(c7));
320
+ #else
321
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM70_8x8x4_F32F16F16F32_TT without CUTE_ARCH_MMA_SM70_ENABLED");
322
+ #endif
323
+ }
324
+
325
+ };
326
+
327
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
328
+
329
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm75.hpp ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp>
34
+
35
+ #include <cute/arch/mma.hpp>
36
+
37
+ // Config
38
+ #if ((__CUDACC_VER_MAJOR__ > 10) || (__CUDACC_VER_MAJOR__ == 10 && __CUDACC_VER_MINOR__ >= 2))
39
+ # define CUTE_ARCH_MMA_SM75_SUPPORTED
40
+ # if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 750))
41
+ # define CUTE_ARCH_MMA_SM75_ENABLED
42
+ # endif
43
+ #endif
44
+
45
+ namespace cute
46
+ {
47
+
48
+ //
49
+ // SM75 MMA 1688 F16F16F32
50
+ //
51
+
52
+ struct SM75_16x8x8_F32F16F16F32_TN
53
+ {
54
+ using DRegisters = float[4];
55
+ using ARegisters = uint32_t[2];
56
+ using BRegisters = uint32_t[1];
57
+ using CRegisters = float[4];
58
+
59
+ // Register asm fma
60
+ CUTE_HOST_DEVICE static void
61
+ fma(float & d0, float & d1, float & d2, float & d3,
62
+ uint32_t const& a0, uint32_t const& a1,
63
+ uint32_t const& b0,
64
+ float const& c0, float const& c1, float const& c2, float const& c3)
65
+ {
66
+ #if defined(CUTE_ARCH_MMA_SM75_ENABLED)
67
+ asm volatile("mma.sync.aligned.m16n8k8.row.col.f32.f16.f16.f32"
68
+ "{%0, %1, %2, %3},"
69
+ "{%4, %5},"
70
+ "{%6},"
71
+ "{%7, %8, %9, %10};\n"
72
+ : "=f"(d0), "=f"(d1), "=f"(d2), "=f"(d3)
73
+ : "r"(a0), "r"(a1),
74
+ "r"(b0),
75
+ "f"(c0), "f"(c1), "f"(c2), "f"(c3));
76
+ #else
77
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM75_16x8x8_F32F16F16F32_TN without CUTE_ARCH_MMA_SM75_ENABLED");
78
+ #endif
79
+ }
80
+ };
81
+
82
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
83
+
84
+ //
85
+ // SM75 MMA 8816 S8S8S32
86
+ //
87
+
88
+ struct SM75_8x8x16_S32S8S8S32_TN
89
+ {
90
+ using DRegisters = uint32_t[2];
91
+ using ARegisters = uint32_t[1];
92
+ using BRegisters = uint32_t[1];
93
+ using CRegisters = uint32_t[2];
94
+
95
+ // Register asm fma
96
+ CUTE_HOST_DEVICE static void
97
+ fma(uint32_t & d0, uint32_t & d1,
98
+ uint32_t const& a0,
99
+ uint32_t const& b0,
100
+ uint32_t const& c0, uint32_t const& c1)
101
+ {
102
+ #if defined(CUTE_ARCH_MMA_SM75_ENABLED)
103
+ asm volatile("mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32"
104
+ "{%0, %1},"
105
+ "{%2},"
106
+ "{%3},"
107
+ "{%4, %5};\n"
108
+ : "=r"(d0), "=r"(d1)
109
+ : "r"(a0),
110
+ "r"(b0),
111
+ "r"(c0), "r"(c1));
112
+ #else
113
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM75_8x8x16_S32S8S8S32_TN without CUTE_ARCH_MMA_SM75_ENABLED");
114
+ #endif
115
+ }
116
+ };
117
+
118
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
119
+
120
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm80.hpp ADDED
@@ -0,0 +1,2241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+
32
+ #pragma once
33
+
34
+ #include <cute/config.hpp>
35
+ #include <cute/arch/mma.hpp>
36
+ #include <cute/numeric/complex.hpp>
37
+
38
+ // Config
39
+ #if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 800))
40
+ # define CUTE_ARCH_MMA_SM80_ENABLED
41
+
42
+ #if (__CUDA_ARCH__ <= 900)
43
+ #define CUTE_ARCH_MMA_B1_AND_SM80_ENABLED
44
+ #endif
45
+
46
+ #if (__CUDA_ARCH__ <= 890)
47
+ #define CUTE_ARCH_MMA_B1_XOR_SM80_ENABLED
48
+ #endif
49
+
50
+ #endif
51
+
52
+
53
+
54
+ namespace cute {
55
+
56
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
57
+
58
+ // MMA 16x8x8 TN
59
+ struct SM80_16x8x8_F16F16F16F16_TN
60
+ {
61
+ using DRegisters = uint32_t[2];
62
+ using ARegisters = uint32_t[2];
63
+ using BRegisters = uint32_t[1];
64
+ using CRegisters = uint32_t[2];
65
+
66
+ CUTE_HOST_DEVICE static void
67
+ fma(uint32_t & d0, uint32_t & d1,
68
+ uint32_t const& a0, uint32_t const& a1,
69
+ uint32_t const& b0,
70
+ uint32_t const& c0, uint32_t const& c1)
71
+ {
72
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
73
+ asm volatile(
74
+ "mma.sync.aligned.m16n8k8.row.col.f16.f16.f16.f16 "
75
+ "{%0, %1},"
76
+ "{%2, %3},"
77
+ "{%4},"
78
+ "{%5, %6};\n"
79
+ : "=r"(d0), "=r"(d1)
80
+ : "r"(a0), "r"(a1),
81
+ "r"(b0),
82
+ "r"(c0), "r"(c1));
83
+ #else
84
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x8_F16F16F16F16_TN without CUTE_ARCH_MMA_SM80_ENABLED");
85
+ #endif
86
+ }
87
+ };
88
+
89
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
90
+
91
+ // MMA 16x8x16 TN
92
+ struct SM80_16x8x16_F16F16F16F16_TN
93
+ {
94
+ using DRegisters = uint32_t[2];
95
+ using ARegisters = uint32_t[4];
96
+ using BRegisters = uint32_t[2];
97
+ using CRegisters = uint32_t[2];
98
+
99
+ CUTE_HOST_DEVICE static void
100
+ fma(uint32_t & d0, uint32_t & d1,
101
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
102
+ uint32_t const& b0, uint32_t const& b1,
103
+ uint32_t const& c0, uint32_t const& c1)
104
+ {
105
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
106
+ asm volatile(
107
+ "mma.sync.aligned.m16n8k16.row.col.f16.f16.f16.f16 "
108
+ "{%0, %1},"
109
+ "{%2, %3, %4, %5},"
110
+ "{%6, %7},"
111
+ "{%8, %9};\n"
112
+ : "=r"(d0), "=r"(d1)
113
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
114
+ "r"(b0), "r"(b1),
115
+ "r"(c0), "r"(c1));
116
+ #else
117
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x16_F16F16F16F16_TN without CUTE_ARCH_MMA_SM80_ENABLED");
118
+ #endif
119
+ }
120
+ };
121
+
122
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
123
+
124
+ // MMA 16x8x8 TN
125
+ struct SM80_16x8x8_F32F16F16F32_TN
126
+ {
127
+ using DRegisters = float[4];
128
+ using ARegisters = uint32_t[2];
129
+ using BRegisters = uint32_t[1];
130
+ using CRegisters = float[4];
131
+
132
+ CUTE_HOST_DEVICE static void
133
+ fma(float & d0, float & d1, float & d2, float & d3,
134
+ uint32_t const& a0, uint32_t const& a1,
135
+ uint32_t const& b0,
136
+ float const & c0, float const & c1, float const & c2, float const & c3)
137
+ {
138
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
139
+ asm volatile(
140
+ "mma.sync.aligned.m16n8k8.row.col.f32.f16.f16.f32 "
141
+ "{%0, %1, %2, %3},"
142
+ "{%4, %5},"
143
+ "{%6},"
144
+ "{%7, %8, %9, %10};\n"
145
+ : "=f"(d0), "=f"(d1), "=f"(d2), "=f"(d3)
146
+ : "r"(a0), "r"(a1),
147
+ "r"(b0),
148
+ "f"(c0), "f"(c1), "f"(c2), "f"(c3));
149
+ #else
150
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x8_F32F16F16F32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
151
+ #endif
152
+ }
153
+ };
154
+
155
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
156
+
157
+ // MMA 16x8x16 TN
158
+ struct SM80_16x8x16_F32F16F16F32_TN
159
+ {
160
+ using DRegisters = float[4];
161
+ using ARegisters = uint32_t[4];
162
+ using BRegisters = uint32_t[2];
163
+ using CRegisters = float[4];
164
+
165
+ CUTE_HOST_DEVICE static void
166
+ fma(float & d0, float & d1, float & d2, float & d3,
167
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
168
+ uint32_t const& b0, uint32_t const& b1,
169
+ float const & c0, float const & c1, float const & c2, float const & c3)
170
+ {
171
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
172
+ asm volatile(
173
+ "mma.sync.aligned.m16n8k16.row.col.f32.f16.f16.f32 "
174
+ "{%0, %1, %2, %3},"
175
+ "{%4, %5, %6, %7},"
176
+ "{%8, %9},"
177
+ "{%10, %11, %12, %13};\n"
178
+ : "=f"(d0), "=f"(d1), "=f"(d2), "=f"(d3)
179
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
180
+ "r"(b0), "r"(b1),
181
+ "f"(c0), "f"(c1), "f"(c2), "f"(c3));
182
+ #else
183
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x16_F32F16F16F32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
184
+ #endif
185
+ }
186
+ };
187
+
188
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
189
+
190
+ // MMA 16x8x8 TN
191
+ struct SM80_16x8x8_F32BF16BF16F32_TN
192
+ {
193
+ using DRegisters = float[4];
194
+ using ARegisters = uint32_t[2];
195
+ using BRegisters = uint32_t[1];
196
+ using CRegisters = float[4];
197
+
198
+ CUTE_HOST_DEVICE static void
199
+ fma(float & d0, float & d1, float & d2, float & d3,
200
+ uint32_t const& a0, uint32_t const& a1,
201
+ uint32_t const& b0,
202
+ float const & c0, float const & c1, float const & c2, float const & c3)
203
+ {
204
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
205
+ asm volatile(
206
+ "mma.sync.aligned.m16n8k8.row.col.f32.bf16.bf16.f32 "
207
+ "{%0, %1, %2, %3},"
208
+ "{%4, %5},"
209
+ "{%6},"
210
+ "{%7, %8, %9, %10};\n"
211
+ : "=f"(d0), "=f"(d1), "=f"(d2), "=f"(d3)
212
+ : "r"(a0), "r"(a1),
213
+ "r"(b0),
214
+ "f"(c0), "f"(c1), "f"(c2), "f"(c3));
215
+ #else
216
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x8_F32BF16BF16F32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
217
+ #endif
218
+ }
219
+ };
220
+
221
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
222
+
223
+ // MMA 16x8x16 TN
224
+ struct SM80_16x8x16_F32BF16BF16F32_TN
225
+ {
226
+ using DRegisters = float[4];
227
+ using ARegisters = uint32_t[4];
228
+ using BRegisters = uint32_t[2];
229
+ using CRegisters = float[4];
230
+
231
+ CUTE_HOST_DEVICE static void
232
+ fma(float & d0, float & d1, float & d2, float & d3,
233
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
234
+ uint32_t const& b0, uint32_t const& b1,
235
+ float const & c0, float const & c1, float const & c2, float const & c3)
236
+ {
237
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
238
+ asm volatile(
239
+ "mma.sync.aligned.m16n8k16.row.col.f32.bf16.bf16.f32 "
240
+ "{%0, %1, %2, %3},"
241
+ "{%4, %5, %6, %7},"
242
+ "{%8, %9},"
243
+ "{%10, %11, %12, %13};\n"
244
+ : "=f"(d0), "=f"(d1), "=f"(d2), "=f"(d3)
245
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
246
+ "r"(b0), "r"(b1),
247
+ "f"(c0), "f"(c1), "f"(c2), "f"(c3));
248
+ #else
249
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x16_F32BF16BF16F32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
250
+ #endif
251
+ }
252
+ };
253
+
254
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
255
+
256
+ // MMA 16x8x4 TN
257
+ struct SM80_16x8x4_F32TF32TF32F32_TN
258
+ {
259
+ using DRegisters = float[4];
260
+ using ARegisters = uint32_t[2];
261
+ using BRegisters = uint32_t[1];
262
+ using CRegisters = float[4];
263
+
264
+ CUTE_HOST_DEVICE static void
265
+ fma(float & d0, float & d1, float & d2, float & d3,
266
+ uint32_t const& a0, uint32_t const& a1,
267
+ uint32_t const& b0,
268
+ float const & c0, float const & c1, float const & c2, float const & c3)
269
+ {
270
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
271
+ asm volatile(
272
+ "mma.sync.aligned.m16n8k4.row.col.f32.tf32.tf32.f32 "
273
+ "{%0, %1, %2, %3},"
274
+ "{%4, %5},"
275
+ "{%6},"
276
+ "{%7, %8, %9, %10};\n"
277
+ : "=f"(d0), "=f"(d1), "=f"(d2), "=f"(d3)
278
+ : "r"(a0), "r"(a1),
279
+ "r"(b0),
280
+ "f"(c0), "f"(c1), "f"(c2), "f"(c3));
281
+ #else
282
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x4_F32TF32TF32F32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
283
+ #endif
284
+ }
285
+ };
286
+
287
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
288
+
289
+ // MMA 16x8x8 TN
290
+ struct SM80_16x8x8_F32TF32TF32F32_TN
291
+ {
292
+ using DRegisters = float[4];
293
+ using ARegisters = uint32_t[4];
294
+ using BRegisters = uint32_t[2];
295
+ using CRegisters = float[4];
296
+
297
+ CUTE_HOST_DEVICE static void
298
+ fma(float & d0, float & d1, float & d2, float & d3,
299
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
300
+ uint32_t const& b0, uint32_t const& b1,
301
+ float const & c0, float const & c1, float const & c2, float const & c3)
302
+ {
303
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
304
+ asm volatile(
305
+ "mma.sync.aligned.m16n8k8.row.col.f32.tf32.tf32.f32 "
306
+ "{%0, %1, %2, %3},"
307
+ "{%4, %5, %6, %7},"
308
+ "{%8, %9},"
309
+ "{%10, %11, %12, %13};\n"
310
+ : "=f"(d0), "=f"(d1), "=f"(d2), "=f"(d3)
311
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
312
+ "r"(b0), "r"(b1),
313
+ "f"(c0), "f"(c1), "f"(c2), "f"(c3));
314
+ #else
315
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x8_F32TF32TF32F32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
316
+ #endif
317
+ }
318
+ };
319
+
320
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
321
+
322
+ // MMA 8x8x4 TN
323
+ struct SM80_8x8x4_F64F64F64F64_TN
324
+ {
325
+ using DRegisters = double[2];
326
+ using ARegisters = double[1];
327
+ using BRegisters = double[1];
328
+ using CRegisters = double[2];
329
+
330
+ CUTE_HOST_DEVICE static void
331
+ fma(double & d0, double & d1,
332
+ double const& a0,
333
+ double const& b0,
334
+ double const& c0, double const& c1)
335
+ {
336
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
337
+ asm volatile(
338
+ "mma.sync.aligned.m8n8k4.row.col.f64.f64.f64.f64 "
339
+ "{%0, %1},"
340
+ "{%2},"
341
+ "{%3},"
342
+ "{%4, %5};\n"
343
+ : "=d"(d0), "=d"(d1)
344
+ : "d"(a0),
345
+ "d"(b0),
346
+ "d"(c0), "d"(c1));
347
+ #else
348
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x4_F64F64F64F64_TN without CUTE_ARCH_MMA_SM80_ENABLED");
349
+ #endif
350
+ }
351
+ };
352
+
353
+ // MMA 8x8x4 TN with Planar Complex multiplication
354
+ struct SM80_8x8x4_C64C64C64C64_TN
355
+ {
356
+ using DRegisters = complex<double>[2];
357
+ using ARegisters = complex<double>[1];
358
+ using BRegisters = complex<double>[1];
359
+ using CRegisters = complex<double>[2];
360
+
361
+ CUTE_HOST_DEVICE static void
362
+ fma(complex<double> & d0, complex<double> & d1,
363
+ complex<double> const& a0,
364
+ complex<double> const& b0,
365
+ complex<double> const& c0, complex<double> const& c1)
366
+ {
367
+ // Because thrust::complex does not provide a mutable ref
368
+ double& rd0 = reinterpret_cast<double(&)[2]>(d0)[0];
369
+ double& id0 = reinterpret_cast<double(&)[2]>(d0)[1];
370
+ double& rd1 = reinterpret_cast<double(&)[2]>(d1)[0];
371
+ double& id1 = reinterpret_cast<double(&)[2]>(d1)[1];
372
+
373
+ // d.real() = a.real() * b.real() + c.real();
374
+ SM80_8x8x4_F64F64F64F64_TN::fma(
375
+ rd0, rd1,
376
+ a0.real(),
377
+ b0.real(),
378
+ c0.real(), c1.real());
379
+
380
+ // d.imag() = a.imag() * b.real() + c.imag();
381
+ SM80_8x8x4_F64F64F64F64_TN::fma(
382
+ id0, id1,
383
+ a0.imag(),
384
+ b0.real(),
385
+ c0.imag(), c1.imag());
386
+
387
+ // d.real() = -a.imag() * b.imag() + d.real();
388
+ SM80_8x8x4_F64F64F64F64_TN::fma(
389
+ rd0, rd1,
390
+ -a0.imag(),
391
+ b0.imag(),
392
+ d0.real(), d1.real());
393
+
394
+ // d.imag() = a.real() * b.imag() + d.imag();
395
+ SM80_8x8x4_F64F64F64F64_TN::fma(
396
+ id0, id1,
397
+ a0.real(),
398
+ b0.imag(),
399
+ d0.imag(), d1.imag());
400
+ }
401
+ };
402
+
403
+ // MMA 8x8x4 TN with Gaussian Complex multiplication:
404
+ // (a + bi)*(c + di)
405
+ // yields
406
+ // t0 += a*c
407
+ // t1 += b*d
408
+ // t2 += (a+b)*(c+d)
409
+ // then
410
+ // re = t0 - t1
411
+ // im = t2 - t0 - t1
412
+ struct SM80_8x8x4_GC64C64C64GC64_TN
413
+ {
414
+ struct GaussComplex {
415
+ double t0, t1, t2;
416
+
417
+ CUTE_HOST_DEVICE //constexpr
418
+ operator complex<double>() const { return complex<double>(t0 - t1, t2 - t0 - t1); }
419
+
420
+ CUTE_HOST_DEVICE friend //constexpr
421
+ complex<double> operator*(GaussComplex const& a, complex<double> const& b) { return static_cast<complex<double>>(a) * b; }
422
+ CUTE_HOST_DEVICE friend //constexpr
423
+ complex<double> operator*(complex<double> const& a, GaussComplex const& b) { return b * a; }
424
+
425
+ CUTE_HOST_DEVICE friend //constexpr
426
+ complex<double> operator+(GaussComplex const& a, complex<double> const& b) { return static_cast<complex<double>>(a) + b; }
427
+ CUTE_HOST_DEVICE friend //constexpr
428
+ complex<double> operator+(complex<double> const& a, GaussComplex const& b) { return b + a; }
429
+ };
430
+
431
+ using DRegisters = GaussComplex[2];
432
+ using ARegisters = complex<double>[1];
433
+ using BRegisters = complex<double>[1];
434
+ using CRegisters = GaussComplex[2];
435
+
436
+ CUTE_HOST_DEVICE static void
437
+ fma(GaussComplex & d0, GaussComplex & d1,
438
+ complex<double> const& a0,
439
+ complex<double> const& b0,
440
+ GaussComplex const& c0, GaussComplex const& c1)
441
+ {
442
+ SM80_8x8x4_F64F64F64F64_TN::fma(d0.t0, d1.t0,
443
+ a0.real(),
444
+ b0.real(),
445
+ c0.t0, c1.t0);
446
+ SM80_8x8x4_F64F64F64F64_TN::fma(d0.t1, d1.t1,
447
+ a0.imag(),
448
+ b0.imag(),
449
+ c0.t1, c1.t1);
450
+ SM80_8x8x4_F64F64F64F64_TN::fma(d0.t2, d1.t2,
451
+ a0.real() + a0.imag(),
452
+ b0.real() + b0.imag(),
453
+ c0.t2, c1.t2);
454
+ }
455
+ };
456
+
457
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
458
+
459
+ // MMA 8x8x16 TN
460
+ struct SM80_8x8x16_S32S8S8S32_TN
461
+ {
462
+ using DRegisters = uint32_t[2];
463
+ using ARegisters = uint32_t[1];
464
+ using BRegisters = uint32_t[1];
465
+ using CRegisters = uint32_t[2];
466
+
467
+ CUTE_HOST_DEVICE static void
468
+ fma(uint32_t & d0, uint32_t & d1,
469
+ uint32_t const& a0,
470
+ uint32_t const& b0,
471
+ uint32_t const& c0, uint32_t const& c1)
472
+ {
473
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
474
+ asm volatile(
475
+ "mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32 "
476
+ "{%0, %1},"
477
+ "{%2},"
478
+ "{%3},"
479
+ "{%4, %5};\n"
480
+ : "=r"(d0), "=r"(d1)
481
+ : "r"(a0),
482
+ "r"(b0),
483
+ "r"(c0), "r"(c1));
484
+ #else
485
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x16_S32S8S8S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
486
+ #endif
487
+ }
488
+ };
489
+
490
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
491
+
492
+ // MMA 8x8x16 TN
493
+ struct SM80_8x8x16_S32S8S8S32_TN_SATURATE
494
+ {
495
+ using DRegisters = uint32_t[2];
496
+ using ARegisters = uint32_t[1];
497
+ using BRegisters = uint32_t[1];
498
+ using CRegisters = uint32_t[2];
499
+
500
+ CUTE_HOST_DEVICE static void
501
+ fma(uint32_t & d0, uint32_t & d1,
502
+ uint32_t const& a0,
503
+ uint32_t const& b0,
504
+ uint32_t const& c0, uint32_t const& c1)
505
+ {
506
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
507
+ asm volatile(
508
+ "mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32.satfinite "
509
+ "{%0, %1},"
510
+ "{%2},"
511
+ "{%3},"
512
+ "{%4, %5};\n"
513
+ : "=r"(d0), "=r"(d1)
514
+ : "r"(a0),
515
+ "r"(b0),
516
+ "r"(c0), "r"(c1));
517
+ #else
518
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x16_S32S8S8S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
519
+ #endif
520
+ }
521
+ };
522
+
523
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
524
+
525
+ // MMA 16x8x16 TN
526
+ struct SM80_16x8x16_S32S8S8S32_TN
527
+ {
528
+ using DRegisters = uint32_t[4];
529
+ using ARegisters = uint32_t[2];
530
+ using BRegisters = uint32_t[1];
531
+ using CRegisters = uint32_t[4];
532
+
533
+ CUTE_HOST_DEVICE static void
534
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
535
+ uint32_t const& a0, uint32_t const& a1,
536
+ uint32_t const& b0,
537
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
538
+ {
539
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
540
+ asm volatile(
541
+ "mma.sync.aligned.m16n8k16.row.col.s32.s8.s8.s32 "
542
+ "{%0, %1, %2, %3},"
543
+ "{%4, %5},"
544
+ "{%6},"
545
+ "{%7, %8, %9, %10};\n"
546
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
547
+ : "r"(a0), "r"(a1),
548
+ "r"(b0),
549
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
550
+ #else
551
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x16_S32S8S8S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
552
+ #endif
553
+ }
554
+ };
555
+
556
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
557
+
558
+ // MMA 16x8x16 TN
559
+ struct SM80_16x8x16_S32S8S8S32_TN_SATURATE
560
+ {
561
+ using DRegisters = uint32_t[4];
562
+ using ARegisters = uint32_t[2];
563
+ using BRegisters = uint32_t[1];
564
+ using CRegisters = uint32_t[4];
565
+
566
+ CUTE_HOST_DEVICE static void
567
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
568
+ uint32_t const& a0, uint32_t const& a1,
569
+ uint32_t const& b0,
570
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
571
+ {
572
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
573
+ asm volatile(
574
+ "mma.sync.aligned.m16n8k16.row.col.s32.s8.s8.s32.satfinite "
575
+ "{%0, %1, %2, %3},"
576
+ "{%4, %5},"
577
+ "{%6},"
578
+ "{%7, %8, %9, %10};\n"
579
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
580
+ : "r"(a0), "r"(a1),
581
+ "r"(b0),
582
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
583
+ #else
584
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x16_S32S8S8S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
585
+ #endif
586
+ }
587
+ };
588
+
589
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
590
+
591
+ // MMA 16x8x32 TN
592
+ struct SM80_16x8x32_S32S8S8S32_TN
593
+ {
594
+ using DRegisters = uint32_t[4];
595
+ using ARegisters = uint32_t[4];
596
+ using BRegisters = uint32_t[2];
597
+ using CRegisters = uint32_t[4];
598
+
599
+ CUTE_HOST_DEVICE static void
600
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
601
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
602
+ uint32_t const& b0, uint32_t const& b1,
603
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
604
+ {
605
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
606
+ asm volatile(
607
+ "mma.sync.aligned.m16n8k32.row.col.s32.s8.s8.s32 "
608
+ "{%0, %1, %2, %3},"
609
+ "{%4, %5, %6, %7},"
610
+ "{%8, %9},"
611
+ "{%10, %11, %12, %13};\n"
612
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
613
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
614
+ "r"(b0), "r"(b1),
615
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
616
+ #else
617
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32S8S8S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
618
+ #endif
619
+ }
620
+ };
621
+
622
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
623
+
624
+ // MMA 16x8x32 TN
625
+ struct SM80_16x8x32_S32S8S8S32_TN_SATURATE
626
+ {
627
+ using DRegisters = uint32_t[4];
628
+ using ARegisters = uint32_t[4];
629
+ using BRegisters = uint32_t[2];
630
+ using CRegisters = uint32_t[4];
631
+
632
+ CUTE_HOST_DEVICE static void
633
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
634
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
635
+ uint32_t const& b0, uint32_t const& b1,
636
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
637
+ {
638
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
639
+ asm volatile(
640
+ "mma.sync.aligned.m16n8k32.row.col.s32.s8.s8.s32.satfinite "
641
+ "{%0, %1, %2, %3},"
642
+ "{%4, %5, %6, %7},"
643
+ "{%8, %9},"
644
+ "{%10, %11, %12, %13};\n"
645
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
646
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
647
+ "r"(b0), "r"(b1),
648
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
649
+ #else
650
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32S8S8S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
651
+ #endif
652
+ }
653
+ };
654
+
655
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
656
+
657
+ // MMA 8x8x16 TN
658
+ struct SM80_8x8x16_S32S8U8S32_TN
659
+ {
660
+ using DRegisters = uint32_t[2];
661
+ using ARegisters = uint32_t[1];
662
+ using BRegisters = uint32_t[1];
663
+ using CRegisters = uint32_t[2];
664
+
665
+ CUTE_HOST_DEVICE static void
666
+ fma(uint32_t & d0, uint32_t & d1,
667
+ uint32_t const& a0,
668
+ uint32_t const& b0,
669
+ uint32_t const& c0, uint32_t const& c1)
670
+ {
671
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
672
+ asm volatile(
673
+ "mma.sync.aligned.m8n8k16.row.col.s32.s8.u8.s32 "
674
+ "{%0, %1},"
675
+ "{%2},"
676
+ "{%3},"
677
+ "{%4, %5};\n"
678
+ : "=r"(d0), "=r"(d1)
679
+ : "r"(a0),
680
+ "r"(b0),
681
+ "r"(c0), "r"(c1));
682
+ #else
683
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x16_S32S8U8S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
684
+ #endif
685
+ }
686
+ };
687
+
688
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
689
+
690
+ // MMA 8x8x16 TN
691
+ struct SM80_8x8x16_S32S8U8S32_TN_SATURATE
692
+ {
693
+ using DRegisters = uint32_t[2];
694
+ using ARegisters = uint32_t[1];
695
+ using BRegisters = uint32_t[1];
696
+ using CRegisters = uint32_t[2];
697
+
698
+ CUTE_HOST_DEVICE static void
699
+ fma(uint32_t & d0, uint32_t & d1,
700
+ uint32_t const& a0,
701
+ uint32_t const& b0,
702
+ uint32_t const& c0, uint32_t const& c1)
703
+ {
704
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
705
+ asm volatile(
706
+ "mma.sync.aligned.m8n8k16.row.col.s32.s8.u8.s32.satfinite "
707
+ "{%0, %1},"
708
+ "{%2},"
709
+ "{%3},"
710
+ "{%4, %5};\n"
711
+ : "=r"(d0), "=r"(d1)
712
+ : "r"(a0),
713
+ "r"(b0),
714
+ "r"(c0), "r"(c1));
715
+ #else
716
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x16_S32S8U8S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
717
+ #endif
718
+ }
719
+ };
720
+
721
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
722
+
723
+ // MMA 16x8x16 TN
724
+ struct SM80_16x8x16_S32S8U8S32_TN
725
+ {
726
+ using DRegisters = uint32_t[4];
727
+ using ARegisters = uint32_t[2];
728
+ using BRegisters = uint32_t[1];
729
+ using CRegisters = uint32_t[4];
730
+
731
+ CUTE_HOST_DEVICE static void
732
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
733
+ uint32_t const& a0, uint32_t const& a1,
734
+ uint32_t const& b0,
735
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
736
+ {
737
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
738
+ asm volatile(
739
+ "mma.sync.aligned.m16n8k16.row.col.s32.s8.u8.s32 "
740
+ "{%0, %1, %2, %3},"
741
+ "{%4, %5},"
742
+ "{%6},"
743
+ "{%7, %8, %9, %10};\n"
744
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
745
+ : "r"(a0), "r"(a1),
746
+ "r"(b0),
747
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
748
+ #else
749
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x16_S32S8U8S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
750
+ #endif
751
+ }
752
+ };
753
+
754
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
755
+
756
+ // MMA 16x8x16 TN
757
+ struct SM80_16x8x16_S32S8U8S32_TN_SATURATE
758
+ {
759
+ using DRegisters = uint32_t[4];
760
+ using ARegisters = uint32_t[2];
761
+ using BRegisters = uint32_t[1];
762
+ using CRegisters = uint32_t[4];
763
+
764
+ CUTE_HOST_DEVICE static void
765
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
766
+ uint32_t const& a0, uint32_t const& a1,
767
+ uint32_t const& b0,
768
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
769
+ {
770
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
771
+ asm volatile(
772
+ "mma.sync.aligned.m16n8k16.row.col.s32.s8.u8.s32.satfinite "
773
+ "{%0, %1, %2, %3},"
774
+ "{%4, %5},"
775
+ "{%6},"
776
+ "{%7, %8, %9, %10};\n"
777
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
778
+ : "r"(a0), "r"(a1),
779
+ "r"(b0),
780
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
781
+ #else
782
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x16_S32S8U8S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
783
+ #endif
784
+ }
785
+ };
786
+
787
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
788
+
789
+ // MMA 16x8x32 TN
790
+ struct SM80_16x8x32_S32S8U8S32_TN
791
+ {
792
+ using DRegisters = uint32_t[4];
793
+ using ARegisters = uint32_t[4];
794
+ using BRegisters = uint32_t[2];
795
+ using CRegisters = uint32_t[4];
796
+
797
+ CUTE_HOST_DEVICE static void
798
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
799
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
800
+ uint32_t const& b0, uint32_t const& b1,
801
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
802
+ {
803
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
804
+ asm volatile(
805
+ "mma.sync.aligned.m16n8k32.row.col.s32.s8.u8.s32 "
806
+ "{%0, %1, %2, %3},"
807
+ "{%4, %5, %6, %7},"
808
+ "{%8, %9},"
809
+ "{%10, %11, %12, %13};\n"
810
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
811
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
812
+ "r"(b0), "r"(b1),
813
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
814
+ #else
815
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32S8U8S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
816
+ #endif
817
+ }
818
+ };
819
+
820
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
821
+
822
+ // MMA 16x8x32 TN
823
+ struct SM80_16x8x32_S32S8U8S32_TN_SATURATE
824
+ {
825
+ using DRegisters = uint32_t[4];
826
+ using ARegisters = uint32_t[4];
827
+ using BRegisters = uint32_t[2];
828
+ using CRegisters = uint32_t[4];
829
+
830
+ CUTE_HOST_DEVICE static void
831
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
832
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
833
+ uint32_t const& b0, uint32_t const& b1,
834
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
835
+ {
836
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
837
+ asm volatile(
838
+ "mma.sync.aligned.m16n8k32.row.col.s32.s8.u8.s32.satfinite "
839
+ "{%0, %1, %2, %3},"
840
+ "{%4, %5, %6, %7},"
841
+ "{%8, %9},"
842
+ "{%10, %11, %12, %13};\n"
843
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
844
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
845
+ "r"(b0), "r"(b1),
846
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
847
+ #else
848
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32S8U8S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
849
+ #endif
850
+ }
851
+ };
852
+
853
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
854
+
855
+ // MMA 8x8x16 TN
856
+ struct SM80_8x8x16_S32U8S8S32_TN
857
+ {
858
+ using DRegisters = uint32_t[2];
859
+ using ARegisters = uint32_t[1];
860
+ using BRegisters = uint32_t[1];
861
+ using CRegisters = uint32_t[2];
862
+
863
+ CUTE_HOST_DEVICE static void
864
+ fma(uint32_t & d0, uint32_t & d1,
865
+ uint32_t const& a0,
866
+ uint32_t const& b0,
867
+ uint32_t const& c0, uint32_t const& c1)
868
+ {
869
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
870
+ asm volatile(
871
+ "mma.sync.aligned.m8n8k16.row.col.s32.u8.s8.s32 "
872
+ "{%0, %1},"
873
+ "{%2},"
874
+ "{%3},"
875
+ "{%4, %5};\n"
876
+ : "=r"(d0), "=r"(d1)
877
+ : "r"(a0),
878
+ "r"(b0),
879
+ "r"(c0), "r"(c1));
880
+ #else
881
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x16_S32U8S8S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
882
+ #endif
883
+ }
884
+ };
885
+
886
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
887
+
888
+ // MMA 8x8x16 TN
889
+ struct SM80_8x8x16_S32U8S8S32_TN_SATURATE
890
+ {
891
+ using DRegisters = uint32_t[2];
892
+ using ARegisters = uint32_t[1];
893
+ using BRegisters = uint32_t[1];
894
+ using CRegisters = uint32_t[2];
895
+
896
+ CUTE_HOST_DEVICE static void
897
+ fma(uint32_t & d0, uint32_t & d1,
898
+ uint32_t const& a0,
899
+ uint32_t const& b0,
900
+ uint32_t const& c0, uint32_t const& c1)
901
+ {
902
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
903
+ asm volatile(
904
+ "mma.sync.aligned.m8n8k16.row.col.s32.u8.s8.s32.satfinite "
905
+ "{%0, %1},"
906
+ "{%2},"
907
+ "{%3},"
908
+ "{%4, %5};\n"
909
+ : "=r"(d0), "=r"(d1)
910
+ : "r"(a0),
911
+ "r"(b0),
912
+ "r"(c0), "r"(c1));
913
+ #else
914
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x16_S32U8S8S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
915
+ #endif
916
+ }
917
+ };
918
+
919
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
920
+
921
+ // MMA 16x8x16 TN
922
+ struct SM80_16x8x16_S32U8S8S32_TN
923
+ {
924
+ using DRegisters = uint32_t[4];
925
+ using ARegisters = uint32_t[2];
926
+ using BRegisters = uint32_t[1];
927
+ using CRegisters = uint32_t[4];
928
+
929
+ CUTE_HOST_DEVICE static void
930
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
931
+ uint32_t const& a0, uint32_t const& a1,
932
+ uint32_t const& b0,
933
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
934
+ {
935
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
936
+ asm volatile(
937
+ "mma.sync.aligned.m16n8k16.row.col.s32.u8.s8.s32 "
938
+ "{%0, %1, %2, %3},"
939
+ "{%4, %5},"
940
+ "{%6},"
941
+ "{%7, %8, %9, %10};\n"
942
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
943
+ : "r"(a0), "r"(a1),
944
+ "r"(b0),
945
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
946
+ #else
947
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x16_S32U8S8S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
948
+ #endif
949
+ }
950
+ };
951
+
952
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
953
+
954
+ // MMA 16x8x16 TN
955
+ struct SM80_16x8x16_S32U8S8S32_TN_SATURATE
956
+ {
957
+ using DRegisters = uint32_t[4];
958
+ using ARegisters = uint32_t[2];
959
+ using BRegisters = uint32_t[1];
960
+ using CRegisters = uint32_t[4];
961
+
962
+ CUTE_HOST_DEVICE static void
963
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
964
+ uint32_t const& a0, uint32_t const& a1,
965
+ uint32_t const& b0,
966
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
967
+ {
968
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
969
+ asm volatile(
970
+ "mma.sync.aligned.m16n8k16.row.col.s32.u8.s8.s32.satfinite "
971
+ "{%0, %1, %2, %3},"
972
+ "{%4, %5},"
973
+ "{%6},"
974
+ "{%7, %8, %9, %10};\n"
975
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
976
+ : "r"(a0), "r"(a1),
977
+ "r"(b0),
978
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
979
+ #else
980
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x16_S32U8S8S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
981
+ #endif
982
+ }
983
+ };
984
+
985
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
986
+
987
+ // MMA 16x8x32 TN
988
+ struct SM80_16x8x32_S32U8S8S32_TN
989
+ {
990
+ using DRegisters = uint32_t[4];
991
+ using ARegisters = uint32_t[4];
992
+ using BRegisters = uint32_t[2];
993
+ using CRegisters = uint32_t[4];
994
+
995
+ CUTE_HOST_DEVICE static void
996
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
997
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
998
+ uint32_t const& b0, uint32_t const& b1,
999
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1000
+ {
1001
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1002
+ asm volatile(
1003
+ "mma.sync.aligned.m16n8k32.row.col.s32.u8.s8.s32 "
1004
+ "{%0, %1, %2, %3},"
1005
+ "{%4, %5, %6, %7},"
1006
+ "{%8, %9},"
1007
+ "{%10, %11, %12, %13};\n"
1008
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1009
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
1010
+ "r"(b0), "r"(b1),
1011
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1012
+ #else
1013
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32U8S8S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
1014
+ #endif
1015
+ }
1016
+ };
1017
+
1018
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1019
+
1020
+ // MMA 16x8x32 TN
1021
+ struct SM80_16x8x32_S32U8S8S32_TN_SATURATE
1022
+ {
1023
+ using DRegisters = uint32_t[4];
1024
+ using ARegisters = uint32_t[4];
1025
+ using BRegisters = uint32_t[2];
1026
+ using CRegisters = uint32_t[4];
1027
+
1028
+ CUTE_HOST_DEVICE static void
1029
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1030
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
1031
+ uint32_t const& b0, uint32_t const& b1,
1032
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1033
+ {
1034
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1035
+ asm volatile(
1036
+ "mma.sync.aligned.m16n8k32.row.col.s32.u8.s8.s32.satfinite "
1037
+ "{%0, %1, %2, %3},"
1038
+ "{%4, %5, %6, %7},"
1039
+ "{%8, %9},"
1040
+ "{%10, %11, %12, %13};\n"
1041
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1042
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
1043
+ "r"(b0), "r"(b1),
1044
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1045
+ #else
1046
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32U8S8S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
1047
+ #endif
1048
+ }
1049
+ };
1050
+
1051
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1052
+
1053
+ // MMA 8x8x16 TN
1054
+ struct SM80_8x8x16_S32U8U8S32_TN
1055
+ {
1056
+ using DRegisters = uint32_t[2];
1057
+ using ARegisters = uint32_t[1];
1058
+ using BRegisters = uint32_t[1];
1059
+ using CRegisters = uint32_t[2];
1060
+
1061
+ CUTE_HOST_DEVICE static void
1062
+ fma(uint32_t & d0, uint32_t & d1,
1063
+ uint32_t const& a0,
1064
+ uint32_t const& b0,
1065
+ uint32_t const& c0, uint32_t const& c1)
1066
+ {
1067
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1068
+ asm volatile(
1069
+ "mma.sync.aligned.m8n8k16.row.col.s32.u8.u8.s32 "
1070
+ "{%0, %1},"
1071
+ "{%2},"
1072
+ "{%3},"
1073
+ "{%4, %5};\n"
1074
+ : "=r"(d0), "=r"(d1)
1075
+ : "r"(a0),
1076
+ "r"(b0),
1077
+ "r"(c0), "r"(c1));
1078
+ #else
1079
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x16_S32U8U8S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
1080
+ #endif
1081
+ }
1082
+ };
1083
+
1084
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1085
+
1086
+ // MMA 8x8x16 TN
1087
+ struct SM80_8x8x16_S32U8U8S32_TN_SATURATE
1088
+ {
1089
+ using DRegisters = uint32_t[2];
1090
+ using ARegisters = uint32_t[1];
1091
+ using BRegisters = uint32_t[1];
1092
+ using CRegisters = uint32_t[2];
1093
+
1094
+ CUTE_HOST_DEVICE static void
1095
+ fma(uint32_t & d0, uint32_t & d1,
1096
+ uint32_t const& a0,
1097
+ uint32_t const& b0,
1098
+ uint32_t const& c0, uint32_t const& c1)
1099
+ {
1100
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1101
+ asm volatile(
1102
+ "mma.sync.aligned.m8n8k16.row.col.s32.u8.u8.s32.satfinite "
1103
+ "{%0, %1},"
1104
+ "{%2},"
1105
+ "{%3},"
1106
+ "{%4, %5};\n"
1107
+ : "=r"(d0), "=r"(d1)
1108
+ : "r"(a0),
1109
+ "r"(b0),
1110
+ "r"(c0), "r"(c1));
1111
+ #else
1112
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x16_S32U8U8S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
1113
+ #endif
1114
+ }
1115
+ };
1116
+
1117
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1118
+
1119
+ // MMA 16x8x16 TN
1120
+ struct SM80_16x8x16_S32U8U8S32_TN
1121
+ {
1122
+ using DRegisters = uint32_t[4];
1123
+ using ARegisters = uint32_t[2];
1124
+ using BRegisters = uint32_t[1];
1125
+ using CRegisters = uint32_t[4];
1126
+
1127
+ CUTE_HOST_DEVICE static void
1128
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1129
+ uint32_t const& a0, uint32_t const& a1,
1130
+ uint32_t const& b0,
1131
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1132
+ {
1133
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1134
+ asm volatile(
1135
+ "mma.sync.aligned.m16n8k16.row.col.s32.u8.u8.s32 "
1136
+ "{%0, %1, %2, %3},"
1137
+ "{%4, %5},"
1138
+ "{%6},"
1139
+ "{%7, %8, %9, %10};\n"
1140
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1141
+ : "r"(a0), "r"(a1),
1142
+ "r"(b0),
1143
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1144
+ #else
1145
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x16_S32U8U8S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
1146
+ #endif
1147
+ }
1148
+ };
1149
+
1150
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1151
+
1152
+ // MMA 16x8x16 TN
1153
+ struct SM80_16x8x16_S32U8U8S32_TN_SATURATE
1154
+ {
1155
+ using DRegisters = uint32_t[4];
1156
+ using ARegisters = uint32_t[2];
1157
+ using BRegisters = uint32_t[1];
1158
+ using CRegisters = uint32_t[4];
1159
+
1160
+ CUTE_HOST_DEVICE static void
1161
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1162
+ uint32_t const& a0, uint32_t const& a1,
1163
+ uint32_t const& b0,
1164
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1165
+ {
1166
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1167
+ asm volatile(
1168
+ "mma.sync.aligned.m16n8k16.row.col.s32.u8.u8.s32.satfinite "
1169
+ "{%0, %1, %2, %3},"
1170
+ "{%4, %5},"
1171
+ "{%6},"
1172
+ "{%7, %8, %9, %10};\n"
1173
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1174
+ : "r"(a0), "r"(a1),
1175
+ "r"(b0),
1176
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1177
+ #else
1178
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x16_S32U8U8S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
1179
+ #endif
1180
+ }
1181
+ };
1182
+
1183
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1184
+
1185
+ // MMA 16x8x32 TN
1186
+ struct SM80_16x8x32_S32U8U8S32_TN
1187
+ {
1188
+ using DRegisters = uint32_t[4];
1189
+ using ARegisters = uint32_t[4];
1190
+ using BRegisters = uint32_t[2];
1191
+ using CRegisters = uint32_t[4];
1192
+
1193
+ CUTE_HOST_DEVICE static void
1194
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1195
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
1196
+ uint32_t const& b0, uint32_t const& b1,
1197
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1198
+ {
1199
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1200
+ asm volatile(
1201
+ "mma.sync.aligned.m16n8k32.row.col.s32.u8.u8.s32 "
1202
+ "{%0, %1, %2, %3},"
1203
+ "{%4, %5, %6, %7},"
1204
+ "{%8, %9},"
1205
+ "{%10, %11, %12, %13};\n"
1206
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1207
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
1208
+ "r"(b0), "r"(b1),
1209
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1210
+ #else
1211
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32U8U8S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
1212
+ #endif
1213
+ }
1214
+ };
1215
+
1216
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1217
+
1218
+ // MMA 16x8x32 TN
1219
+ struct SM80_16x8x32_S32U8U8S32_TN_SATURATE
1220
+ {
1221
+ using DRegisters = uint32_t[4];
1222
+ using ARegisters = uint32_t[4];
1223
+ using BRegisters = uint32_t[2];
1224
+ using CRegisters = uint32_t[4];
1225
+
1226
+ CUTE_HOST_DEVICE static void
1227
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1228
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
1229
+ uint32_t const& b0, uint32_t const& b1,
1230
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1231
+ {
1232
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1233
+ asm volatile(
1234
+ "mma.sync.aligned.m16n8k32.row.col.s32.u8.u8.s32.satfinite "
1235
+ "{%0, %1, %2, %3},"
1236
+ "{%4, %5, %6, %7},"
1237
+ "{%8, %9},"
1238
+ "{%10, %11, %12, %13};\n"
1239
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1240
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
1241
+ "r"(b0), "r"(b1),
1242
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1243
+ #else
1244
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32U8U8S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
1245
+ #endif
1246
+ }
1247
+ };
1248
+
1249
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1250
+
1251
+ // MMA 8x8x32 TN
1252
+ struct SM80_8x8x32_S32S4S4S32_TN
1253
+ {
1254
+ using DRegisters = uint32_t[2];
1255
+ using ARegisters = uint32_t[1];
1256
+ using BRegisters = uint32_t[1];
1257
+ using CRegisters = uint32_t[2];
1258
+
1259
+ CUTE_HOST_DEVICE static void
1260
+ fma(uint32_t & d0, uint32_t & d1,
1261
+ uint32_t const& a0,
1262
+ uint32_t const& b0,
1263
+ uint32_t const& c0, uint32_t const& c1)
1264
+ {
1265
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1266
+ asm volatile(
1267
+ "mma.sync.aligned.m8n8k32.row.col.s32.s4.s4.s32 "
1268
+ "{%0, %1},"
1269
+ "{%2},"
1270
+ "{%3},"
1271
+ "{%4, %5};\n"
1272
+ : "=r"(d0), "=r"(d1)
1273
+ : "r"(a0),
1274
+ "r"(b0),
1275
+ "r"(c0), "r"(c1));
1276
+ #else
1277
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x32_S32S4S4S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
1278
+ #endif
1279
+ }
1280
+ };
1281
+
1282
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1283
+
1284
+ // MMA 8x8x32 TN
1285
+ struct SM80_8x8x32_S32S4S4S32_TN_SATURATE
1286
+ {
1287
+ using DRegisters = uint32_t[2];
1288
+ using ARegisters = uint32_t[1];
1289
+ using BRegisters = uint32_t[1];
1290
+ using CRegisters = uint32_t[2];
1291
+
1292
+ CUTE_HOST_DEVICE static void
1293
+ fma(uint32_t & d0, uint32_t & d1,
1294
+ uint32_t const& a0,
1295
+ uint32_t const& b0,
1296
+ uint32_t const& c0, uint32_t const& c1)
1297
+ {
1298
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1299
+ asm volatile(
1300
+ "mma.sync.aligned.m8n8k32.row.col.s32.s4.s4.s32.satfinite "
1301
+ "{%0, %1},"
1302
+ "{%2},"
1303
+ "{%3},"
1304
+ "{%4, %5};\n"
1305
+ : "=r"(d0), "=r"(d1)
1306
+ : "r"(a0),
1307
+ "r"(b0),
1308
+ "r"(c0), "r"(c1));
1309
+ #else
1310
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x32_S32S4S4S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
1311
+ #endif
1312
+ }
1313
+ };
1314
+
1315
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1316
+
1317
+ // MMA 16x8x32 TN
1318
+ struct SM80_16x8x32_S32S4S4S32_TN
1319
+ {
1320
+ using DRegisters = uint32_t[4];
1321
+ using ARegisters = uint32_t[2];
1322
+ using BRegisters = uint32_t[1];
1323
+ using CRegisters = uint32_t[4];
1324
+
1325
+ CUTE_HOST_DEVICE static void
1326
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1327
+ uint32_t const& a0, uint32_t const& a1,
1328
+ uint32_t const& b0,
1329
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1330
+ {
1331
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1332
+ asm volatile(
1333
+ "mma.sync.aligned.m16n8k32.row.col.s32.s4.s4.s32 "
1334
+ "{%0, %1, %2, %3},"
1335
+ "{%4, %5},"
1336
+ "{%6},"
1337
+ "{%7, %8, %9, %10};\n"
1338
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1339
+ : "r"(a0), "r"(a1),
1340
+ "r"(b0),
1341
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1342
+ #else
1343
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32S4S4S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
1344
+ #endif
1345
+ }
1346
+ };
1347
+
1348
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1349
+
1350
+ // MMA 16x8x32 TN
1351
+ struct SM80_16x8x32_S32S4S4S32_TN_SATURATE
1352
+ {
1353
+ using DRegisters = uint32_t[4];
1354
+ using ARegisters = uint32_t[2];
1355
+ using BRegisters = uint32_t[1];
1356
+ using CRegisters = uint32_t[4];
1357
+
1358
+ CUTE_HOST_DEVICE static void
1359
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1360
+ uint32_t const& a0, uint32_t const& a1,
1361
+ uint32_t const& b0,
1362
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1363
+ {
1364
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1365
+ asm volatile(
1366
+ "mma.sync.aligned.m16n8k32.row.col.s32.s4.s4.s32.satfinite "
1367
+ "{%0, %1, %2, %3},"
1368
+ "{%4, %5},"
1369
+ "{%6},"
1370
+ "{%7, %8, %9, %10};\n"
1371
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1372
+ : "r"(a0), "r"(a1),
1373
+ "r"(b0),
1374
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1375
+ #else
1376
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32S4S4S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
1377
+ #endif
1378
+ }
1379
+ };
1380
+
1381
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1382
+
1383
+ // MMA 16x8x64 TN
1384
+ struct SM80_16x8x64_S32S4S4S32_TN
1385
+ {
1386
+ using DRegisters = uint32_t[4];
1387
+ using ARegisters = uint32_t[4];
1388
+ using BRegisters = uint32_t[2];
1389
+ using CRegisters = uint32_t[4];
1390
+
1391
+ CUTE_HOST_DEVICE static void
1392
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1393
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
1394
+ uint32_t const& b0, uint32_t const& b1,
1395
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1396
+ {
1397
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1398
+ asm volatile(
1399
+ "mma.sync.aligned.m16n8k64.row.col.s32.s4.s4.s32 "
1400
+ "{%0, %1, %2, %3},"
1401
+ "{%4, %5, %6, %7},"
1402
+ "{%8, %9},"
1403
+ "{%10, %11, %12, %13};\n"
1404
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1405
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
1406
+ "r"(b0), "r"(b1),
1407
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1408
+ #else
1409
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x64_S32S4S4S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
1410
+ #endif
1411
+ }
1412
+ };
1413
+
1414
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1415
+
1416
+ // MMA 16x8x64 TN
1417
+ struct SM80_16x8x64_S32S4S4S32_TN_SATURATE
1418
+ {
1419
+ using DRegisters = uint32_t[4];
1420
+ using ARegisters = uint32_t[4];
1421
+ using BRegisters = uint32_t[2];
1422
+ using CRegisters = uint32_t[4];
1423
+
1424
+ CUTE_HOST_DEVICE static void
1425
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1426
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
1427
+ uint32_t const& b0, uint32_t const& b1,
1428
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1429
+ {
1430
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1431
+ asm volatile(
1432
+ "mma.sync.aligned.m16n8k64.row.col.s32.s4.s4.s32.satfinite "
1433
+ "{%0, %1, %2, %3},"
1434
+ "{%4, %5, %6, %7},"
1435
+ "{%8, %9},"
1436
+ "{%10, %11, %12, %13};\n"
1437
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1438
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
1439
+ "r"(b0), "r"(b1),
1440
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1441
+ #else
1442
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x64_S32S4S4S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
1443
+ #endif
1444
+ }
1445
+ };
1446
+
1447
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1448
+
1449
+ // MMA 8x8x32 TN
1450
+ struct SM80_8x8x32_S32S4U4S32_TN
1451
+ {
1452
+ using DRegisters = uint32_t[2];
1453
+ using ARegisters = uint32_t[1];
1454
+ using BRegisters = uint32_t[1];
1455
+ using CRegisters = uint32_t[2];
1456
+
1457
+ CUTE_HOST_DEVICE static void
1458
+ fma(uint32_t & d0, uint32_t & d1,
1459
+ uint32_t const& a0,
1460
+ uint32_t const& b0,
1461
+ uint32_t const& c0, uint32_t const& c1)
1462
+ {
1463
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1464
+ asm volatile(
1465
+ "mma.sync.aligned.m8n8k32.row.col.s32.s4.u4.s32 "
1466
+ "{%0, %1},"
1467
+ "{%2},"
1468
+ "{%3},"
1469
+ "{%4, %5};\n"
1470
+ : "=r"(d0), "=r"(d1)
1471
+ : "r"(a0),
1472
+ "r"(b0),
1473
+ "r"(c0), "r"(c1));
1474
+ #else
1475
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x32_S32S4U4S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
1476
+ #endif
1477
+ }
1478
+ };
1479
+
1480
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1481
+
1482
+ // MMA 8x8x32 TN
1483
+ struct SM80_8x8x32_S32S4U4S32_TN_SATURATE
1484
+ {
1485
+ using DRegisters = uint32_t[2];
1486
+ using ARegisters = uint32_t[1];
1487
+ using BRegisters = uint32_t[1];
1488
+ using CRegisters = uint32_t[2];
1489
+
1490
+ CUTE_HOST_DEVICE static void
1491
+ fma(uint32_t & d0, uint32_t & d1,
1492
+ uint32_t const& a0,
1493
+ uint32_t const& b0,
1494
+ uint32_t const& c0, uint32_t const& c1)
1495
+ {
1496
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1497
+ asm volatile(
1498
+ "mma.sync.aligned.m8n8k32.row.col.s32.s4.u4.s32.satfinite "
1499
+ "{%0, %1},"
1500
+ "{%2},"
1501
+ "{%3},"
1502
+ "{%4, %5};\n"
1503
+ : "=r"(d0), "=r"(d1)
1504
+ : "r"(a0),
1505
+ "r"(b0),
1506
+ "r"(c0), "r"(c1));
1507
+ #else
1508
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x32_S32S4U4S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
1509
+ #endif
1510
+ }
1511
+ };
1512
+
1513
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1514
+
1515
+ // MMA 16x8x32 TN
1516
+ struct SM80_16x8x32_S32S4U4S32_TN
1517
+ {
1518
+ using DRegisters = uint32_t[4];
1519
+ using ARegisters = uint32_t[2];
1520
+ using BRegisters = uint32_t[1];
1521
+ using CRegisters = uint32_t[4];
1522
+
1523
+ CUTE_HOST_DEVICE static void
1524
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1525
+ uint32_t const& a0, uint32_t const& a1,
1526
+ uint32_t const& b0,
1527
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1528
+ {
1529
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1530
+ asm volatile(
1531
+ "mma.sync.aligned.m16n8k32.row.col.s32.s4.u4.s32 "
1532
+ "{%0, %1, %2, %3},"
1533
+ "{%4, %5},"
1534
+ "{%6},"
1535
+ "{%7, %8, %9, %10};\n"
1536
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1537
+ : "r"(a0), "r"(a1),
1538
+ "r"(b0),
1539
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1540
+ #else
1541
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32S4U4S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
1542
+ #endif
1543
+ }
1544
+ };
1545
+
1546
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1547
+
1548
+ // MMA 16x8x32 TN
1549
+ struct SM80_16x8x32_S32S4U4S32_TN_SATURATE
1550
+ {
1551
+ using DRegisters = uint32_t[4];
1552
+ using ARegisters = uint32_t[2];
1553
+ using BRegisters = uint32_t[1];
1554
+ using CRegisters = uint32_t[4];
1555
+
1556
+ CUTE_HOST_DEVICE static void
1557
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1558
+ uint32_t const& a0, uint32_t const& a1,
1559
+ uint32_t const& b0,
1560
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1561
+ {
1562
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1563
+ asm volatile(
1564
+ "mma.sync.aligned.m16n8k32.row.col.s32.s4.u4.s32.satfinite "
1565
+ "{%0, %1, %2, %3},"
1566
+ "{%4, %5},"
1567
+ "{%6},"
1568
+ "{%7, %8, %9, %10};\n"
1569
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1570
+ : "r"(a0), "r"(a1),
1571
+ "r"(b0),
1572
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1573
+ #else
1574
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32S4U4S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
1575
+ #endif
1576
+ }
1577
+ };
1578
+
1579
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1580
+
1581
+ // MMA 16x8x64 TN
1582
+ struct SM80_16x8x64_S32S4U4S32_TN
1583
+ {
1584
+ using DRegisters = uint32_t[4];
1585
+ using ARegisters = uint32_t[4];
1586
+ using BRegisters = uint32_t[2];
1587
+ using CRegisters = uint32_t[4];
1588
+
1589
+ CUTE_HOST_DEVICE static void
1590
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1591
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
1592
+ uint32_t const& b0, uint32_t const& b1,
1593
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1594
+ {
1595
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1596
+ asm volatile(
1597
+ "mma.sync.aligned.m16n8k64.row.col.s32.s4.u4.s32 "
1598
+ "{%0, %1, %2, %3},"
1599
+ "{%4, %5, %6, %7},"
1600
+ "{%8, %9},"
1601
+ "{%10, %11, %12, %13};\n"
1602
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1603
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
1604
+ "r"(b0), "r"(b1),
1605
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1606
+ #else
1607
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x64_S32S4U4S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
1608
+ #endif
1609
+ }
1610
+ };
1611
+
1612
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1613
+
1614
+ // MMA 16x8x64 TN
1615
+ struct SM80_16x8x64_S32S4U4S32_TN_SATURATE
1616
+ {
1617
+ using DRegisters = uint32_t[4];
1618
+ using ARegisters = uint32_t[4];
1619
+ using BRegisters = uint32_t[2];
1620
+ using CRegisters = uint32_t[4];
1621
+
1622
+ CUTE_HOST_DEVICE static void
1623
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1624
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
1625
+ uint32_t const& b0, uint32_t const& b1,
1626
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1627
+ {
1628
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1629
+ asm volatile(
1630
+ "mma.sync.aligned.m16n8k64.row.col.s32.s4.u4.s32.satfinite "
1631
+ "{%0, %1, %2, %3},"
1632
+ "{%4, %5, %6, %7},"
1633
+ "{%8, %9},"
1634
+ "{%10, %11, %12, %13};\n"
1635
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1636
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
1637
+ "r"(b0), "r"(b1),
1638
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1639
+ #else
1640
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x64_S32S4U4S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
1641
+ #endif
1642
+ }
1643
+ };
1644
+
1645
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1646
+
1647
+ // MMA 8x8x32 TN
1648
+ struct SM80_8x8x32_S32U4S4S32_TN
1649
+ {
1650
+ using DRegisters = uint32_t[2];
1651
+ using ARegisters = uint32_t[1];
1652
+ using BRegisters = uint32_t[1];
1653
+ using CRegisters = uint32_t[2];
1654
+
1655
+ CUTE_HOST_DEVICE static void
1656
+ fma(uint32_t & d0, uint32_t & d1,
1657
+ uint32_t const& a0,
1658
+ uint32_t const& b0,
1659
+ uint32_t const& c0, uint32_t const& c1)
1660
+ {
1661
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1662
+ asm volatile(
1663
+ "mma.sync.aligned.m8n8k32.row.col.s32.u4.s4.s32 "
1664
+ "{%0, %1},"
1665
+ "{%2},"
1666
+ "{%3},"
1667
+ "{%4, %5};\n"
1668
+ : "=r"(d0), "=r"(d1)
1669
+ : "r"(a0),
1670
+ "r"(b0),
1671
+ "r"(c0), "r"(c1));
1672
+ #else
1673
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x32_S32U4S4S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
1674
+ #endif
1675
+ }
1676
+ };
1677
+
1678
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1679
+
1680
+ // MMA 8x8x32 TN
1681
+ struct SM80_8x8x32_S32U4S4S32_TN_SATURATE
1682
+ {
1683
+ using DRegisters = uint32_t[2];
1684
+ using ARegisters = uint32_t[1];
1685
+ using BRegisters = uint32_t[1];
1686
+ using CRegisters = uint32_t[2];
1687
+
1688
+ CUTE_HOST_DEVICE static void
1689
+ fma(uint32_t & d0, uint32_t & d1,
1690
+ uint32_t const& a0,
1691
+ uint32_t const& b0,
1692
+ uint32_t const& c0, uint32_t const& c1)
1693
+ {
1694
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1695
+ asm volatile(
1696
+ "mma.sync.aligned.m8n8k32.row.col.s32.u4.s4.s32.satfinite "
1697
+ "{%0, %1},"
1698
+ "{%2},"
1699
+ "{%3},"
1700
+ "{%4, %5};\n"
1701
+ : "=r"(d0), "=r"(d1)
1702
+ : "r"(a0),
1703
+ "r"(b0),
1704
+ "r"(c0), "r"(c1));
1705
+ #else
1706
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x32_S32U4S4S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
1707
+ #endif
1708
+ }
1709
+ };
1710
+
1711
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1712
+
1713
+ // MMA 16x8x32 TN
1714
+ struct SM80_16x8x32_S32U4S4S32_TN
1715
+ {
1716
+ using DRegisters = uint32_t[4];
1717
+ using ARegisters = uint32_t[2];
1718
+ using BRegisters = uint32_t[1];
1719
+ using CRegisters = uint32_t[4];
1720
+
1721
+ CUTE_HOST_DEVICE static void
1722
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1723
+ uint32_t const& a0, uint32_t const& a1,
1724
+ uint32_t const& b0,
1725
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1726
+ {
1727
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1728
+ asm volatile(
1729
+ "mma.sync.aligned.m16n8k32.row.col.s32.u4.s4.s32 "
1730
+ "{%0, %1, %2, %3},"
1731
+ "{%4, %5},"
1732
+ "{%6},"
1733
+ "{%7, %8, %9, %10};\n"
1734
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1735
+ : "r"(a0), "r"(a1),
1736
+ "r"(b0),
1737
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1738
+ #else
1739
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32U4S4S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
1740
+ #endif
1741
+ }
1742
+ };
1743
+
1744
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1745
+
1746
+ // MMA 16x8x32 TN
1747
+ struct SM80_16x8x32_S32U4S4S32_TN_SATURATE
1748
+ {
1749
+ using DRegisters = uint32_t[4];
1750
+ using ARegisters = uint32_t[2];
1751
+ using BRegisters = uint32_t[1];
1752
+ using CRegisters = uint32_t[4];
1753
+
1754
+ CUTE_HOST_DEVICE static void
1755
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1756
+ uint32_t const& a0, uint32_t const& a1,
1757
+ uint32_t const& b0,
1758
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1759
+ {
1760
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1761
+ asm volatile(
1762
+ "mma.sync.aligned.m16n8k32.row.col.s32.u4.s4.s32.satfinite "
1763
+ "{%0, %1, %2, %3},"
1764
+ "{%4, %5},"
1765
+ "{%6},"
1766
+ "{%7, %8, %9, %10};\n"
1767
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1768
+ : "r"(a0), "r"(a1),
1769
+ "r"(b0),
1770
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1771
+ #else
1772
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32U4S4S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
1773
+ #endif
1774
+ }
1775
+ };
1776
+
1777
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1778
+
1779
+ // MMA 16x8x64 TN
1780
+ struct SM80_16x8x64_S32U4S4S32_TN
1781
+ {
1782
+ using DRegisters = uint32_t[4];
1783
+ using ARegisters = uint32_t[4];
1784
+ using BRegisters = uint32_t[2];
1785
+ using CRegisters = uint32_t[4];
1786
+
1787
+ CUTE_HOST_DEVICE static void
1788
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1789
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
1790
+ uint32_t const& b0, uint32_t const& b1,
1791
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1792
+ {
1793
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1794
+ asm volatile(
1795
+ "mma.sync.aligned.m16n8k64.row.col.s32.u4.s4.s32 "
1796
+ "{%0, %1, %2, %3},"
1797
+ "{%4, %5, %6, %7},"
1798
+ "{%8, %9},"
1799
+ "{%10, %11, %12, %13};\n"
1800
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1801
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
1802
+ "r"(b0), "r"(b1),
1803
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1804
+ #else
1805
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x64_S32U4S4S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
1806
+ #endif
1807
+ }
1808
+ };
1809
+
1810
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1811
+
1812
+ // MMA 16x8x64 TN
1813
+ struct SM80_16x8x64_S32U4S4S32_TN_SATURATE
1814
+ {
1815
+ using DRegisters = uint32_t[4];
1816
+ using ARegisters = uint32_t[4];
1817
+ using BRegisters = uint32_t[2];
1818
+ using CRegisters = uint32_t[4];
1819
+
1820
+ CUTE_HOST_DEVICE static void
1821
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1822
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
1823
+ uint32_t const& b0, uint32_t const& b1,
1824
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1825
+ {
1826
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1827
+ asm volatile(
1828
+ "mma.sync.aligned.m16n8k64.row.col.s32.u4.s4.s32.satfinite "
1829
+ "{%0, %1, %2, %3},"
1830
+ "{%4, %5, %6, %7},"
1831
+ "{%8, %9},"
1832
+ "{%10, %11, %12, %13};\n"
1833
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1834
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
1835
+ "r"(b0), "r"(b1),
1836
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1837
+ #else
1838
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x64_S32U4S4S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
1839
+ #endif
1840
+ }
1841
+ };
1842
+
1843
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1844
+
1845
+ // MMA 8x8x32 TN
1846
+ struct SM80_8x8x32_S32U4U4S32_TN
1847
+ {
1848
+ using DRegisters = uint32_t[2];
1849
+ using ARegisters = uint32_t[1];
1850
+ using BRegisters = uint32_t[1];
1851
+ using CRegisters = uint32_t[2];
1852
+
1853
+ CUTE_HOST_DEVICE static void
1854
+ fma(uint32_t & d0, uint32_t & d1,
1855
+ uint32_t const& a0,
1856
+ uint32_t const& b0,
1857
+ uint32_t const& c0, uint32_t const& c1)
1858
+ {
1859
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1860
+ asm volatile(
1861
+ "mma.sync.aligned.m8n8k32.row.col.s32.u4.u4.s32 "
1862
+ "{%0, %1},"
1863
+ "{%2},"
1864
+ "{%3},"
1865
+ "{%4, %5};\n"
1866
+ : "=r"(d0), "=r"(d1)
1867
+ : "r"(a0),
1868
+ "r"(b0),
1869
+ "r"(c0), "r"(c1));
1870
+ #else
1871
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x32_S32U4U4S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
1872
+ #endif
1873
+ }
1874
+ };
1875
+
1876
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1877
+
1878
+ // MMA 8x8x32 TN
1879
+ struct SM80_8x8x32_S32U4U4S32_TN_SATURATE
1880
+ {
1881
+ using DRegisters = uint32_t[2];
1882
+ using ARegisters = uint32_t[1];
1883
+ using BRegisters = uint32_t[1];
1884
+ using CRegisters = uint32_t[2];
1885
+
1886
+ CUTE_HOST_DEVICE static void
1887
+ fma(uint32_t & d0, uint32_t & d1,
1888
+ uint32_t const& a0,
1889
+ uint32_t const& b0,
1890
+ uint32_t const& c0, uint32_t const& c1)
1891
+ {
1892
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1893
+ asm volatile(
1894
+ "mma.sync.aligned.m8n8k32.row.col.s32.u4.u4.s32.satfinite "
1895
+ "{%0, %1},"
1896
+ "{%2},"
1897
+ "{%3},"
1898
+ "{%4, %5};\n"
1899
+ : "=r"(d0), "=r"(d1)
1900
+ : "r"(a0),
1901
+ "r"(b0),
1902
+ "r"(c0), "r"(c1));
1903
+ #else
1904
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x32_S32U4U4S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
1905
+ #endif
1906
+ }
1907
+ };
1908
+
1909
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1910
+
1911
+ // MMA 16x8x32 TN
1912
+ struct SM80_16x8x32_S32U4U4S32_TN
1913
+ {
1914
+ using DRegisters = uint32_t[4];
1915
+ using ARegisters = uint32_t[2];
1916
+ using BRegisters = uint32_t[1];
1917
+ using CRegisters = uint32_t[4];
1918
+
1919
+ CUTE_HOST_DEVICE static void
1920
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1921
+ uint32_t const& a0, uint32_t const& a1,
1922
+ uint32_t const& b0,
1923
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1924
+ {
1925
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1926
+ asm volatile(
1927
+ "mma.sync.aligned.m16n8k32.row.col.s32.u4.u4.s32 "
1928
+ "{%0, %1, %2, %3},"
1929
+ "{%4, %5},"
1930
+ "{%6},"
1931
+ "{%7, %8, %9, %10};\n"
1932
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1933
+ : "r"(a0), "r"(a1),
1934
+ "r"(b0),
1935
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1936
+ #else
1937
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32U4U4S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
1938
+ #endif
1939
+ }
1940
+ };
1941
+
1942
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1943
+
1944
+ // MMA 16x8x32 TN
1945
+ struct SM80_16x8x32_S32U4U4S32_TN_SATURATE
1946
+ {
1947
+ using DRegisters = uint32_t[4];
1948
+ using ARegisters = uint32_t[2];
1949
+ using BRegisters = uint32_t[1];
1950
+ using CRegisters = uint32_t[4];
1951
+
1952
+ CUTE_HOST_DEVICE static void
1953
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1954
+ uint32_t const& a0, uint32_t const& a1,
1955
+ uint32_t const& b0,
1956
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1957
+ {
1958
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1959
+ asm volatile(
1960
+ "mma.sync.aligned.m16n8k32.row.col.s32.u4.u4.s32.satfinite "
1961
+ "{%0, %1, %2, %3},"
1962
+ "{%4, %5},"
1963
+ "{%6},"
1964
+ "{%7, %8, %9, %10};\n"
1965
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1966
+ : "r"(a0), "r"(a1),
1967
+ "r"(b0),
1968
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
1969
+ #else
1970
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x32_S32U4U4S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
1971
+ #endif
1972
+ }
1973
+ };
1974
+
1975
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1976
+
1977
+ // MMA 16x8x64 TN
1978
+ struct SM80_16x8x64_S32U4U4S32_TN
1979
+ {
1980
+ using DRegisters = uint32_t[4];
1981
+ using ARegisters = uint32_t[4];
1982
+ using BRegisters = uint32_t[2];
1983
+ using CRegisters = uint32_t[4];
1984
+
1985
+ CUTE_HOST_DEVICE static void
1986
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
1987
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
1988
+ uint32_t const& b0, uint32_t const& b1,
1989
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
1990
+ {
1991
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
1992
+ asm volatile(
1993
+ "mma.sync.aligned.m16n8k64.row.col.s32.u4.u4.s32 "
1994
+ "{%0, %1, %2, %3},"
1995
+ "{%4, %5, %6, %7},"
1996
+ "{%8, %9},"
1997
+ "{%10, %11, %12, %13};\n"
1998
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
1999
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
2000
+ "r"(b0), "r"(b1),
2001
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
2002
+ #else
2003
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x64_S32U4U4S32_TN without CUTE_ARCH_MMA_SM80_ENABLED");
2004
+ #endif
2005
+ }
2006
+ };
2007
+
2008
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
2009
+
2010
+ // MMA 16x8x64 TN
2011
+ struct SM80_16x8x64_S32U4U4S32_TN_SATURATE
2012
+ {
2013
+ using DRegisters = uint32_t[4];
2014
+ using ARegisters = uint32_t[4];
2015
+ using BRegisters = uint32_t[2];
2016
+ using CRegisters = uint32_t[4];
2017
+
2018
+ CUTE_HOST_DEVICE static void
2019
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
2020
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
2021
+ uint32_t const& b0, uint32_t const& b1,
2022
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
2023
+ {
2024
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
2025
+ asm volatile(
2026
+ "mma.sync.aligned.m16n8k64.row.col.s32.u4.u4.s32.satfinite "
2027
+ "{%0, %1, %2, %3},"
2028
+ "{%4, %5, %6, %7},"
2029
+ "{%8, %9},"
2030
+ "{%10, %11, %12, %13};\n"
2031
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
2032
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
2033
+ "r"(b0), "r"(b1),
2034
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
2035
+ #else
2036
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x64_S32U4U4S32_TN_SATURATE without CUTE_ARCH_MMA_SM80_ENABLED");
2037
+ #endif
2038
+ }
2039
+ };
2040
+
2041
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
2042
+
2043
+ // MMA 8x8x128 TN
2044
+ struct SM80_8x8x128_S32U1U1S32_TN_ANDPOPC
2045
+ {
2046
+ using DRegisters = uint32_t[2];
2047
+ using ARegisters = uint32_t[1];
2048
+ using BRegisters = uint32_t[1];
2049
+ using CRegisters = uint32_t[2];
2050
+
2051
+ CUTE_HOST_DEVICE static void
2052
+ fma(uint32_t & d0, uint32_t & d1,
2053
+ uint32_t const& a0,
2054
+ uint32_t const& b0,
2055
+ uint32_t const& c0, uint32_t const& c1)
2056
+ {
2057
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
2058
+ asm volatile(
2059
+ "mma.sync.aligned.m8n8k128.row.col.s32.b1.b1.s32.and.popc "
2060
+ "{%0, %1},"
2061
+ "{%2},"
2062
+ "{%3},"
2063
+ "{%4, %5};\n"
2064
+ : "=r"(d0), "=r"(d1)
2065
+ : "r"(a0),
2066
+ "r"(b0),
2067
+ "r"(c0), "r"(c1));
2068
+ #else
2069
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x128_S32U1U1S32_TN_ANDPOPC without CUTE_ARCH_MMA_SM80_ENABLED");
2070
+ #endif
2071
+ }
2072
+ };
2073
+
2074
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
2075
+
2076
+ // MMA 16x8x128 TN
2077
+ struct SM80_16x8x128_S32U1U1S32_TN_ANDPOPC
2078
+ {
2079
+ using DRegisters = uint32_t[4];
2080
+ using ARegisters = uint32_t[2];
2081
+ using BRegisters = uint32_t[1];
2082
+ using CRegisters = uint32_t[4];
2083
+
2084
+ CUTE_HOST_DEVICE static void
2085
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
2086
+ uint32_t const& a0, uint32_t const& a1,
2087
+ uint32_t const& b0,
2088
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
2089
+ {
2090
+ #if defined(CUTE_ARCH_MMA_SM80_ENABLED)
2091
+ asm volatile(
2092
+ "mma.sync.aligned.m16n8k128.row.col.s32.b1.b1.s32.and.popc "
2093
+ "{%0, %1, %2, %3},"
2094
+ "{%4, %5},"
2095
+ "{%6},"
2096
+ "{%7, %8, %9, %10};\n"
2097
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
2098
+ : "r"(a0), "r"(a1),
2099
+ "r"(b0),
2100
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
2101
+ #else
2102
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x128_S32U1U1S32_TN_ANDPOPC without CUTE_ARCH_MMA_SM80_ENABLED");
2103
+ #endif
2104
+ }
2105
+ };
2106
+
2107
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
2108
+
2109
+ // MMA 16x8x256 TN
2110
+ struct SM80_16x8x256_S32U1U1S32_TN_ANDPOPC
2111
+ {
2112
+ using DRegisters = uint32_t[4];
2113
+ using ARegisters = uint32_t[4];
2114
+ using BRegisters = uint32_t[2];
2115
+ using CRegisters = uint32_t[4];
2116
+
2117
+ CUTE_HOST_DEVICE static void
2118
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
2119
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
2120
+ uint32_t const& b0, uint32_t const& b1,
2121
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
2122
+ {
2123
+ #if defined(CUTE_ARCH_MMA_B1_AND_SM80_ENABLED)
2124
+ asm volatile(
2125
+ "mma.sync.aligned.m16n8k256.row.col.s32.b1.b1.s32.and.popc "
2126
+ "{%0, %1, %2, %3},"
2127
+ "{%4, %5, %6, %7},"
2128
+ "{%8, %9},"
2129
+ "{%10, %11, %12, %13};\n"
2130
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
2131
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
2132
+ "r"(b0), "r"(b1),
2133
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
2134
+ #else
2135
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x256_S32U1U1S32_TN_ANDPOPC without CUTE_ARCH_MMA_SM80_ENABLED");
2136
+ #endif
2137
+ }
2138
+ };
2139
+
2140
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
2141
+
2142
+ // MMA 8x8x128 TN
2143
+ struct SM80_8x8x128_S32U1U1S32_TN_XORPOPC
2144
+ {
2145
+ using DRegisters = uint32_t[2];
2146
+ using ARegisters = uint32_t[1];
2147
+ using BRegisters = uint32_t[1];
2148
+ using CRegisters = uint32_t[2];
2149
+
2150
+ CUTE_HOST_DEVICE static void
2151
+ fma(uint32_t & d0, uint32_t & d1,
2152
+ uint32_t const& a0,
2153
+ uint32_t const& b0,
2154
+ uint32_t const& c0, uint32_t const& c1)
2155
+ {
2156
+ #if defined(CUTE_ARCH_MMA_B1_XOR_SM80_ENABLED)
2157
+ asm volatile(
2158
+ "mma.sync.aligned.m8n8k128.row.col.s32.b1.b1.s32.xor.popc "
2159
+ "{%0, %1},"
2160
+ "{%2},"
2161
+ "{%3},"
2162
+ "{%4, %5};\n"
2163
+ : "=r"(d0), "=r"(d1)
2164
+ : "r"(a0),
2165
+ "r"(b0),
2166
+ "r"(c0), "r"(c1));
2167
+ #else
2168
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_8x8x128_S32U1U1S32_TN_XORPOPC without CUTE_ARCH_MMA_SM80_ENABLED");
2169
+ #endif
2170
+ }
2171
+ };
2172
+
2173
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
2174
+
2175
+ // MMA 16x8x128 TN
2176
+ struct SM80_16x8x128_S32U1U1S32_TN_XORPOPC
2177
+ {
2178
+ using DRegisters = uint32_t[4];
2179
+ using ARegisters = uint32_t[2];
2180
+ using BRegisters = uint32_t[1];
2181
+ using CRegisters = uint32_t[4];
2182
+
2183
+ CUTE_HOST_DEVICE static void
2184
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
2185
+ uint32_t const& a0, uint32_t const& a1,
2186
+ uint32_t const& b0,
2187
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
2188
+ {
2189
+ #if defined(CUTE_ARCH_MMA_B1_XOR_SM80_ENABLED)
2190
+ asm volatile(
2191
+ "mma.sync.aligned.m16n8k128.row.col.s32.b1.b1.s32.xor.popc "
2192
+ "{%0, %1, %2, %3},"
2193
+ "{%4, %5},"
2194
+ "{%6},"
2195
+ "{%7, %8, %9, %10};\n"
2196
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
2197
+ : "r"(a0), "r"(a1),
2198
+ "r"(b0),
2199
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
2200
+ #else
2201
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x128_S32U1U1S32_TN_XORPOPC without CUTE_ARCH_MMA_SM80_ENABLED");
2202
+ #endif
2203
+ }
2204
+ };
2205
+
2206
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
2207
+
2208
+ // MMA 16x8x256 TN
2209
+ struct SM80_16x8x256_S32U1U1S32_TN_XORPOPC
2210
+ {
2211
+ using DRegisters = uint32_t[4];
2212
+ using ARegisters = uint32_t[4];
2213
+ using BRegisters = uint32_t[2];
2214
+ using CRegisters = uint32_t[4];
2215
+
2216
+ CUTE_HOST_DEVICE static void
2217
+ fma(uint32_t & d0, uint32_t & d1, uint32_t & d2, uint32_t & d3,
2218
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
2219
+ uint32_t const& b0, uint32_t const& b1,
2220
+ uint32_t const& c0, uint32_t const& c1, uint32_t const& c2, uint32_t const& c3)
2221
+ {
2222
+ #if defined(CUTE_ARCH_MMA_B1_XOR_SM80_ENABLED)
2223
+ asm volatile(
2224
+ "mma.sync.aligned.m16n8k256.row.col.s32.b1.b1.s32.xor.popc "
2225
+ "{%0, %1, %2, %3},"
2226
+ "{%4, %5, %6, %7},"
2227
+ "{%8, %9},"
2228
+ "{%10, %11, %12, %13};\n"
2229
+ : "=r"(d0), "=r"(d1), "=r"(d2), "=r"(d3)
2230
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
2231
+ "r"(b0), "r"(b1),
2232
+ "r"(c0), "r"(c1), "r"(c2), "r"(c3));
2233
+ #else
2234
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM80_16x8x256_S32U1U1S32_TN_XORPOPC without CUTE_ARCH_MMA_SM80_ENABLED");
2235
+ #endif
2236
+ }
2237
+ };
2238
+
2239
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
2240
+
2241
+ } // namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm89.hpp ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+
32
+ //
33
+
34
+ //
35
+ #pragma once
36
+
37
+ #include <cute/config.hpp>
38
+ #include <cute/arch/mma.hpp>
39
+
40
+ ////////////////////////////////////////////////////////////////////////////////
41
+
42
+ #if (__CUDACC_VER_MAJOR__ > 12) || (__CUDACC_VER_MAJOR__ == 12 && __CUDACC_VER_MINOR__ >= 4)
43
+ # define CUTE_ARCH_MMA_F32_SM89_SUPPORTED
44
+ #endif
45
+
46
+ #if (__CUDACC_VER_MAJOR__ > 12) || (__CUDACC_VER_MAJOR__ == 12 && __CUDACC_VER_MINOR__ >= 8)
47
+ # define CUTE_ARCH_MMA_F16_SM89_SUPPORTED
48
+ #endif
49
+
50
+ #if defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 890)
51
+ # if defined(CUTE_ARCH_MMA_F32_SM89_SUPPORTED)
52
+ # define CUTE_ARCH_MMA_F32_SM89_ENABLED
53
+ # endif
54
+
55
+ # if defined(CUTE_ARCH_MMA_F16_SM89_SUPPORTED)
56
+ # define CUTE_ARCH_MMA_F16_SM89_ENABLED
57
+ # endif
58
+ #endif
59
+
60
+ ////////////////////////////////////////////////////////////////////////////////
61
+
62
+ namespace cute {
63
+ // MMA 16x8x32 TN
64
+ struct SM89_16x8x32_F32E4M3E4M3F32_TN
65
+ {
66
+ using DRegisters = float[4];
67
+ using ARegisters = uint32_t[4];
68
+ using BRegisters = uint32_t[2];
69
+ using CRegisters = float[4];
70
+
71
+ CUTE_HOST_DEVICE static void
72
+ fma(float & d0, float & d1, float & d2, float & d3,
73
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
74
+ uint32_t const& b0, uint32_t const& b1,
75
+ float const& c0, float const& c1, float const& c2, float const& c3)
76
+ {
77
+ #if defined(CUTE_ARCH_MMA_F32_SM89_ENABLED)
78
+ asm(
79
+ "mma.sync.aligned.m16n8k32.row.col.f32.e4m3.e4m3.f32 "
80
+ "{%0,%1,%2,%3}, {%4,%5,%6,%7}, {%8,%9}, {%10,%11,%12,%13};\n"
81
+ : "=f"(d0), "=f"(d1), "=f"(d2), "=f"(d3)
82
+ :
83
+ "r"(a0), "r"(a1), "r"(a2), "r"(a3),
84
+ "r"(b0), "r"(b1),
85
+ "f"(c0), "f"(c1), "f"(c2), "f"(c3)
86
+ );
87
+ #else
88
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM89_16x8x32_F32E4M3E4M3F32_TN without CUTE_ARCH_MMA_F32_SM89_ENABLED");
89
+ #endif
90
+ }
91
+ };
92
+
93
+ struct SM89_16x8x32_F32E4M3E5M2F32_TN
94
+ {
95
+ using DRegisters = float[4];
96
+ using ARegisters = uint32_t[4];
97
+ using BRegisters = uint32_t[2];
98
+ using CRegisters = float[4];
99
+
100
+ CUTE_HOST_DEVICE static void
101
+ fma(float & d0, float & d1, float & d2, float & d3,
102
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
103
+ uint32_t const& b0, uint32_t const& b1,
104
+ float const& c0, float const& c1, float const& c2, float const& c3)
105
+ {
106
+ #if defined(CUTE_ARCH_MMA_F32_SM89_ENABLED)
107
+ asm(
108
+ "mma.sync.aligned.m16n8k32.row.col.f32.e4m3.e5m2.f32 "
109
+ "{%0,%1,%2,%3}, {%4,%5,%6,%7}, {%8,%9}, {%10,%11,%12,%13};\n"
110
+ : "=f"(d0), "=f"(d1), "=f"(d2), "=f"(d3)
111
+ :
112
+ "r"(a0), "r"(a1), "r"(a2), "r"(a3),
113
+ "r"(b0), "r"(b1),
114
+ "f"(c0), "f"(c1), "f"(c2), "f"(c3)
115
+ );
116
+ #else
117
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM89_16x8x32_F32E4M3E5M2F32_TN without CUTE_ARCH_MMA_F32_SM89_ENABLED");
118
+ #endif
119
+ }
120
+ };
121
+
122
+ struct SM89_16x8x32_F32E5M2E5M2F32_TN
123
+ {
124
+ using DRegisters = float[4];
125
+ using ARegisters = uint32_t[4];
126
+ using BRegisters = uint32_t[2];
127
+ using CRegisters = float[4];
128
+
129
+ CUTE_HOST_DEVICE static void
130
+ fma(float & d0, float & d1, float & d2, float & d3,
131
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
132
+ uint32_t const& b0, uint32_t const& b1,
133
+ float const& c0, float const& c1, float const& c2, float const& c3)
134
+ {
135
+ #if defined(CUTE_ARCH_MMA_F32_SM89_ENABLED)
136
+ asm(
137
+ "mma.sync.aligned.m16n8k32.row.col.f32.e5m2.e5m2.f32 "
138
+ "{%0,%1,%2,%3}, {%4,%5,%6,%7}, {%8,%9}, {%10,%11,%12,%13};\n"
139
+ : "=f"(d0), "=f"(d1), "=f"(d2), "=f"(d3)
140
+ :
141
+ "r"(a0), "r"(a1), "r"(a2), "r"(a3),
142
+ "r"(b0), "r"(b1),
143
+ "f"(c0), "f"(c1), "f"(c2), "f"(c3)
144
+ );
145
+ #else
146
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM89_16x8x32_F32E5M2E5M2F32_TN without CUTE_ARCH_MMA_F32_SM89_ENABLED");
147
+ #endif
148
+ }
149
+ };
150
+
151
+ struct SM89_16x8x32_F32E5M2E4M3F32_TN
152
+ {
153
+ using DRegisters = float[4];
154
+ using ARegisters = uint32_t[4];
155
+ using BRegisters = uint32_t[2];
156
+ using CRegisters = float[4];
157
+
158
+ CUTE_HOST_DEVICE static void
159
+ fma(float & d0, float & d1, float & d2, float & d3,
160
+ uint32_t const& a0, uint32_t const& a1, uint32_t const& a2, uint32_t const& a3,
161
+ uint32_t const& b0, uint32_t const& b1,
162
+ float const& c0, float const& c1, float const& c2, float const& c3)
163
+ {
164
+ #if defined(CUTE_ARCH_MMA_F32_SM89_ENABLED)
165
+ asm(
166
+ "mma.sync.aligned.m16n8k32.row.col.f32.e5m2.e4m3.f32 "
167
+ "{%0,%1,%2,%3}, {%4,%5,%6,%7}, {%8,%9}, {%10,%11,%12,%13};\n"
168
+ : "=f"(d0), "=f"(d1), "=f"(d2), "=f"(d3)
169
+ :
170
+ "r"(a0), "r"(a1), "r"(a2), "r"(a3),
171
+ "r"(b0), "r"(b1),
172
+ "f"(c0), "f"(c1), "f"(c2), "f"(c3)
173
+ );
174
+ #else
175
+ CUTE_INVALID_CONTROL_PATH("Attempting to use SM89_16x8x32_F32E5M2E4M3F32_TN without CUTE_ARCH_MMA_F32_SM89_ENABLED");
176
+ #endif
177
+ }
178
+ };
179
+
180
+ } // namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm90.hpp ADDED
The diff for this file is too large to render. See raw diff
 
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm90_desc.hpp ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+
32
+ #pragma once
33
+
34
+ #include <cute/arch/config.hpp>
35
+
36
+ #include <cute/arch/mma.hpp>
37
+
38
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
39
+
40
+ namespace cute {
41
+
42
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
43
+ // GMMA Descriptor and utilities
44
+
45
+ // GMMA enums and utilities
46
+ namespace SM90::GMMA {
47
+
48
+ enum class LayoutType : uint8_t {
49
+ INTERLEAVE = 0,
50
+ B128 = 1,
51
+ B64 = 2,
52
+ B32 = 3,
53
+ };
54
+
55
+ CUTE_HOST_DEVICE char const* to_string(LayoutType const& t) {
56
+ switch (t) {
57
+ case LayoutType::INTERLEAVE: return "INTERLEAVE";
58
+ case LayoutType::B128: return "B128";
59
+ case LayoutType::B64: return "B64";
60
+ case LayoutType::B32: return "B32";
61
+ }
62
+ return nullptr;
63
+ }
64
+
65
+ #if !defined(__CUDACC_RTC__)
66
+ // Output operator for all enums in this namespace
67
+ CUTE_HOST std::ostream& operator<<(std::ostream& os, LayoutType const& t) {
68
+ char const* s = to_string(t);
69
+ if (s) {
70
+ std::operator<<(os, s); // Explicit call to avoid ambiguity
71
+ } else {
72
+ os.setstate(std::ios_base::failbit);
73
+ }
74
+ return os;
75
+ }
76
+ #endif // !defined(__CUDACC_RTC__)
77
+
78
+ } // end namespace SM90::GMMA
79
+
80
+ union GmmaDescriptor
81
+ {
82
+ CUTE_HOST_DEVICE constexpr
83
+ GmmaDescriptor() noexcept : desc_(0) {}
84
+ CUTE_HOST_DEVICE constexpr
85
+ GmmaDescriptor(uint64_t desc) noexcept : desc_(desc) {}
86
+ CUTE_HOST_DEVICE constexpr
87
+ GmmaDescriptor(GmmaDescriptor const& t) noexcept : desc_(t.desc_) {}
88
+ CUTE_HOST_DEVICE constexpr
89
+ GmmaDescriptor(GmmaDescriptor && t) noexcept : desc_(t.desc_) {}
90
+
91
+ CUTE_HOST_DEVICE constexpr
92
+ GmmaDescriptor& operator=(GmmaDescriptor const& t) noexcept {
93
+ desc_ = t.desc_;
94
+ return *this;
95
+ }
96
+
97
+ CUTE_HOST_DEVICE constexpr
98
+ GmmaDescriptor& operator=(GmmaDescriptor && t) noexcept {
99
+ desc_ = t.desc_;
100
+ return *this;
101
+ }
102
+
103
+ uint64_t desc_;
104
+ uint32_t reg32_[2];
105
+ uint16_t reg16_[4];
106
+
107
+ // Bitfield implementation avoids the need for shifts in assignment
108
+ struct {
109
+ // start_address, bit [0,14), 4LSB not included
110
+ uint16_t start_address_ : 14, : 2; // 14 bits [0,14), 2 bits unused
111
+ // leading dimension byte offset, bit [16,30), 4LSB not included
112
+ // For N: This is the stride from the first col to the second col of the 8x2 brick in INTERLEAVED
113
+ // Unused for all SWIZZLE_* layouts (and assumed to be 1)
114
+ // For T: This is the stride from the first 8 rows to the next 8 rows.
115
+ uint16_t leading_byte_offset_ : 14, : 2; // 14 bits [0,14), 2 bits unused
116
+ // stride dimension byte offset, bit [32,46), 4LSB not included
117
+ // For N: This is the stride from the first 8 rows to the next 8 rows.
118
+ // For T: This is the stride fro mthe first 8 cols to the next 8 cols.
119
+ uint16_t stride_byte_offset_ : 14, : 2; // 14 bits [0,14), 2 bits unused
120
+ // base_offset, bit [49,52)
121
+ // Valid only for SWIZZLE_128B and SWIZZLE_64B
122
+ uint8_t : 1, base_offset_ : 3, : 4; // 1 bit unused, 3 bits [1,4), 4 bits unused
123
+ // layout type, bit [62,64)
124
+ // SWIZZLE_NONE = 0, SWIZZLE_32B = 3, SWIZZLE_64B = 2, SWIZZLE_128B = 1
125
+ uint8_t : 6, layout_type_ : 2; // 6 bits unused, 2 bits [6,8)
126
+ } bitfield;
127
+
128
+ // Decay to a uint64_t
129
+ CUTE_HOST_DEVICE constexpr
130
+ operator uint64_t() const noexcept { return desc_; }
131
+ };
132
+
133
+ // Printer
134
+ CUTE_HOST_DEVICE void
135
+ print(GmmaDescriptor const& t)
136
+ {
137
+ #if !defined(__CUDACC_RTC__)
138
+ printf("GmmaDescriptor: 0x%016llx\n", static_cast<unsigned long long>(t.desc_));
139
+ printf(" start_addr : 0x%04x\n", t.bitfield.start_address_);
140
+ printf(" leading_off: 0x%04x (%d)\n", t.bitfield.leading_byte_offset_, t.bitfield.leading_byte_offset_);
141
+ printf(" stride_off : 0x%04x (%d)\n", t.bitfield.stride_byte_offset_, t.bitfield.stride_byte_offset_);
142
+ printf(" base_offset: 0x%01x\n", t.bitfield.base_offset_);
143
+ printf(" layout_type: 0x%01x (%s)\n", t.bitfield.layout_type_, to_string(static_cast<SM90::GMMA::LayoutType>(t.bitfield.layout_type_)));
144
+ #endif // !defined(__CUDACC_RTC__)
145
+ }
146
+
147
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
148
+
149
+ } // namespace cute
150
+
151
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm90_gmma.hpp ADDED
The diff for this file is too large to render. See raw diff
 
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm90_gmma_ext.hpp ADDED
The diff for this file is too large to render. See raw diff
 
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm90_gmma_sparse.hpp ADDED
The diff for this file is too large to render. See raw diff
 
lib/python3.12/site-packages/deep_gemm/include/cute/arch/mma_sm90_gmma_sparse_ext.hpp ADDED
The diff for this file is too large to render. See raw diff
 
lib/python3.12/site-packages/deep_gemm/include/cute/arch/simd_sm100.hpp ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2024 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ //
32
+
33
+ //
34
+
35
+ #pragma once
36
+
37
+ #include <cute/config.hpp>
38
+ #include <cute/arch/config.hpp>
39
+ #include <cute/numeric/real.hpp>
40
+
41
+ namespace cute {
42
+
43
+ CUTE_HOST_DEVICE
44
+ void
45
+ add(float2 & c,
46
+ float2 const& a,
47
+ float2 const& b)
48
+ {
49
+ #if defined(CUTE_ARCH_FLOAT2_MATH_ENABLED)
50
+ asm volatile("add.f32x2 %0, %1, %2;\n"
51
+ : "=l"(reinterpret_cast<uint64_t &>(c))
52
+ : "l"(reinterpret_cast<uint64_t const&>(a)),
53
+ "l"(reinterpret_cast<uint64_t const&>(b)));
54
+ #else
55
+ add(c.x, a.x, b.x);
56
+ add(c.y, a.y, b.y);
57
+ #endif
58
+ }
59
+
60
+ CUTE_HOST_DEVICE
61
+ void
62
+ mul(float2 & c,
63
+ float2 const& a,
64
+ float2 const& b)
65
+ {
66
+ #if defined(CUTE_ARCH_FLOAT2_MATH_ENABLED)
67
+ asm volatile("mul.f32x2 %0, %1, %2;\n"
68
+ : "=l"(reinterpret_cast<uint64_t &>(c))
69
+ : "l"(reinterpret_cast<uint64_t const&>(a)),
70
+ "l"(reinterpret_cast<uint64_t const&>(b)));
71
+ #else
72
+ mul(c.x, a.x, b.x);
73
+ mul(c.y, a.y, b.y);
74
+ #endif
75
+ }
76
+
77
+ CUTE_HOST_DEVICE
78
+ void
79
+ fma(float2 & d,
80
+ float2 const& a,
81
+ float2 const& b,
82
+ float2 const& c)
83
+ {
84
+ #if defined(CUTE_ARCH_FLOAT2_MATH_ENABLED)
85
+ asm volatile("fma.rn.f32x2 %0, %1, %2, %3;\n"
86
+ : "=l"(reinterpret_cast<uint64_t &>(d))
87
+ : "l"(reinterpret_cast<uint64_t const&>(a)),
88
+ "l"(reinterpret_cast<uint64_t const&>(b)),
89
+ "l"(reinterpret_cast<uint64_t const&>(c)));
90
+ #else
91
+ fma(d.x, a.x, b.x, c.x);
92
+ fma(d.y, a.y, b.y, c.y);
93
+ #endif
94
+ }
95
+
96
+ } // namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/arch/tmem_allocator_sm100.hpp ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ //
32
+
33
+ //
34
+ #pragma once
35
+
36
+ #include <cute/arch/config.hpp>
37
+ #include <cute/arch/cluster_sm90.hpp>
38
+ #include <cute/atom/copy_traits_sm100.hpp>
39
+
40
+ #include <cutlass/pipeline/sm90_pipeline.hpp>
41
+
42
+ namespace cute::TMEM {
43
+
44
+ // All operations of this class require that only a single warp uniformly participates
45
+ class Allocator1Sm {
46
+ public:
47
+ static constexpr int ColumnsPerAllocationSlice = 32;
48
+ static constexpr int Sm100TmemCapacityColumns = 512;
49
+
50
+ __device__ Allocator1Sm() { }
51
+
52
+ /**
53
+ * Performs a non-blocking allocation of TMEM.
54
+ * @param num_columns Number of columns being freed. Must be 32 <= num_columns <= 512 and power of 2.
55
+ * @param dst_ptr Pointer to shared memory to which to write the result tmem pointer to.
56
+ * @pre Must be issued by a single fully active warp of the CTA.
57
+ * @pre Must never be issued by more than one warp at the same time.
58
+ * @pre For repeated allocations, the same warp must be used to issue all allocations.
59
+ **/
60
+ CUTE_HOST_DEVICE void
61
+ allocate(int num_columns, uint32_t* dst_ptr) {
62
+ #if defined(CUTE_ARCH_TCGEN05_TMEM_ENABLED)
63
+ uint32_t dst_intptr = cute::cast_smem_ptr_to_uint(dst_ptr);
64
+ asm volatile(
65
+ "tcgen05.alloc.cta_group::1.sync.aligned.shared::cta.b32 [%0], %1;"
66
+ :
67
+ : "r"(dst_intptr), "r"(num_columns));
68
+ #else
69
+ CUTE_INVALID_CONTROL_PATH("Attempting to use TMEM allocation PTX without CUTE_ARCH_TCGEN05_TMEM_ENABLED");
70
+ #endif
71
+ }
72
+
73
+ __device__
74
+ void
75
+ free(uint32_t tmem_ptr, int num_columns) {
76
+ #if defined(CUTE_ARCH_TCGEN05_TMEM_ENABLED)
77
+ asm volatile(
78
+ "{\n\t"
79
+ "tcgen05.dealloc.cta_group::1.sync.aligned.b32 %0, %1; \n\t"
80
+ "}"
81
+ :
82
+ : "r"(tmem_ptr), "r"(num_columns));
83
+ #else
84
+ CUTE_INVALID_CONTROL_PATH("Attempting to use TMEM allocation PTX without CUTE_ARCH_TCGEN05_TMEM_ENABLED");
85
+ #endif
86
+ }
87
+
88
+ __device__ void
89
+ release_allocation_lock() {
90
+ #if defined(CUTE_ARCH_TCGEN05_TMEM_ENABLED)
91
+ asm volatile("tcgen05.relinquish_alloc_permit.cta_group::1.sync.aligned;" ::);
92
+ #else
93
+ CUTE_INVALID_CONTROL_PATH("Attempting to use TMEM allocation PTX without CUTE_ARCH_TCGEN05_TMEM_ENABLED");
94
+ #endif
95
+ }
96
+ };
97
+
98
+ ///////////////////////////////////////////////////////////////////////////////
99
+ ///////////////////////////////////////////////////////////////////////////////
100
+ ///////////////////////////////////////////////////////////////////////////////
101
+
102
+ class Allocator2Sm {
103
+ public:
104
+ static constexpr int ColumnsPerAllocationSlice = 32;
105
+ static constexpr int Sm100TmemCapacityColumns = 512;
106
+
107
+ __device__ Allocator2Sm() { }
108
+
109
+ /**
110
+ * Performs a non-blocking allocation of TMEM.
111
+ * @param num_columns Number of columns being freed. Must be 32 <= num_columns <= 512 and power of 2.
112
+ * @param dst_ptr Pointer to shared memory to which to write the result tmem pointer to.
113
+ * Both CTAs _must_ provide the exact same dst_ptr for correctness.
114
+ * @pre Must be issued by a single fully active warp of the CTA.
115
+ * @pre Must never be issued by more than one warp at the same time.
116
+ * @pre For repeated allocations, the same warp must be used to issue all allocations.
117
+ * @pre The 2 warps from participating CTAs have the same logical warp ID.
118
+ **/
119
+ CUTE_HOST_DEVICE void
120
+ allocate(int num_columns, uint32_t* dst_ptr) {
121
+ #if defined(CUTE_ARCH_TCGEN05_TMEM_ENABLED)
122
+ uint32_t dst_intptr = cute::cast_smem_ptr_to_uint(dst_ptr);
123
+ asm volatile(
124
+ "tcgen05.alloc.cta_group::2.sync.aligned.shared::cta.b32 [%0], %1;"
125
+ :
126
+ : "r"(dst_intptr), "r"(num_columns));
127
+ #else
128
+ CUTE_INVALID_CONTROL_PATH("Attempting to use TMEM allocation PTX without CUTE_ARCH_TCGEN05_TMEM_ENABLED");
129
+ #endif
130
+ }
131
+
132
+ /**
133
+ * Frees the TMEM corresponding to the pointer and slice count provided.
134
+ * Release the TMEM after checking that the CTA issuing the free does indeed own the corresponding slices.
135
+ * @param tmem_ptr Base address of the TMEM address space being freed.
136
+ * @param num_columns Number of columns being freed. Must be 32 <= num_columns <= 512 and power of 2.
137
+ * @pre Must be issued by a single fully active warp of the CTA.
138
+ * @pre Must never be issued by more than one warp at the same time.
139
+ * @pre The 2 warps from participating CTAs have the same logical warp ID.
140
+ * @returns true
141
+ **/
142
+ __device__
143
+ void
144
+ free(uint32_t tmem_ptr, int num_columns) {
145
+ #if defined(CUTE_ARCH_TCGEN05_TMEM_ENABLED)
146
+ asm volatile(
147
+ "{\n\t"
148
+ "tcgen05.dealloc.cta_group::2.sync.aligned.b32 %0, %1; \n\t"
149
+ "}"
150
+ :
151
+ : "r"(tmem_ptr), "r"(num_columns));
152
+ #else
153
+ CUTE_INVALID_CONTROL_PATH("Attempting to use TMEM allocation PTX without CUTE_ARCH_TCGEN05_TMEM_ENABLED");
154
+ #endif
155
+ }
156
+
157
+ __device__
158
+ void
159
+ release_allocation_lock() {
160
+ #if defined(CUTE_ARCH_TCGEN05_TMEM_ENABLED)
161
+ asm volatile("tcgen05.relinquish_alloc_permit.cta_group::2.sync.aligned;" ::);
162
+ #else
163
+ CUTE_INVALID_CONTROL_PATH("Attempting to use TMEM allocation PTX without CUTE_ARCH_TCGEN05_TMEM_ENABLED");
164
+ #endif
165
+ }
166
+ };
167
+
168
+ } // namespace cute::TMEM
lib/python3.12/site-packages/deep_gemm/include/cute/arch/util.hpp ADDED
@@ -0,0 +1,320 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp>
34
+ #include <cute/numeric/integer_sequence.hpp>
35
+
36
+ #if defined(__clang__) && defined(__CUDA__)
37
+ // __cvta_generic_to_shared was added in Clang 14: https://reviews.llvm.org/D111665
38
+ #if __clang_major__ >= 14
39
+ #define CUTE_CLANG_SUPPORTS_CVTA_GENERIC_TO_SHARED 1
40
+ #endif
41
+
42
+ // __nvvm_get_smem_pointer added in Clang 14: https://reviews.llvm.org/D111665
43
+ // ... but will not work on Windows until Clang 15: https://reviews.llvm.org/D122897
44
+ #if (!defined(_WIN32) && __clang_major__ >= 14) || __clang_major__ >= 15
45
+ #define CUTE_CLANG_SUPPORTS_NVVM_GET_SMEM_POINTER 1
46
+ #endif
47
+ #endif
48
+
49
+ #if defined(__NVCC__) || defined(__CUDACC_RTC__)
50
+ // __cvta_generic_to_shared added in CUDA 11+
51
+ #if __CUDACC_VER_MAJOR__ >= 11
52
+ #define CUTE_NVCC_SUPPORTS_CVTA_GENERIC_TO_SHARED 1
53
+ #endif
54
+
55
+ // __nvvm_get_smem_pointer added in CUDA 10.2
56
+ #if __CUDACC_VER_MAJOR__ == 10 && __CUDACC_VER_MINOR__ >= 2
57
+ #define CUTE_NVCC_SUPPORTS_NVVM_GET_SMEM_POINTER 1
58
+ #endif
59
+ #endif
60
+
61
+ #if CUTE_NVCC_SUPPORTS_CVTA_GENERIC_TO_SHARED || CUTE_CLANG_SUPPORTS_CVTA_GENERIC_TO_SHARED
62
+ #define CUTE_CVTA_GENERIC_TO_SHARED_SUPPORTED 1
63
+ #endif
64
+
65
+ #if !defined(CUTE_CVTA_GENERIC_TO_SHARED_ACTIVATED) && CUTE_CVTA_GENERIC_TO_SHARED_SUPPORTED && defined(__CUDA_ARCH__)
66
+ #define CUTE_CVTA_GENERIC_TO_SHARED_ACTIVATED 1
67
+ #endif
68
+
69
+ #if CUTE_NVCC_SUPPORTS_NVVM_GET_SMEM_POINTER || CUTE_CLANG_SUPPORTS_NVVM_GET_SMEM_POINTER
70
+ #define CUTE_NVVM_GET_SMEM_POINTER_SUPPORTED 1
71
+ #endif
72
+
73
+ #if !defined(CUTE_NVVM_GET_SMEM_POINTER_ACTIVATED) && CUTE_NVVM_GET_SMEM_POINTER_SUPPORTED && defined(__CUDA_ARCH__)
74
+ #define CUTE_NVVM_GET_SMEM_POINTER_ACTIVATED 1
75
+ #endif
76
+
77
+ // Clang 14+ provides a declaration of __nvvm_get_smem_pointer, so we only need
78
+ // to provide one for NVCC
79
+ #if CUTE_NVCC_SUPPORTS_NVVM_GET_SMEM_POINTER
80
+ extern "C" {
81
+ // This NVVM intrinsic is subject to change in future versions of CUDA.
82
+ // Clients should not call it directly.
83
+ CUTE_DEVICE uint32_t __nvvm_get_smem_pointer(void*);
84
+ }
85
+ #endif
86
+
87
+ namespace cute
88
+ {
89
+
90
+ /// CUTE helper to cast SMEM pointer to unsigned
91
+ CUTE_HOST_DEVICE
92
+ uint32_t
93
+ cast_smem_ptr_to_uint(void const* const ptr)
94
+ {
95
+ // We prefer to use the new CVTA intrinsics if they are available, otherwise we will fall back to
96
+ // the previous internal intrinsics if they are available.
97
+ #if CUTE_CVTA_GENERIC_TO_SHARED_ACTIVATED
98
+ //
99
+ // This NVVM intrinsic converts an address in shared memory to a plain
100
+ // unsigned integer. This is necessary to pass to shared memory instructions
101
+ // in inline PTX.
102
+ //
103
+ // In CUDA 11 and beyond, this replaces __nvvm_get_smem_pointer() [only available in 10.2].
104
+ //
105
+ //__device__ size_t __cvta_generic_to_shared(void* ptr);
106
+
107
+ /// CUTE helper to get SMEM pointer
108
+ return static_cast<uint32_t>(__cvta_generic_to_shared(ptr));
109
+
110
+ #elif CUTE_NVVM_GET_SMEM_POINTER_ACTIVATED
111
+
112
+ return __nvvm_get_smem_pointer(ptr);
113
+
114
+ #elif defined(__CUDA_ARCH__)
115
+
116
+ uint32_t smem_ptr;
117
+
118
+ asm(
119
+ "{ .reg .u64 smem_ptr; cvta.to.shared.u64 smem_ptr, %1; cvt.u32.u64 %0, smem_ptr; }\n"
120
+ : "=r"(smem_ptr) : "l"(ptr));
121
+
122
+ return smem_ptr;
123
+
124
+ #else
125
+
126
+
127
+ (void) ptr;
128
+ printf("ERROR: cast_smem_ptr_to_uint not supported but used.\n");
129
+ return 0;
130
+
131
+ #endif
132
+ }
133
+
134
+ namespace detail {
135
+
136
+ //
137
+ // Wrapper for MMAOp::fma
138
+ //
139
+
140
+ template <class MmaOp>
141
+ struct CallFMA {
142
+ template <class... Args>
143
+ CUTE_HOST_DEVICE constexpr void
144
+ operator()(Args&&... args) const {
145
+ return MmaOp::fma(static_cast<Args&&>(args)...);
146
+ }
147
+ };
148
+
149
+ //
150
+ // Wrapper for CopyOp::copy
151
+ //
152
+
153
+ template <class CopyOp>
154
+ struct CallCOPY {
155
+ template <class... Args>
156
+ CUTE_HOST_DEVICE constexpr void
157
+ operator()(Args&&... args) const {
158
+ return CopyOp::copy(static_cast<Args&&>(args)...);
159
+ }
160
+ };
161
+
162
+ //
163
+ // Utility for exploding pointers/arrays/tensors into functions
164
+ //
165
+
166
+ template <class Fn,
167
+ class PtrA, int... I>
168
+ CUTE_HOST_DEVICE constexpr
169
+ void
170
+ explode(Fn fn,
171
+ PtrA&& a, int_sequence<I...>)
172
+ {
173
+ return fn(a[I]...);
174
+ }
175
+
176
+ template <class Fn,
177
+ class PtrS, int... Is,
178
+ class PtrD, int... Id>
179
+ CUTE_HOST_DEVICE constexpr
180
+ void
181
+ explode(Fn fn,
182
+ PtrS&& s, int_sequence<Is...>,
183
+ PtrD&& d, int_sequence<Id...>)
184
+ {
185
+ return fn(s[Is]..., d[Id]...);
186
+ }
187
+
188
+ template <class Fn,
189
+ class PtrA, int... Ia,
190
+ class PtrB, int... Ib,
191
+ class PtrC, int... Ic>
192
+ CUTE_HOST_DEVICE constexpr
193
+ void
194
+ explode(Fn fn,
195
+ PtrA&& a, int_sequence<Ia...>,
196
+ PtrB&& b, int_sequence<Ib...>,
197
+ PtrC&& c, int_sequence<Ic...>)
198
+ {
199
+ return fn(a[Ia]..., b[Ib]..., c[Ic]...);
200
+ }
201
+
202
+ template <class Fn,
203
+ class PtrD, int... Id,
204
+ class PtrA, int... Ia,
205
+ class PtrB, int... Ib,
206
+ class PtrC, int... Ic>
207
+ CUTE_HOST_DEVICE constexpr
208
+ void
209
+ explode(Fn fn,
210
+ PtrD&& d, int_sequence<Id...>,
211
+ PtrA&& a, int_sequence<Ia...>,
212
+ PtrB&& b, int_sequence<Ib...>,
213
+ PtrC&& c, int_sequence<Ic...>)
214
+ {
215
+ return fn(d[Id]..., a[Ia]..., b[Ib]..., c[Ic]...);
216
+ }
217
+
218
+ template <class Fn,
219
+ class PtrD, int... Id,
220
+ class PtrA, int... Ia,
221
+ class PtrB, int... Ib,
222
+ class PtrC, int... Ic,
223
+ class PtrE, int... Ie>
224
+ CUTE_HOST_DEVICE constexpr
225
+ void
226
+ explode(Fn fn,
227
+ PtrD&& d, int_sequence<Id...>,
228
+ PtrA&& a, int_sequence<Ia...>,
229
+ PtrB&& b, int_sequence<Ib...>,
230
+ PtrC&& c, int_sequence<Ic...>,
231
+ PtrE&& e, int_sequence<Ie...>)
232
+ {
233
+ return fn(d[Id]..., a[Ia]..., b[Ib]..., c[Ic]..., e[Ie]...);
234
+ }
235
+
236
+ template <class Fn,
237
+ class PtrD, int... Id,
238
+ class PtrA, int... Ia,
239
+ class PtrB, int... Ib,
240
+ class PtrC, int... Ic,
241
+ class PtrE, int... Ie,
242
+ class PtrF, int... If>
243
+ CUTE_HOST_DEVICE constexpr
244
+ void
245
+ explode(Fn fn,
246
+ PtrD&& d, int_sequence<Id...>,
247
+ PtrA&& a, int_sequence<Ia...>,
248
+ PtrB&& b, int_sequence<Ib...>,
249
+ PtrC&& c, int_sequence<Ic...>,
250
+ PtrE&& e, int_sequence<Ie...>,
251
+ PtrF&& f, int_sequence<If...>)
252
+ {
253
+ return fn(d[Id]..., a[Ia]..., b[Ib]..., c[Ic]..., e[Ie]..., f[If]...);
254
+ }
255
+
256
+ template <class Fn,
257
+ class PtrD, int... Id,
258
+ class PtrA, int... Ia,
259
+ class PtrB, int... Ib,
260
+ class PtrC, int... Ic,
261
+ class PtrE, int... Ie,
262
+ class PtrF, int... If,
263
+ class PtrG, int... Ig>
264
+ CUTE_HOST_DEVICE constexpr
265
+ void
266
+ explode(Fn fn,
267
+ PtrD&& d, int_sequence<Id...>,
268
+ PtrA&& a, int_sequence<Ia...>,
269
+ PtrB&& b, int_sequence<Ib...>,
270
+ PtrC&& c, int_sequence<Ic...>,
271
+ PtrE&& e, int_sequence<Ie...>,
272
+ PtrF&& f, int_sequence<If...>,
273
+ PtrG&& g, int_sequence<Ig...>)
274
+ {
275
+ return fn(d[Id]..., a[Ia]..., b[Ib]..., c[Ic]..., e[Ie]..., f[If]..., g[Ig]...);
276
+ }
277
+
278
+ //
279
+ // Utility for exploding tuples into functions
280
+ //
281
+
282
+ template <class Fn,
283
+ class TupleA, int... I>
284
+ CUTE_HOST_DEVICE constexpr
285
+ void
286
+ explode_tuple(Fn fn,
287
+ TupleA&& a, int_sequence<I...>)
288
+ {
289
+ return fn(get<I>(a)...);
290
+ }
291
+
292
+ template <class Fn,
293
+ class TupleA, int... Ia,
294
+ class TupleB, int... Ib>
295
+ CUTE_HOST_DEVICE constexpr
296
+ void
297
+ explode_tuple(Fn fn,
298
+ TupleA&& a, int_sequence<Ia...>,
299
+ TupleB&& b, int_sequence<Ib...>)
300
+ {
301
+ return fn(get<Ia>(a)..., get<Ib>(b)...);
302
+ }
303
+
304
+ template <class Fn,
305
+ class TupleA, int... Ia,
306
+ class TupleB, int... Ib,
307
+ class TupleC, int... Ic>
308
+ CUTE_HOST_DEVICE constexpr
309
+ void
310
+ explode_tuple(Fn fn,
311
+ TupleA&& a, int_sequence<Ia...>,
312
+ TupleB&& b, int_sequence<Ib...>,
313
+ TupleC&& c, int_sequence<Ic...>)
314
+ {
315
+ return fn(get<Ia>(a)..., get<Ib>(b)..., get<Ic>(c)...);
316
+ }
317
+
318
+ } // end namespace detail
319
+
320
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/atom/copy_atom.hpp ADDED
@@ -0,0 +1,765 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/config.hpp> // CUTE_HOST_DEVICE
34
+ #include <cute/tensor_impl.hpp> // cute::Tensor
35
+ #include <cute/util/type_traits.hpp> // cute::__CUTE_REQUIRES
36
+ #include <cute/container/tuple.hpp> // cute::is_tuple
37
+ #include <cute/numeric/integral_constant.hpp> // cute::is_constant, cute::is_integral
38
+ #include <cute/atom/copy_traits.hpp> // cute::Copy_Traits
39
+ #include <cute/atom/mma_atom.hpp> // cute::TiledMMA
40
+
41
+ namespace cute
42
+ {
43
+
44
+ template <class... Args>
45
+ struct Copy_Atom;
46
+
47
+ template <class CopyOperation, class CopyInternalType>
48
+ struct Copy_Atom<CopyOperation, CopyInternalType> : Copy_Atom<Copy_Traits<CopyOperation>, CopyInternalType>
49
+ {};
50
+
51
+ template <class... Args, class CopyInternalType>
52
+ struct Copy_Atom<Copy_Traits<Args...>, CopyInternalType>
53
+ : Copy_Traits<Args...>
54
+ {
55
+ using Traits = Copy_Traits<Args...>;
56
+
57
+ // Bit and Thr layouts from the Copy_Traits
58
+ using ThrID = typename Traits::ThrID;
59
+ using BitLayoutSrc = typename Traits::SrcLayout;
60
+ using BitLayoutDst = typename Traits::DstLayout;
61
+ using BitLayoutRef = typename Traits::RefLayout;
62
+
63
+ using ValType = CopyInternalType;
64
+
65
+ using ValLayoutSrc = decltype(recast_layout<uint1_t, ValType>(BitLayoutSrc{}));
66
+ using ValLayoutDst = decltype(recast_layout<uint1_t, ValType>(BitLayoutDst{}));
67
+ using ValLayoutRef = decltype(recast_layout<uint1_t, ValType>(BitLayoutRef{}));
68
+
69
+ CUTE_STATIC_ASSERT_V(size<0>(ValLayoutSrc{}) == size(ThrID{}), "CopyOperation is not valid for Src of ValType.");
70
+ CUTE_STATIC_ASSERT_V(size<0>(ValLayoutDst{}) == size(ThrID{}), "CopyOperation is not valid for Dst of ValType.");
71
+ CUTE_STATIC_ASSERT_V(size<0>(ValLayoutRef{}) == size(ThrID{}), "CopyOperation is not valid for Ref of ValType.");
72
+
73
+ static constexpr int NumValSrc = size<1>(ValLayoutSrc{});
74
+ static constexpr int NumValDst = size<1>(ValLayoutDst{});
75
+
76
+ // Additional Trait parameters/transformations
77
+ template <class... TraitsArgs>
78
+ CUTE_HOST_DEVICE
79
+ auto
80
+ with(TraitsArgs&&... args) const {
81
+ auto traits = Traits::with(static_cast<TraitsArgs&&>(args)...);
82
+ return Copy_Atom<decltype(traits), CopyInternalType>{traits};
83
+ }
84
+
85
+ //
86
+ // Tensor call interfaces
87
+ //
88
+
89
+ // Check and call instruction, or recurse
90
+ template <class SEngine, class SLayout,
91
+ class DEngine, class DLayout>
92
+ CUTE_HOST_DEVICE
93
+ void
94
+ call(Tensor<SEngine,SLayout> const& src,
95
+ Tensor<DEngine,DLayout> & dst) const
96
+ {
97
+ static_assert(SLayout::rank == 1, "Expected rank-1 src tensor");
98
+ static_assert(DLayout::rank == 1, "Expected rank-1 dst tensor");
99
+
100
+ if constexpr (is_constant<NumValSrc, decltype(size(src))>::value ||
101
+ is_constant<NumValDst, decltype(size(dst))>::value) {
102
+ // Dispatch to unpack to execute instruction
103
+ return copy_unpack(static_cast<Traits const&>(*this), src, dst);
104
+ } else if constexpr (is_tuple<decltype(shape(src))>::value &&
105
+ is_tuple<decltype(shape(dst))>::value) {
106
+ // If the size of the src/dst doesn't match the instruction,
107
+ // recurse this rank-1 layout by peeling off the mode
108
+ // ((A,B,C,...)) -> (A,B,C,...)
109
+ return copy(*this, tensor<0>(src), tensor<0>(dst));
110
+ } else {
111
+ static_assert(dependent_false<SEngine>,
112
+ "CopyAtom: Src/Dst partitioning does not match the instruction requirement.");
113
+ }
114
+ }
115
+
116
+ // Accept mutable temporaries
117
+ template <class SEngine, class SLayout,
118
+ class DEngine, class DLayout>
119
+ CUTE_HOST_DEVICE
120
+ void
121
+ call(Tensor<SEngine,SLayout> const& src,
122
+ Tensor<DEngine,DLayout> && dst) const
123
+ {
124
+ return call(src, dst);
125
+ }
126
+ };
127
+
128
+ //
129
+ // A tiling of copy atoms
130
+ //
131
+
132
+ template <class TiledCopy, class ThrIdx>
133
+ struct ThrCopy;
134
+
135
+ template <class Copy_Atom,
136
+ class LayoutCopy_TV, // (tid,vid) -> coord [Need not be 2D...]
137
+ class ShapeTiler_MN> // coord space
138
+ struct TiledCopy : Copy_Atom
139
+ {
140
+ // Layout information from the CopyAtom
141
+ using AtomThrID = typename Copy_Atom::ThrID; // thrid -> thr_idx
142
+ using AtomLayoutSrc = typename Copy_Atom::ValLayoutSrc; // (thr,val) -> offset
143
+ using AtomLayoutDst = typename Copy_Atom::ValLayoutDst; // (thr,val) -> offset
144
+ using AtomLayoutRef = typename Copy_Atom::ValLayoutRef; // (thr,val) -> offset
145
+
146
+ using AtomNumThr = decltype(size<0>(AtomLayoutRef{}));
147
+ using AtomNumVal = decltype(size<1>(AtomLayoutRef{}));
148
+
149
+ // Layout information for the TiledCopy
150
+ using Tiler_MN = ShapeTiler_MN;
151
+ using TiledLayout_TV = LayoutCopy_TV;
152
+ using TiledNumThr = decltype(size<0>(TiledLayout_TV{}));
153
+ using TiledNumVal = decltype(size<1>(TiledLayout_TV{}));
154
+
155
+ CUTE_STATIC_ASSERT_V(TiledNumThr{} % AtomNumThr{} == Int<0>{}, "TiledCopy uses too few thrs for selected CopyAtom");
156
+ CUTE_STATIC_ASSERT_V(TiledNumVal{} % AtomNumVal{} == Int<0>{}, "TiledCopy uses too few vals for selected CopyAtom");
157
+
158
+ // Tile a tensor or a layout from shape
159
+ // (M,N,...)
160
+ // to shape
161
+ // ((ThrV,ThrX),FrgV,(RestM,RestN,...))
162
+ // where
163
+ // ThrV: The threads local to a COPY_ATOM Src.
164
+ // ThrX: The threads tiled across COPY_ATOMs Src.
165
+ // FrgV: The values local to a COPY_ATOM Src.
166
+ // RestM: The values tiled in M.
167
+ // RestN: The values tiled in N.
168
+ template <class STensor>
169
+ CUTE_HOST_DEVICE constexpr static
170
+ auto
171
+ tidfrg_S(STensor&& stensor)
172
+ {
173
+ CUTE_STATIC_ASSERT_V(rank(stensor) >= rank(Tiler_MN{}), "Rank of tensor to be partitioned too small.");
174
+
175
+ // Tile the stensor and compute the (src-thr, src-val) -> (ref-thr, ref-val) layout
176
+ return tile2thrfrg(zipped_divide(stensor,Tiler_MN{}), right_inverse(AtomLayoutRef{}).compose(AtomLayoutSrc{}));
177
+ }
178
+
179
+ // Tile a tensor or a layout from shape
180
+ // (M,N,...)
181
+ // to shape
182
+ // ((ThrV,ThrX),FrgV,(RestM,RestN,...))
183
+ // where
184
+ // ThrV: The threads local to a COPY_ATOM Dst.
185
+ // ThrX: The threads tiled across COPY_ATOMs Dst.
186
+ // FrgV: The values local to a COPY_ATOM Dst.
187
+ // RestM: The values tiled in M.
188
+ // RestN: The values tiled in N.
189
+ template <class DTensor>
190
+ CUTE_HOST_DEVICE constexpr static
191
+ auto
192
+ tidfrg_D(DTensor&& dtensor)
193
+ {
194
+ CUTE_STATIC_ASSERT_V(rank(dtensor) >= rank(Tiler_MN{}), "Rank of tensor to be partitioned too small.");
195
+
196
+ // Tile the dtensor and compute the (dst-thr, dst-val) -> (ref-thr, ref-val) layout
197
+ return tile2thrfrg(zipped_divide(dtensor,Tiler_MN{}), right_inverse(AtomLayoutRef{}).compose(AtomLayoutDst{}));
198
+ }
199
+
200
+ // Tile a tensor or a layout from shape
201
+ // ((TileM,TileN,...), (RestM,RestN,...))
202
+ // to shape
203
+ // ((ThrV,ThrX),FrgV,(RestM,RestN,...))
204
+ template <class Tensor, class Ref2TrgLayout>
205
+ CUTE_HOST_DEVICE constexpr static
206
+ auto
207
+ tile2thrfrg(Tensor&& tensor, Ref2TrgLayout const& ref2trg)
208
+ {
209
+ // Take the thrs/vals that the atom is interested in
210
+ // NOTE: Assumes the AtomNumThr are contiguous and identity within TiledThrID
211
+ auto atom_layout_TV = zipped_divide(TiledLayout_TV{}, make_shape(AtomNumThr{}, AtomNumVal{}));
212
+ // ((atom_tid,atom_val),(rest_tid,rest_val)) -> (m,n)
213
+
214
+ // Transform to the trg layout
215
+ auto trg_layout_TV = atom_layout_TV.compose(ref2trg, _);
216
+ // ((trg_tid,trg_val),(rest_tid,rest_val)) -> (m,n)
217
+
218
+ // Transform the thrs mode from thrid to thr_idx
219
+ // NOTE: Assumes the AtomNumThr are contiguous and identity within TiledThrID
220
+ auto thrval2mn = coalesce(zip(trg_layout_TV), Shape<_1,Shape<_1,_1>>{});
221
+ // ((trg_tid,rest_tid),(trg_val,rest_val)) -> (m,n)
222
+
223
+ /// ==================
224
+
225
+ // Transform the tile mode
226
+ auto tv_tensor = tensor.compose(thrval2mn, _);
227
+ // ((thrid,val),(RestM,RestN,...))
228
+
229
+ // Unfold and return
230
+ return tv_tensor(make_coord(_,_), _);
231
+ }
232
+
233
+ // retile_S and retile_D assume they are working with the reference layout -- they are the same
234
+ template <class Tensor>
235
+ CUTE_HOST_DEVICE constexpr static
236
+ auto
237
+ retile(Tensor&& tensor)
238
+ {
239
+ constexpr int R = remove_cvref_t<Tensor>::rank;
240
+ // Assert that AtomLayoutSrc|Dst is identity so we can skip the Ref transformation
241
+
242
+ // Assume the first size<0>(tensor) elements are the first val_ids in TiledLayout_TV.
243
+ // Then, we only need the shape+layout of those size<0>(tensor) elements in TiledLayout_TV
244
+ // and that shape is what we gather from the other modes of tensor
245
+
246
+ auto V = size<0>(tensor);
247
+
248
+ auto frg_layout_mn = upcast<TiledNumThr{} * V>(right_inverse(TiledLayout_TV{}).with_shape(shape(Tiler_MN{})));
249
+ // (m,n) -> v_idx -- The shape and order of the V inside of TiledLayout_TV
250
+
251
+ auto frg_layout_v = zipped_divide(logical_product(make_layout(V), right_inverse(frg_layout_mn)), make_layout(AtomNumVal{}));
252
+ // (atom_vals,rest_vals) -> (v,m,n)
253
+
254
+ /// =======
255
+
256
+ // Tile the tensor for TileFrg
257
+ auto t_tensor = zipped_divide(tensor, prepend(product_each(shape(frg_layout_mn)), V));
258
+ // ((TileV,TileM,TileN,...),(1,RestM,RestN,...))
259
+
260
+ // Transform the tile mode
261
+ auto v_tensor = t_tensor.compose(frg_layout_v, _);
262
+ // ((atom_vals,rest_vals),(1,RM,RN,...))
263
+
264
+ // Unfold and return
265
+ return v_tensor(_, append<R>(Int<0>{},_));
266
+ }
267
+
268
+ CUTE_HOST_DEVICE constexpr static
269
+ auto
270
+ get_layoutS_TV()
271
+ {
272
+ // (M,N) -> (M,N)
273
+ auto ref_S = make_layout(make_shape(shape(Tiler_MN{}), Int<1>{}));
274
+ // (thr_idx,val_idx) -> (M,N)
275
+ return tile2thrfrg(ref_S, right_inverse(AtomLayoutRef{}).compose(AtomLayoutSrc{}))(_,_,Int<0>{});
276
+ }
277
+
278
+ CUTE_HOST_DEVICE constexpr static
279
+ auto
280
+ get_layoutS_MN()
281
+ {
282
+ // (thr_idx,val_idx) -> (M,N)
283
+ auto layoutS_TV = get_layoutS_TV();
284
+ // (M,K) -> (thr_idx,val_idx)
285
+ auto layoutS_MK = right_inverse(layoutS_TV).with_shape(shape(Tiler_MN{}));
286
+
287
+ // athrid = (v,m,k) -> thr_idx
288
+ auto thrID_S = make_layout(size<0>(TiledLayout_TV{}));
289
+
290
+ return cute::make_tuple(layoutS_MK, thrID_S);
291
+ }
292
+
293
+ CUTE_HOST_DEVICE constexpr static
294
+ auto
295
+ get_layoutD_TV()
296
+ {
297
+ // (M,N) -> (M,N)
298
+ auto ref_D = make_layout(make_shape(shape(Tiler_MN{}), Int<1>{}));
299
+ // (thr_idx,val_idx) -> (M,N)
300
+ return tile2thrfrg(ref_D, right_inverse(AtomLayoutRef{}).compose(AtomLayoutDst{}))(_,_,Int<0>{});
301
+ }
302
+
303
+ CUTE_HOST_DEVICE constexpr static
304
+ auto
305
+ get_layoutD_MN()
306
+ {
307
+ // (thr_idx,val_idx) -> (M,N)
308
+ auto layoutD_TV = get_layoutD_TV();
309
+ // (M,K) -> (thr_idx,val_idx)
310
+ auto layoutD_MK = right_inverse(layoutD_TV).with_shape(shape(Tiler_MN{}));
311
+
312
+ // athrid = (v,m,k) -> thr_idx
313
+ auto thrID_D = make_layout(size<0>(TiledLayout_TV{}));
314
+
315
+ return cute::make_tuple(layoutD_MK, thrID_D);
316
+ }
317
+
318
+ template <class ThrIdx,
319
+ __CUTE_REQUIRES(is_integral<ThrIdx>::value)>
320
+ CUTE_HOST_DEVICE static
321
+ auto
322
+ get_slice(ThrIdx const& thr_idx)
323
+ {
324
+ return ThrCopy<TiledCopy, ThrIdx>(thr_idx);
325
+ }
326
+
327
+ template <class ThrIdx,
328
+ __CUTE_REQUIRES(is_integral<ThrIdx>::value)>
329
+ CUTE_HOST_DEVICE static
330
+ auto
331
+ get_thread_slice(ThrIdx const& thr_idx)
332
+ {
333
+ return get_slice(thr_idx);
334
+ }
335
+ };
336
+
337
+ template <class TiledCopy, class ThrIdx>
338
+ struct ThrCopy
339
+ {
340
+ ThrIdx thr_idx_;
341
+
342
+ CUTE_HOST_DEVICE
343
+ ThrCopy(ThrIdx const& thr_idx) : thr_idx_(thr_idx) {}
344
+
345
+ template <class STensor>
346
+ CUTE_HOST_DEVICE
347
+ auto
348
+ partition_S(STensor&& stensor) const {
349
+ //static_assert(sizeof(typename remove_cvref_t<STensor>::value_type) == sizeof(typename TiledCopy::ValType),
350
+ // "Expected ValType for tiling SrcTensor.");
351
+ auto thr_tensor = make_tensor(static_cast<STensor&&>(stensor).data(), TiledCopy::tidfrg_S(stensor.layout()));
352
+ return thr_tensor(thr_idx_, _, repeat<rank_v<STensor>>(_));
353
+ }
354
+
355
+ template <class DTensor>
356
+ CUTE_HOST_DEVICE
357
+ auto
358
+ partition_D(DTensor&& dtensor) const {
359
+ //static_assert(sizeof(typename remove_cvref_t<DTensor>::value_type) == sizeof(typename TiledCopy::ValType),
360
+ // "Expected ValType for tiling DstTensor.");
361
+ auto thr_tensor = make_tensor(static_cast<DTensor&&>(dtensor).data(), TiledCopy::tidfrg_D(dtensor.layout()));
362
+ return thr_tensor(thr_idx_, _, repeat<rank_v<DTensor>>(_));
363
+ }
364
+
365
+ template <class STensor>
366
+ CUTE_HOST_DEVICE static
367
+ auto
368
+ retile_S(STensor&& stensor) {
369
+ // static_assert(sizeof(typename remove_cvref_t<STensor>::value_type) == sizeof(typename TiledCopy::ValType),
370
+ // "Expected ValType for tiling SrcTensor.");
371
+ return make_tensor(static_cast<STensor&&>(stensor).data(), TiledCopy::retile(stensor.layout()));
372
+ }
373
+
374
+ template <class DTensor>
375
+ CUTE_HOST_DEVICE static
376
+ auto
377
+ retile_D(DTensor&& dtensor) {
378
+ // static_assert(sizeof(typename remove_cvref_t<DTensor>::value_type) == sizeof(typename TiledCopy::ValType),
379
+ // "Expected ValType for tiling DstTensor.");
380
+ return make_tensor(static_cast<DTensor&&>(dtensor).data(), TiledCopy::retile(dtensor.layout()));
381
+ }
382
+ };
383
+
384
+
385
+ template <class... Args,
386
+ class LayoutCopy_TV,
387
+ class Tiler>
388
+ CUTE_HOST_DEVICE
389
+ auto
390
+ make_tiled_copy_impl(Copy_Atom<Args...> const& atom,
391
+ LayoutCopy_TV const&,
392
+ Tiler const&)
393
+ {
394
+ return TiledCopy<Copy_Atom<Args...>, LayoutCopy_TV, Tiler>{atom};
395
+ }
396
+
397
+ //
398
+ // These tile the Copy_Atom as a whole
399
+ //
400
+
401
+ template <class... CArgs, class... MArgs>
402
+ CUTE_HOST_DEVICE
403
+ auto
404
+ make_tiled_copy_A(Copy_Atom<CArgs...> const& copy_atom,
405
+ TiledMMA<MArgs...> const& mma)
406
+ {
407
+ return make_tiled_copy_impl(copy_atom, mma.get_layoutA_TV(), make_shape(tile_size<0>(mma),tile_size<2>(mma)));
408
+ }
409
+
410
+ template <class... CArgs, class... MArgs>
411
+ CUTE_HOST_DEVICE
412
+ auto
413
+ make_tiled_copy_B(Copy_Atom<CArgs...> const& copy_atom,
414
+ TiledMMA<MArgs...> const& mma)
415
+ {
416
+ return make_tiled_copy_impl(copy_atom, mma.get_layoutB_TV(), make_shape(tile_size<1>(mma),tile_size<2>(mma)));
417
+ }
418
+
419
+ template <class... CArgs, class... MArgs>
420
+ CUTE_HOST_DEVICE
421
+ auto
422
+ make_tiled_copy_C(Copy_Atom<CArgs...> const& copy_atom,
423
+ TiledMMA<MArgs...> const& mma)
424
+ {
425
+ return make_tiled_copy_impl(copy_atom, mma.get_layoutC_TV(), make_shape(tile_size<0>(mma),tile_size<1>(mma)));
426
+ }
427
+
428
+ // returns the smallest tiled copy that can retile LayoutC_TV
429
+ // for use with pipelined epilogues with subtiled stores
430
+ template <class... CArgs, class... MArgs>
431
+ CUTE_HOST_DEVICE
432
+ auto
433
+ make_tiled_copy_C_atom(Copy_Atom<CArgs...> const& copy_atom,
434
+ TiledMMA<MArgs...> const& mma)
435
+ {
436
+ // Truncate the V-layout to just the Copy_Atom, keep the V-order
437
+ auto layoutC_TV = mma.get_layoutC_TV();
438
+ auto copy_V = Int<Copy_Atom<CArgs...>::NumValSrc>{};
439
+ CUTE_STATIC_ASSERT_V(copy_V <= size<1>(layoutC_TV));
440
+ auto layout_TV = composition(layoutC_TV, make_layout(make_shape(size<0>(layoutC_TV), copy_V)));
441
+
442
+ // Recompute tiler and restride the TV layout for the new tiler
443
+
444
+ // Tiler -- Find the active elements in the MMA tensor and generate a tiler to extract them
445
+ // Convert to the awkward by-mode tiler to preserve the modes of the tiled MMA
446
+ auto mma_tiler = make_shape(tile_size<0>(mma),tile_size<1>(mma));
447
+ auto mma_zeros = repeat_like(mma_tiler, Int<0>{});
448
+
449
+ auto tiler = transform(make_seq<rank(mma_tiler)>{}, [&](auto i) {
450
+ return filter(composition(make_layout(mma_tiler, replace<i>(mma_zeros, Int<1>{})), layout_TV));
451
+ });
452
+
453
+ // Layout_TV -- Find the (tid,vid) -> tile coord transformation
454
+ // Apply the tiler to a reference and transform the codomain
455
+ // tile_coord -> mma_coord
456
+ auto tile2mma = composition(make_layout(mma_tiler), tiler);
457
+
458
+ // (tid,vid) -> tile_coord
459
+ auto layout_tv = composition(left_inverse(tile2mma), layout_TV);
460
+
461
+ return make_tiled_copy_impl(copy_atom, layout_tv, tiler);
462
+ }
463
+
464
+ /** Produce a TiledCopy from logical thread and values layouts.
465
+ * The thread and value layouts map coordinates to thr_idx and val_idx.
466
+ * The product of these layouts is taken to produce the TV layout and the Tiler.
467
+ * Useful when threads and values need very specific mappings onto coordinates
468
+ * in the target tensors.
469
+ */
470
+ template <class... Args,
471
+ class ThrLayout,
472
+ class ValLayout = Layout<_1>>
473
+ CUTE_HOST_DEVICE
474
+ auto
475
+ make_tiled_copy(Copy_Atom<Args...> const& copy_atom,
476
+ ThrLayout const& thr_layout = {}, // (m,n) -> thr_idx
477
+ ValLayout const& val_layout = {}) // (m,n) -> val_idx
478
+ {
479
+ // Take the raked_products to compute the Layout_MN
480
+ // (M,N) -> (thr_idx, val_idx)
481
+ auto layout_mn = raked_product(thr_layout, val_layout);
482
+ // (thr_idx, val_idx) -> (M,N)
483
+ auto layout_tv = right_inverse(layout_mn).with_shape(make_shape(size(thr_layout), size(val_layout)));
484
+ // Tiler for extracting relevant elements
485
+ // (M,N) -> tensor coord
486
+ auto tiler = product_each(shape(layout_mn));
487
+
488
+ #if 0
489
+ print("thr_layout: "); print(thr_layout); print("\n");
490
+ print("val_layout: "); print(val_layout); print("\n");
491
+ print("layout_mn : "); print(layout_mn); print("\n");
492
+ print("layout_tv : "); print(layout_tv); print("\n");
493
+ print("tiler : "); print(tiler); print("\n");
494
+ #endif
495
+
496
+ return make_tiled_copy_impl(copy_atom, layout_tv, tiler);
497
+ }
498
+
499
+ /** Produce a TiledCopy from thread and value offset maps.
500
+ * The TV Layout maps threads and values to the codomain of the data_layout.
501
+ * It is verified that the intended codomain is valid within data_layout.
502
+ * Useful when threads and values don't care about owning specific coordinates, but
503
+ * care more about the vector-width and offsets between them.
504
+ */
505
+ template <class... Args, class AtomTVLayout, class DataLayout>
506
+ CUTE_HOST_DEVICE constexpr
507
+ auto
508
+ make_cotiled_copy(Copy_Atom<Args...> const& copy_atom,
509
+ AtomTVLayout const& atom_tv_layout, // atom (thr,val) -> data addr
510
+ DataLayout const& data_layout) // coord -> data addr The target layout
511
+ {
512
+ static_assert(is_static<AtomTVLayout>::value);
513
+ static_assert(is_static<DataLayout>::value);
514
+
515
+ // data addr -> data coord Append 1:0 so off-the-ends get the stride-0
516
+ auto inv_data_layout = make_layout(left_inverse(data_layout), Layout<_1,_0>{});
517
+
518
+ // (tid,vid) -> data_coord
519
+ auto layout_tv_data = composition(inv_data_layout, atom_tv_layout);
520
+
521
+ // Check validity
522
+ CUTE_STATIC_ASSERT_V(coalesce(composition(data_layout, layout<1>(layout_tv_data))) == coalesce(layout<1>(atom_tv_layout)),
523
+ "The memory pointed to by AtomTVLayout does not exist in the DataLayout.");
524
+ //
525
+ // Tiler -- Find the active elements in the DATA tensor and generate a tiler to extract them
526
+ //
527
+
528
+ // Convert to the awkward by-mode tiler to preserve the modes of the tiled DATA
529
+ auto flat_data_shape = product_each(shape(data_layout));
530
+ auto flat_data_zeros = repeat<rank(flat_data_shape)>(Int<0>{});
531
+
532
+ auto tiler = transform(make_seq<rank(flat_data_shape)>{}, [&](auto i) {
533
+ return filter(composition(make_layout(flat_data_shape, replace<i>(flat_data_zeros, Int<1>{})), layout_tv_data));
534
+ });
535
+
536
+ //
537
+ // Layout_TV -- Find the (tid,vid) -> tile coord transformation
538
+ //
539
+
540
+ // Apply the tiler to a reference and transform the codomain
541
+ // tile_coord -> data_coord
542
+ auto tile2data = composition(make_layout(flat_data_shape), tiler);
543
+
544
+ // (tid,vid) -> tile_coord
545
+ auto layout_tv = composition(left_inverse(tile2data), layout_tv_data);
546
+ return make_tiled_copy_impl(copy_atom, layout_tv, tiler);
547
+ }
548
+
549
+ // Make a TiledCopy out of the copy_atom that matches the Src-Layout of tiled_copy
550
+ template <class... Args,
551
+ class TiledCopy>
552
+ CUTE_HOST_DEVICE
553
+ auto
554
+ make_tiled_copy_S(Copy_Atom<Args...> const& copy_atom,
555
+ TiledCopy const& tiled_copy)
556
+ {
557
+ return make_tiled_copy_impl(copy_atom, tiled_copy.get_layoutS_TV(), typename TiledCopy::Tiler_MN{});
558
+ }
559
+
560
+ // Make a TiledCopy out of the copy_atom that matches the Dst-Layout of tiled_copy
561
+ template <class... Args,
562
+ class TiledCopy>
563
+ CUTE_HOST_DEVICE
564
+ auto
565
+ make_tiled_copy_D(Copy_Atom<Args...> const& copy_atom,
566
+ TiledCopy const& tiled_copy)
567
+ {
568
+ return make_tiled_copy_impl(copy_atom, tiled_copy.get_layoutD_TV(), typename TiledCopy::Tiler_MN{});
569
+ }
570
+
571
+ //
572
+ // Size
573
+ //
574
+
575
+ // The logical size of a TileCopy
576
+ template <int... I, class... Args>
577
+ CUTE_HOST_DEVICE constexpr
578
+ auto
579
+ tile_size(TiledCopy<Args...> const&)
580
+ {
581
+ return size<I...>(typename TiledCopy<Args...>::Tiler_MN{});
582
+ }
583
+
584
+ // The number of threads involved in a TiledCopy
585
+ template <class... Args>
586
+ CUTE_HOST_DEVICE constexpr
587
+ auto
588
+ size(TiledCopy<Args...> const&)
589
+ {
590
+ return typename TiledCopy<Args...>::TiledNumThr{};
591
+ }
592
+
593
+ //
594
+ // Display utilities
595
+ //
596
+
597
+ template <class... Args, class T>
598
+ CUTE_HOST_DEVICE
599
+ void
600
+ print(Copy_Atom<Copy_Traits<Args...>, T> const&)
601
+ {
602
+ using Atom = Copy_Atom<Copy_Traits<Args...>, T>;
603
+ print("Copy_Atom\n");
604
+ print(" ThrID: "); print(typename Atom::ThrID{}); print("\n");
605
+ print(" ValLayoutSrc: "); print(typename Atom::ValLayoutSrc{}); print("\n");
606
+ print(" ValLayoutDst: "); print(typename Atom::ValLayoutDst{}); print("\n");
607
+ print(" ValLayoutRef: "); print(typename Atom::ValLayoutRef{}); print("\n");
608
+ print(" ValueType: "); print(sizeof_bits<typename Atom::ValType>::value); print("b\n");
609
+ }
610
+
611
+ template <class Atom, class... Args>
612
+ CUTE_HOST_DEVICE
613
+ void
614
+ print(TiledCopy<Atom, Args...> const& copy, char const* pad = "")
615
+ {
616
+ using Copy = TiledCopy<Atom, Args...>;
617
+ print("TiledCopy\n");
618
+ print(" Tiler_MN: "); print(typename Copy::Tiler_MN{}); print("\n");
619
+ print(" TiledLayout_TV: "); print(typename Copy::TiledLayout_TV{}); print("\n");
620
+ print(static_cast<Atom const&>(copy));
621
+ }
622
+
623
+ template <class TiledCopy, class ThrIdx>
624
+ CUTE_HOST_DEVICE
625
+ void
626
+ print(ThrCopy<TiledCopy, ThrIdx> const& thr_copy)
627
+ {
628
+ print("ThrCopy\n");
629
+ print(" ThrIdx: "); print(thr_copy.thr_idx_); print("\n");
630
+ print(TiledCopy{});
631
+ }
632
+
633
+ // TiledCopy to LaTeX TikZ
634
+ template <class... Args, class TikzColorFn = TikzColor_TV>
635
+ CUTE_HOST_DEVICE
636
+ auto
637
+ print_latex(TiledCopy<Args...> const& copy,
638
+ TikzColorFn color = {}) // lambda(thr_idx,val_idx) -> tikz color string
639
+ {
640
+ auto [layoutS_MN, thrID_S] = copy.get_layoutS_MN();
641
+ auto [layoutD_MN, thrID_D] = copy.get_layoutD_MN();
642
+
643
+ print_latex_copy(layoutS_MN, thrID_S,
644
+ layoutD_MN, thrID_D);
645
+ }
646
+
647
+ // MNK Copy Layout to LaTeX TikZ
648
+ template <class LayoutS, class ThrIDS,
649
+ class LayoutD, class ThrIDD,
650
+ class TikzColorFn = TikzColor_TV>
651
+ CUTE_HOST_DEVICE
652
+ void
653
+ print_latex_copy(LayoutS const& S, ThrIDS const& TS, // (m,n) -> (tid,vid) and tid -> thr_idx
654
+ LayoutD const& D, ThrIDD const& TD, // (m,n) -> (tid,vid) and tid -> thr_idx
655
+ TikzColorFn color = {}) // lambda(thr_idx,val_idx) -> tikz color string
656
+ {
657
+ CUTE_STATIC_ASSERT_V(rank(S) == Int<2>{});
658
+ CUTE_STATIC_ASSERT_V(rank(D) == Int<2>{});
659
+
660
+ assert(size<0>(S) == size<0>(D));
661
+ assert(size<1>(S) == size<1>(D));
662
+
663
+ // Commented prints
664
+ printf("%% LayoutS: "); print(S); printf("\n");
665
+ printf("%% ThrIDS : "); print(TS); printf("\n");
666
+ printf("%% LayoutD: "); print(D); printf("\n");
667
+ printf("%% ThrIDD : "); print(TD); printf("\n\n");
668
+
669
+ // Header
670
+ printf("\\documentclass[convert]{standalone}\n"
671
+ "\\usepackage{tikz}\n\n"
672
+ "\\begin{document}\n"
673
+ "\\begin{tikzpicture}[x={(0cm,-1cm)},y={(1cm,0cm)},every node/.style={minimum size=1cm, outer sep=0pt}]\n\n");
674
+
675
+ // S starting at 0,0
676
+ for (int i = 0; i < size<0>(S); ++i) {
677
+ for (int j = 0; j < size<1>(S); ++j) {
678
+ int thrid = S(i,j) % size(TS);
679
+ int val_idx = S(i,j) / size(TS);
680
+ int thr_idx = TS(thrid);
681
+
682
+ printf("\\node[fill=%s] at (%d,%d) {\\shortstack{T%d \\\\ V%d}};\n",
683
+ color(thr_idx, val_idx),
684
+ i, j,
685
+ thr_idx, val_idx);
686
+ }
687
+ }
688
+ // Grid
689
+ printf("\\draw[color=black,thick,shift={(-0.5,-0.5)}] (%d,%d) grid (%d,%d);\n\n",
690
+ 0, 0, int(size<0>(S)), int(size<1>(S)));
691
+ // S Labels
692
+ for (int i = 0, j = -1; i < size<0>(S); ++i) {
693
+ printf("\\node at (%d,%d) {\\Large{\\texttt{%d}}};\n", i, j, i);
694
+ }
695
+ for (int i = -1, j = 0; j < size<1>(S); ++j) {
696
+ printf("\\node at (%d,%d) {\\Large{\\texttt{%d}}};\n", i, j, j);
697
+ }
698
+
699
+ // D starting at 0,size<1>(S)+3
700
+ for (int i = 0; i < size<0>(D); ++i) {
701
+ for (int j = 0; j < size<1>(D); ++j) {
702
+ int thrid = D(i,j) % size(TD);
703
+ int val_idx = D(i,j) / size(TD);
704
+ int thr_idx = TD(thrid);
705
+
706
+ printf("\\node[fill=%s] at (%d,%d) {\\shortstack{T%d \\\\ V%d}};\n",
707
+ color(thr_idx, val_idx),
708
+ i, j + size<1>(S) + 3,
709
+ thr_idx, val_idx);
710
+ }
711
+ }
712
+ // Grid
713
+ printf("\\draw[color=black,thick,shift={(-0.5,-0.5)}] (%d,%d) grid (%d,%d);\n\n",
714
+ 0, int(size<1>(S)+3), int(size<0>(D)), int(size<1>(D)+size<1>(S)+3));
715
+ // D Labels
716
+ for (int i = 0, j = size<1>(D); i < size<0>(D); ++i) {
717
+ printf("\\node at (%d,%d) {\\Large{\\texttt{%d}}};\n", i, j + size<1>(S) + 3, i);
718
+ }
719
+ for (int i = -1, j = 0; j < size<1>(D); ++j) {
720
+ printf("\\node at (%d,%d) {\\Large{\\texttt{%d}}};\n", i, j + size<1>(S) + 3, j);
721
+ }
722
+
723
+ // Footer
724
+ printf("\\end{tikzpicture}\n"
725
+ "\\end{document}\n");
726
+ }
727
+
728
+ } // end namespace cute
729
+
730
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
731
+
732
+ #include <cute/atom/copy_traits_sm50.hpp>
733
+ #include <cute/atom/copy_traits_sm75.hpp>
734
+ #include <cute/atom/copy_traits_sm80.hpp>
735
+ #include <cute/atom/copy_traits_sm90.hpp>
736
+ #include <cute/atom/copy_traits_sm100.hpp>
737
+
738
+
739
+ // Config
740
+ #if (__CUDACC_VER_MAJOR__ >= 12)
741
+ # define CUTE_COPY_ATOM_TMA_SM90_ENABLED
742
+ # define CUTE_COPY_ATOM_TMA_SM100_ENABLED
743
+ #endif
744
+
745
+
746
+ #if (!defined(CUTE_COPY_ATOM_TMA_SM90_ENABLED))
747
+ # define CUTE_COPY_ATOM_TMA_SM90_ENABLED
748
+ #endif
749
+
750
+ #if (!defined(CUTE_COPY_ATOM_TMA_SM100_ENABLED))
751
+ # define CUTE_COPY_ATOM_TMA_SM100_ENABLED
752
+ #endif
753
+
754
+
755
+ #if defined(CUTE_COPY_ATOM_TMA_SM90_ENABLED)
756
+ #include <cute/atom/copy_traits_sm90_tma.hpp>
757
+ #endif
758
+
759
+
760
+ #if defined(CUTE_COPY_ATOM_TMA_SM100_ENABLED)
761
+ #include <cute/atom/copy_traits_sm100_tma.hpp>
762
+ #endif
763
+
764
+
765
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
lib/python3.12/site-packages/deep_gemm/include/cute/atom/copy_traits.hpp ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ #include <cute/arch/copy.hpp>
34
+
35
+ #include <cute/tensor_impl.hpp>
36
+
37
+ namespace cute
38
+ {
39
+
40
+ /**
41
+ * concept Copy_Traits
42
+ * {
43
+ * using ThrID = // Logical thread id (tid) -> tidx
44
+ *
45
+ * using SrcLayout = // (Logical src thread id (tid), Logical src value id (vid)) -> bit
46
+ * using DstLayout = // (Logical dst thread id (tid), Logical dst value id (vid)) -> bit
47
+ * using RefLayout = // (Logical ref thread id (tid), Logical ref value id (vid)) -> bit
48
+ * };
49
+ *
50
+ * The abstract bit ordering of the Copy_Traits (the codomain of SrcLayout, DstLayout, and RefLayout)
51
+ * is arbitrary and only used to construct maps
52
+ * (ref-tid,ref-vid) -> (src-tid,src-vid)
53
+ * (ref-tid,ref-vid) -> (dst-tid,dst-vid)
54
+ * in TiledCopy. The Layout_TV in TiledCopy is in accordance with the RefLayout of a Traits, then mapped to
55
+ * the Src or Dst (tid,vid) representation on demand.
56
+ *
57
+ */
58
+
59
+ template <class CopyOperation, class... CopyOpArgs>
60
+ struct Copy_Traits
61
+ {
62
+ static_assert(dependent_false<CopyOperation>, "Copy_Traits not implemented for this CopyOperation.");
63
+ };
64
+
65
+ template <class S, class D>
66
+ struct Copy_Traits<UniversalCopy<S,D>>
67
+ {
68
+ // Logical thread id to thread idx (one-thread)
69
+ using ThrID = Layout<_1>;
70
+
71
+ // Map from (src-thr,src-val) to bit
72
+ using SrcLayout = Layout<Shape<_1,Int<sizeof_bits<S>::value>>>;
73
+ // Map from (dst-thr,dst-val) to bit
74
+ using DstLayout = Layout<Shape<_1,Int<sizeof_bits<D>::value>>>;
75
+
76
+ // Reference map from (thr,val) to bit
77
+ using RefLayout = SrcLayout;
78
+ };
79
+
80
+ template <int MaxVecBits>
81
+ struct Copy_Traits<AutoVectorizingCopyWithAssumedAlignment<MaxVecBits>>
82
+ {
83
+ // Logical thread id to thread idx (one-thread)
84
+ using ThrID = Layout<_1>;
85
+
86
+ // Map from (src-thr,src-val) to bit
87
+ using SrcLayout = Layout<Shape<_1,_1>, Stride<_0,_0>>;
88
+ // Map from (dst-thr,dst-val) to bit
89
+ using DstLayout = Layout<Shape<_1,_1>, Stride<_0,_0>>;
90
+
91
+ // Reference map from (thr,val) to bit
92
+ using RefLayout = SrcLayout;
93
+ };
94
+
95
+ // Extract a CPY_Op from a CPY_Traits
96
+ template <class CPY_Traits>
97
+ struct CPY_Op {};
98
+
99
+ template <class CPY_Op_Arg, class... Args>
100
+ struct CPY_Op<Copy_Traits<CPY_Op_Arg, Args...>> {
101
+ using type = CPY_Op_Arg;
102
+ };
103
+
104
+ //
105
+ // Generic copy_unpack for common argument-based Copy_Traits
106
+ //
107
+
108
+ template <class AnyCPYTraits,
109
+ class SEngine, class SLayout,
110
+ class DEngine, class DLayout>
111
+ CUTE_HOST_DEVICE constexpr
112
+ void
113
+ copy_unpack(AnyCPYTraits const&,
114
+ Tensor<SEngine,SLayout> const& src,
115
+ Tensor<DEngine,DLayout> & dst)
116
+ {
117
+ using CopyOp = typename CPY_Op<AnyCPYTraits>::type;
118
+ using RegistersSrc = typename CopyOp::SRegisters;
119
+ using RegistersDst = typename CopyOp::DRegisters;
120
+ using RegTypeSrc = typename remove_extent<RegistersSrc>::type;
121
+ using RegTypeDst = typename remove_extent<RegistersDst>::type;
122
+ constexpr int RegNumSrc = extent<RegistersSrc>::value;
123
+ constexpr int RegNumDst = extent<RegistersDst>::value;
124
+
125
+ Tensor rS = recast<RegTypeSrc>(src);
126
+ Tensor rD = recast<RegTypeDst>(dst);
127
+
128
+ CUTE_STATIC_ASSERT_V(size(rS) == Int<RegNumSrc>{},
129
+ "Copy_Traits: src failed to vectorize into registers. Layout is incompatible with this CopyOp.");
130
+ CUTE_STATIC_ASSERT_V(size(rD) == Int<RegNumDst>{},
131
+ "Copy_Traits: dst failed to vectorize into registers. Layout is incompatible with this CopyOp.");
132
+
133
+ detail::explode(detail::CallCOPY<CopyOp>{},
134
+ rS, make_int_sequence<RegNumSrc>{},
135
+ rD, make_int_sequence<RegNumDst>{});
136
+ }
137
+
138
+ // Accept mutable temporaries
139
+ template <class AnyCPYTraits,
140
+ class SEngine, class SLayout,
141
+ class DEngine, class DLayout>
142
+ CUTE_HOST_DEVICE constexpr
143
+ void
144
+ copy_unpack(AnyCPYTraits const& traits,
145
+ Tensor<SEngine,SLayout> const& src,
146
+ Tensor<DEngine,DLayout> && dst)
147
+ {
148
+ copy_unpack(traits, src, dst);
149
+ }
150
+
151
+ namespace detail {
152
+
153
+ template <class CopyOp, class = void>
154
+ constexpr bool is_prefetch = false;
155
+
156
+ template <class CopyOp>
157
+ constexpr bool is_prefetch<CopyOp, void_t<typename CopyOp::PREFETCH>> = is_same_v<CopyOp, typename CopyOp::PREFETCH>;
158
+
159
+ } // end namespace detail
160
+
161
+
162
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/atom/copy_traits_sm100.hpp ADDED
The diff for this file is too large to render. See raw diff
 
lib/python3.12/site-packages/deep_gemm/include/cute/atom/copy_traits_sm100_im2col.hpp ADDED
@@ -0,0 +1,488 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2023 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+ #pragma once
32
+
33
+ /*! \file
34
+ \brief im2col make_tma_copy
35
+
36
+ */
37
+
38
+ #include "cute/arch/copy_sm90.hpp"
39
+ #include "cute/arch/copy_sm90_desc.hpp"
40
+ #include "cute/atom/copy_traits_sm90_im2col.hpp"
41
+ #include "cute/tensor.hpp"
42
+
43
+ namespace cute {
44
+
45
+ struct SM100_TMA_2SM_LOAD_IM2COL_OP : SM100_TMA_2SM_LOAD_IM2COL {};
46
+
47
+ /// @brief Non-executable specialization of Copy_Traits for SM100
48
+ /// im2col TMA load, with TMA descriptor but no barrier.
49
+ ///
50
+ /// Use `.with(memory_barrier)` to construct an executable version.
51
+ template <class NumBitsPerTMA, class TMATensor>
52
+ struct Copy_Traits<SM100_TMA_2SM_LOAD_IM2COL, NumBitsPerTMA, TMATensor>
53
+ {
54
+ using ThrID = Layout<_2>;
55
+ // Map from (src-thr,src-val) to bit
56
+ using SrcLayout = Layout<Shape<_2, NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
57
+ // Map from (dst-thr,dst-val) to bit
58
+ using DstLayout = Layout<Shape<_2, NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
59
+ // Reference map from (thr,val) to bit
60
+ using RefLayout = SrcLayout;
61
+
62
+ Im2ColTmaDescriptor tma_desc_;
63
+ TMATensor tma_tensor_;
64
+
65
+ CUTE_HOST_DEVICE constexpr
66
+ Im2ColTmaDescriptor const*
67
+ get_tma_descriptor() const
68
+ {
69
+ return &tma_desc_;
70
+ }
71
+
72
+ template <class GShape>
73
+ CUTE_HOST_DEVICE constexpr
74
+ TMATensor const
75
+ get_tma_tensor(GShape const&) const
76
+ {
77
+ return tma_tensor_;
78
+ }
79
+
80
+ /// @brief Get an executable specialization.
81
+ ///
82
+ /// Copy_Traits specializations with SM100_TMA_2SM_LOAD_IM2COL are not
83
+ /// directly executable. Instead, call this "with" member function
84
+ /// to get an executable specialization. "Executable" means that
85
+ /// @c copy_unpack works.
86
+ ///
87
+ /// @param tma_mbar Memory barrier for synchronization
88
+ ///
89
+ /// @param multicast_mask Multicast mask (unused; only exists
90
+ /// for consistency with the actual multicast Copy_Traits
91
+ /// specialization)
92
+ ///
93
+ /// @return Executable specialization of @c Copy_Traits
94
+ CUTE_HOST_DEVICE constexpr
95
+ Copy_Traits<SM100_TMA_2SM_LOAD_IM2COL_OP, NumBitsPerTMA>
96
+ with(uint64_t& tma_mbar, [[maybe_unused]] uint16_t const& multicast_mask = 0) const
97
+ {
98
+ return {{}, {&tma_desc_, &tma_mbar}};
99
+ }
100
+
101
+ // Copy_Traits specializations with SM100_TMA_2SM_LOAD_IM2COL
102
+ // are not directly executable. Instead, call .with
103
+ // to get an executable specialization.
104
+ template <class TS, class SLayout,
105
+ class TD, class DLayout>
106
+ CUTE_HOST_DEVICE friend constexpr void
107
+ copy_unpack(Copy_Traits const& traits,
108
+ Tensor<TS,SLayout> const& src,
109
+ Tensor<TD,DLayout> & dst) = delete;
110
+ };
111
+
112
+ /// TMA load, with TMA descriptor and barrier.
113
+ template <class NumBitsPerTMA>
114
+ struct Copy_Traits<SM100_TMA_2SM_LOAD_IM2COL_OP, NumBitsPerTMA>
115
+ : TMA_LOAD_IM2COL_Unpack<SM100_TMA_2SM_LOAD_IM2COL_OP>
116
+ {
117
+ using ThrID = Layout<_2>;
118
+ // Map from (src-thr,src-val) to bit
119
+ using SrcLayout = Layout<Shape<_2, NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
120
+ // Map from (dst-thr,dst-val) to bit
121
+ using DstLayout = Layout<Shape<_2, NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
122
+ // Reference map from (thr,val) to bit
123
+ using RefLayout = SrcLayout;
124
+
125
+ // SM100_TMA_2SM_LOAD_IM2COL arguments
126
+ tuple<
127
+ Im2ColTmaDescriptor const*,
128
+ uint64_t* // smem mbarrier
129
+ > const opargs_;
130
+ };
131
+
132
+ //////////////////////////////////////////////////////////////////////////////
133
+ ///////////////////////////// TMA_LOAD_MULTICAST /////////////////////////////
134
+ //////////////////////////////////////////////////////////////////////////////
135
+
136
+ struct SM100_TMA_2SM_LOAD_IM2COL_MULTICAST_OP : SM100_TMA_2SM_LOAD_IM2COL_MULTICAST {};
137
+
138
+ /// @brief Non-executable specialization of Copy_Traits for SM100
139
+ /// im2col TMA load, with TMA descriptor but no barrier or multicast
140
+ /// mask.
141
+ ///
142
+ /// Use `.with(memory_barrier)` to construct an executable version.
143
+ template <class NumBitsPerTMA, class TMATensor>
144
+ struct Copy_Traits<SM100_TMA_2SM_LOAD_IM2COL_MULTICAST, NumBitsPerTMA, TMATensor>
145
+ {
146
+ using ThrID = Layout<_2>;
147
+ // Map from (src-thr,src-val) to bit
148
+ using SrcLayout = Layout<Shape<_2, NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
149
+ // Map from (dst-thr,dst-val) to bit
150
+ using DstLayout = Layout<Shape<_2, NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
151
+ // Reference map from (thr,val) to bit
152
+ using RefLayout = SrcLayout;
153
+
154
+ Im2ColTmaDescriptor tma_desc_;
155
+ TMATensor tma_tensor_;
156
+
157
+ CUTE_HOST_DEVICE constexpr
158
+ Im2ColTmaDescriptor const*
159
+ get_tma_descriptor() const
160
+ {
161
+ return &tma_desc_;
162
+ }
163
+
164
+ template <class GShape>
165
+ CUTE_HOST_DEVICE constexpr
166
+ TMATensor const
167
+ get_tma_tensor(GShape const&) const
168
+ {
169
+ return tma_tensor_;
170
+ }
171
+
172
+ /// @brief Get an executable specialization.
173
+ ///
174
+ /// Copy_Traits specializations with SM100_TMA_2SM_LOAD_IM2COL_MULTICAST
175
+ /// are not directly executable. Instead, call this "with" member
176
+ /// function to get an executable specialization. "Executable"
177
+ /// means that @c copy_unpack works.
178
+ ///
179
+ /// @param tma_mbar Memory barrier for synchronization
180
+ ///
181
+ /// @param multicast_mask Multicast mask (defaults to a single CTA)
182
+ ///
183
+ /// @return Executable specialization of @c Copy_Traits
184
+ CUTE_HOST_DEVICE constexpr
185
+ Copy_Traits<SM100_TMA_2SM_LOAD_IM2COL_MULTICAST_OP, NumBitsPerTMA>
186
+ with(uint64_t& tma_mbar, uint16_t const& multicast_mask) const
187
+ {
188
+ return {{}, {&tma_desc_, &tma_mbar, multicast_mask}};
189
+ }
190
+
191
+ // Copy_Traits specializations with SM100_TMA_LOAD_IM2COL_MULTICAST
192
+ // are not directly executable. Instead, call .with to get an
193
+ // executable specialization.
194
+ template <class TS, class SLayout,
195
+ class TD, class DLayout>
196
+ CUTE_HOST_DEVICE friend constexpr void
197
+ copy_unpack(Copy_Traits const& traits,
198
+ Tensor<TS,SLayout> const& src,
199
+ Tensor<TD,DLayout> & dst) = delete;
200
+ };
201
+
202
+ /// @brief Executable specialization of Copy_Traits for SM100 multicast
203
+ /// im2col TMA load, with TMA descriptor, barrier, and multicast mask.
204
+ template <class NumBitsPerTMA>
205
+ struct Copy_Traits<SM100_TMA_2SM_LOAD_IM2COL_MULTICAST_OP, NumBitsPerTMA>
206
+ : TMA_LOAD_IM2COL_Unpack<SM100_TMA_2SM_LOAD_IM2COL_MULTICAST_OP>
207
+ {
208
+ using ThrID = Layout<_2>;
209
+ // Map from (src-thr,src-val) to bit.
210
+ using SrcLayout = Layout<Shape<_2, NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
211
+ // Map from (dst-thr,dst-val) to bit
212
+ using DstLayout = Layout<Shape<_2, NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
213
+ // Reference map from (thr,val) to bit
214
+ using RefLayout = SrcLayout;
215
+
216
+ // SM100_TMA_2SM_LOAD_IM2COL_MULTICAST arguments
217
+ tuple<
218
+ Im2ColTmaDescriptor const*,
219
+ uint64_t*, // smem mbarrier
220
+ uint16_t // multicast mask
221
+ > const opargs_;
222
+ };
223
+
224
+ ////////////////////////////////////
225
+ // Make TMA
226
+ ///////////////////////////////////
227
+
228
+ #if !defined(__CUDACC_RTC__)
229
+ /** Make a CuTe CTA-collective TiledCopy for a TMA operation.
230
+ *
231
+ * @param CopyOp The target copy operation: SM100_TMA_2SM_LOAD
232
+ * @param gtensor The GMEM Tensor to be involved in the TMA.
233
+ * @param slayout The SMEM Layout to be involved in the TMA.
234
+ * @param cluster_tile The Cluster-local tile that each Cluster will be tiling GMEM with.
235
+ * This is often the cluster_tile_shape that is used to tile the GMEM:
236
+ * local_tile(gtensor, cluster_tile_shape, cluster_coord)
237
+ * -> Cluster-local tile of GMEM
238
+ * @param mma The TiledMMA that defines the Cluster-Tile to Block-Tile partitioning.
239
+ *
240
+ * This code attempts to maximize the TMA box size. It does this by tracing
241
+ * the SMEM "vector" -- the inverse of the smem layout -- to find the largest
242
+ * contiguous array of smem that can be written to/from global memory given
243
+ * the constraints that the TMA instruction imposes.
244
+ *
245
+ * This is accomplished by assigning "basis" strides to the GMEM to track which
246
+ * modes of SMEM map to which modes of GMEM, then reordering the modes of GMEM according
247
+ * to the SMEM vector, and then using those GMEM/SMEM modes to fill in the desc.
248
+ *
249
+ * Examples:
250
+ */
251
+ template <class CopyOp,
252
+ class GEngine, class GLayout,
253
+ class SLayout,
254
+ class Cluster_Tile,
255
+ class... Args,
256
+ class LowerCornerStride,
257
+ class UpperCornerStride,
258
+ class LowerPaddingStride,
259
+ class UpperPaddingStride,
260
+ class TraversalStride,
261
+ class LowerSRTStride,
262
+ class DilationStride>
263
+ CUTE_HOST
264
+ auto
265
+ make_im2col_tma_copy_A_sm100(CopyOp const& copy_op,
266
+ Tensor<GEngine,GLayout> const& gtensor, // (M,K,...)
267
+ SLayout const& slayout, // (MMA, MMA_M, MMA_K)
268
+ Cluster_Tile const& cluster_tile, // (TILE_M,TILE_N,TILE_K)
269
+ TiledMMA<Args...> const& mma,
270
+ LowerCornerStride const& lower_corner_whd,
271
+ UpperCornerStride const& upper_corner_whd,
272
+ LowerPaddingStride const& lower_padding_whd,
273
+ UpperPaddingStride const& upper_padding_whd,
274
+ TraversalStride const& stride_whd,
275
+ LowerSRTStride const& lower_srt,
276
+ DilationStride const& stride_srt,
277
+ TMA::DescriptorAuxParams const& aux_params = {})
278
+ {
279
+ constexpr int R = GLayout::rank;
280
+ // Keep only MK modes from MNK
281
+ auto cluster_tile_shape = append<R>(make_shape(get<0>(cluster_tile), get<2>(cluster_tile)), Int<1>{});
282
+ auto cluster_layout = make_identity_layout(cluster_tile_shape);
283
+ // cta val idx -> gmem mode
284
+ auto cta_v_tile = layout<1>(mma.thrfrg_A(cluster_layout))(_, repeat<R>(_));
285
+
286
+ auto cta_t_vmnk_strides = [](){
287
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD_IM2COL_MULTICAST> ||
288
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD_IM2COL_MULTICAST>) {
289
+ return Stride<_0,_0,_1,_0>{}; // VMNK: Use only the N-CTAs in the Multicast
290
+ } else
291
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD_IM2COL> ||
292
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD_IM2COL>) {
293
+ return Stride<_0,_0,_0,_0>{}; // VMNK: Use no CTAs in Non-Multicast
294
+ } else {
295
+ static_assert(dependent_false<CopyOp>, "Unsupported TMA");
296
+ }
297
+ }();
298
+
299
+ auto cta_t_shape = shape(mma.get_thr_layout_vmnk());
300
+ // cta rank -> logical cta idx
301
+ auto cta_t_map = make_layout(cta_t_shape, compact_col_major(cta_t_shape, cta_t_vmnk_strides));
302
+
303
+ return detail::make_tma_copy_im2col(copy_op, gtensor, slayout,
304
+ cta_t_map, cta_v_tile,
305
+ lower_corner_whd, upper_corner_whd, lower_padding_whd, upper_padding_whd, stride_whd,
306
+ lower_srt, stride_srt, aux_params);
307
+ }
308
+
309
+ template <class CopyOp,
310
+ class GEngine, class GLayout,
311
+ class SLayout,
312
+ class Cluster_Tile,
313
+ class... Args,
314
+ class LowerCornerStride,
315
+ class UpperCornerStride,
316
+ class LowerPaddingStride,
317
+ class UpperPaddingStride,
318
+ class TraversalStride,
319
+ class LowerSRTStride,
320
+ class DilationStride>
321
+ CUTE_HOST
322
+ auto
323
+ make_im2col_tma_copy_B_sm100(CopyOp const& copy_op,
324
+ Tensor<GEngine,GLayout> const& gtensor, // (N,K,...)
325
+ SLayout const& slayout, // (MMA, MMA_N, MMA_K)
326
+ Cluster_Tile const& cluster_tile, // (TILE_M,TILE_N,TILE_K)
327
+ TiledMMA<Args...> const& mma,
328
+ LowerCornerStride const& lower_corner_whd,
329
+ UpperCornerStride const& upper_corner_whd,
330
+ LowerPaddingStride const& lower_padding_whd,
331
+ UpperPaddingStride const& upper_padding_whd,
332
+ TraversalStride const& stride_whd,
333
+ LowerSRTStride const& lower_srt,
334
+ DilationStride const& stride_srt,
335
+ TMA::DescriptorAuxParams const& aux_params = {})
336
+ {
337
+ constexpr int R = GLayout::rank;
338
+ // Keep only NK modes from MNK
339
+ auto cluster_tile_shape = append<R>(make_shape(get<1>(cluster_tile), get<2>(cluster_tile)), Int<1>{});
340
+ auto cluster_layout = make_identity_layout(cluster_tile_shape);
341
+ // cta val idx -> gmem mode
342
+ auto cta_v_tile = layout<1>(mma.thrfrg_B(cluster_layout))(_, repeat<R>(_));
343
+
344
+ auto cta_t_vmnk_strides = [](){
345
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD_IM2COL_MULTICAST> ||
346
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD_IM2COL_MULTICAST>) {
347
+ return Stride<_0,_1,_0,_0>{}; // VMNK: Use only the M-CTAs in the Multicast
348
+ } else
349
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD_IM2COL> ||
350
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD_IM2COL>) {
351
+ return Stride<_0,_0,_0,_0>{}; // VMNK: Use no CTAs in Non-Multicast
352
+ } else {
353
+ static_assert(dependent_false<CopyOp>, "Unsupported TMA");
354
+ }
355
+ }();
356
+
357
+ auto cta_t_shape = shape(mma.get_thr_layout_vmnk());
358
+ // cta rank -> logical cta idx
359
+ auto cta_t_map = make_layout(cta_t_shape, compact_col_major(cta_t_shape, cta_t_vmnk_strides));
360
+
361
+ return detail::make_tma_copy_im2col(copy_op, gtensor, slayout,
362
+ cta_t_map, cta_v_tile,
363
+ lower_corner_whd, upper_corner_whd, lower_padding_whd, upper_padding_whd, stride_whd,
364
+ lower_srt, stride_srt, aux_params);
365
+ }
366
+
367
+ /////////////////////////////////////
368
+ // Experimental Make Im2col TMA Atom
369
+ /////////////////////////////////////
370
+
371
+ template <class TmaInternalType = void,
372
+ class CopyOp,
373
+ class GEngine, class GLayout,
374
+ class SLayout,
375
+ class MMA_Tiler,
376
+ class... Args,
377
+ class ClusterShapeVMNK,
378
+ class LowerCornerStride,
379
+ class UpperCornerStride,
380
+ class LowerPaddingStride,
381
+ class UpperPaddingStride,
382
+ class TraversalStride,
383
+ class LowerSRTStride,
384
+ class DilationStride>
385
+ CUTE_HOST
386
+ auto
387
+ make_im2col_tma_atom_A_sm100(CopyOp const& copy_op,
388
+ Tensor<GEngine,GLayout> const& gtensor, // (M, K, ...)
389
+ SLayout const& slayout, // (MMA, MMA_M, MMA_K, ...)
390
+ MMA_Tiler const& mma_tiler, // (TILE_M, TILE_N, TILE_K, ...)
391
+ TiledMMA<Args...> const& mma,
392
+ ClusterShapeVMNK const& cluster_shape, // (CTA_V, CTA_M, CTA_N, CTA_K)
393
+ LowerCornerStride const& lower_corner_whd,
394
+ UpperCornerStride const& upper_corner_whd,
395
+ LowerPaddingStride const& lower_padding_whd,
396
+ UpperPaddingStride const& upper_padding_whd,
397
+ TraversalStride const& stride_whd,
398
+ LowerSRTStride const& lower_srt,
399
+ DilationStride const& stride_srt,
400
+ TMA::DescriptorAuxParams const& aux_params = {})
401
+ {
402
+ constexpr int R = GLayout::rank;
403
+ // Keep only MK modes from MNK
404
+ auto cluster_tile_shape = append<R>(make_shape(get<0>(mma_tiler), get<2>(mma_tiler)), Int<1>{});
405
+ auto cluster_layout = make_identity_layout(cluster_tile_shape);
406
+ // cta val idx -> gmem mode
407
+ auto cta_v_tile = layout<1>(mma.thrfrg_A(cluster_layout))(_, repeat<R>(_));
408
+
409
+ // The size of the multicasting
410
+ auto num_multicast = [&](){
411
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD_IM2COL_MULTICAST> ||
412
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD_IM2COL_MULTICAST>) {
413
+ return size<2>(cluster_shape); // VMNK: Use only the N-CTAs in the Multicast
414
+ } else
415
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD_IM2COL> ||
416
+ is_same_v<CopyOp, SM90_TMA_STORE_IM2COL> ||
417
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD_IM2COL>) {
418
+ return Int<1>{}; // VMNK: Use no CTAs in Non-Multicast
419
+ } else {
420
+ static_assert(dependent_false<CopyOp>, "Unsupported TMA");
421
+ }
422
+ }();
423
+
424
+ return detail::make_tma_atom_im2col(copy_op, gtensor, slayout, num_multicast, cta_v_tile,
425
+ lower_corner_whd, upper_corner_whd, lower_padding_whd, upper_padding_whd,
426
+ stride_whd, lower_srt, stride_srt, aux_params);
427
+ }
428
+
429
+ template <class TmaInternalType = void,
430
+ class CopyOp,
431
+ class GEngine, class GLayout,
432
+ class SLayout,
433
+ class MMA_Tiler,
434
+ class... Args,
435
+ class ClusterShapeVMNK,
436
+ class LowerCornerStride,
437
+ class UpperCornerStride,
438
+ class LowerPaddingStride,
439
+ class UpperPaddingStride,
440
+ class TraversalStride,
441
+ class LowerSRTStride,
442
+ class DilationStride>
443
+ CUTE_HOST
444
+ auto
445
+ make_im2col_tma_atom_B_sm100(CopyOp const& copy_op,
446
+ Tensor<GEngine,GLayout> const& gtensor, // (N, K, ...)
447
+ SLayout const& slayout, // (MMA, MMA_N, MMA_K, ...)
448
+ MMA_Tiler const& mma_tiler, // (TILE_M, TILE_N, TILE_K, ...)
449
+ TiledMMA<Args...> const& mma,
450
+ ClusterShapeVMNK const& cluster_shape, // (CTA_V, CTA_M, CTA_N, CTA_K)
451
+ LowerCornerStride const& lower_corner_whd,
452
+ UpperCornerStride const& upper_corner_whd,
453
+ LowerPaddingStride const& lower_padding_whd,
454
+ UpperPaddingStride const& upper_padding_whd,
455
+ TraversalStride const& stride_whd,
456
+ LowerSRTStride const& lower_srt,
457
+ DilationStride const& stride_srt,
458
+ TMA::DescriptorAuxParams const& aux_params = {})
459
+ {
460
+ constexpr int R = GLayout::rank;
461
+ // Keep only NK modes from MNK
462
+ auto cluster_tile_shape = append<R>(make_shape(get<1>(mma_tiler), get<2>(mma_tiler)), Int<1>{});
463
+ auto cluster_layout = make_identity_layout(cluster_tile_shape);
464
+ // cta val idx -> gmem mode
465
+ auto cta_v_tile = layout<1>(mma.thrfrg_B(cluster_layout))(_, repeat<R>(_));
466
+
467
+ // The size of the multicasting
468
+ auto num_multicast = [&](){
469
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD_IM2COL_MULTICAST> ||
470
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD_IM2COL_MULTICAST>) {
471
+ return size<1>(cluster_shape); // VMNK: Use only the M-CTAs in the Multicast
472
+ } else
473
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD_IM2COL> ||
474
+ is_same_v<CopyOp, SM90_TMA_STORE_IM2COL> ||
475
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD_IM2COL>) {
476
+ return Int<1>{}; // VMNK: Use no CTAs in Non-Multicast
477
+ } else {
478
+ static_assert(dependent_false<CopyOp>, "Unsupported TMA");
479
+ }
480
+ }();
481
+
482
+ return detail::make_tma_atom_im2col(copy_op, gtensor, slayout, num_multicast, cta_v_tile,
483
+ lower_corner_whd, upper_corner_whd, lower_padding_whd, upper_padding_whd,
484
+ stride_whd, lower_srt, stride_srt, aux_params);
485
+ }
486
+ #endif // !defined(__CUDACC_RTC__)
487
+
488
+ } // end namespace cute
lib/python3.12/site-packages/deep_gemm/include/cute/atom/copy_traits_sm100_tma.hpp ADDED
@@ -0,0 +1,487 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***************************************************************************************************
2
+ * Copyright (c) 2021 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * 3. Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ **************************************************************************************************/
31
+
32
+
33
+
34
+ #pragma once
35
+
36
+ #if !defined(__CUDACC_RTC__)
37
+ #include <cuda.h>
38
+ #endif
39
+
40
+ #include <cute/tensor.hpp>
41
+ #include <cute/atom/copy_traits_sm90_tma.hpp>
42
+ #include <cute/arch/copy_sm100_tma.hpp>
43
+ #include <cute/atom/copy_traits.hpp>
44
+
45
+ namespace cute
46
+ {
47
+
48
+ //////////////////////////////////////////////////////////////////////////////
49
+ ////////////////////////////// TMA_LOAD ////////////////////////////////////////
50
+ //////////////////////////////////////////////////////////////////////////////
51
+
52
+ struct SM100_TMA_2SM_LOAD_OP : SM100_TMA_2SM_LOAD {};
53
+
54
+ // The non-executable SM100_TMA_2SM_LOAD with tma_desc and no tma_mbar
55
+ // Use .with(tma_mbar) to construct an executable version
56
+ template <class NumBitsPerTMA, class AuxParams_>
57
+ struct Copy_Traits<SM100_TMA_2SM_LOAD, NumBitsPerTMA, AuxParams_>
58
+ {
59
+ using ThrID = Layout<_2>;
60
+ // Map from (src-thr,src-val) to bit
61
+ using SrcLayout = Layout<Shape<_2,NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
62
+ // Map from (dst-thr,dst-val) to bit
63
+ using DstLayout = Layout<Shape<_2,NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
64
+ // Reference map from (thr,val) to bit
65
+ using RefLayout = SrcLayout;
66
+
67
+ // SM100_TMA_2SM_LOAD arguments
68
+ TmaDescriptor tma_desc_;
69
+ using AuxParams = AuxParams_;
70
+ AuxParams aux_params_;
71
+
72
+ // Return TmaDescriptor/TensorMap
73
+ CUTE_HOST_DEVICE constexpr
74
+ TmaDescriptor const*
75
+ get_tma_descriptor() const {
76
+ return &tma_desc_;
77
+ }
78
+
79
+ // Construct an executable SM100_TMA_2SM_LOAD with tma_mbar
80
+ CUTE_HOST_DEVICE constexpr
81
+ Copy_Traits<SM100_TMA_2SM_LOAD_OP, NumBitsPerTMA>
82
+ with(
83
+ uint64_t& tma_mbar,
84
+ [[maybe_unused]] uint16_t const& multicast_mask = 0,
85
+ TMA::CacheHintSm100 const& cache_hint = TMA::CacheHintSm100::EVICT_NORMAL) const {
86
+ // We accept multicast_mask here to keep the API for both atoms consistent
87
+ return {{}, {&tma_desc_, &tma_mbar, static_cast<uint64_t>(cache_hint)}};
88
+ }
89
+
90
+ // Construct an executable SM100_TMA_2SM_LOAD with tma_mbar (temp. overloaded for grouped gemm/ptr array gemm)
91
+ CUTE_HOST_DEVICE constexpr
92
+ Copy_Traits<SM100_TMA_2SM_LOAD_OP, NumBitsPerTMA>
93
+ with(
94
+ TmaDescriptor const* new_tma_desc,
95
+ uint64_t& tma_mbar,
96
+ [[maybe_unused]] uint16_t const& multicast_mask = 0,
97
+ TMA::CacheHintSm100 const& cache_hint = TMA::CacheHintSm100::EVICT_NORMAL) const {
98
+ // We accept multicast_mask here to keep the API for both atoms consistent
99
+ return {{}, {new_tma_desc, &tma_mbar, static_cast<uint64_t>(cache_hint)}};
100
+ }
101
+
102
+ template <class GShape>
103
+ CUTE_HOST_DEVICE constexpr
104
+ auto
105
+ get_tma_tensor(GShape const& g_shape) const {
106
+ static_assert(is_congruent<decltype(g_shape), decltype(aux_params_.g_stride_)>::value);
107
+ return make_counting_tensor(make_layout(g_shape, aux_params_.g_stride_));
108
+ }
109
+
110
+ // Don't try to execute a copy with SM100_TMA_2SM_LOAD before calling .with()
111
+ template <class TS, class SLayout,
112
+ class TD, class DLayout>
113
+ CUTE_HOST_DEVICE friend constexpr void
114
+ copy_unpack(Copy_Traits const& traits,
115
+ Tensor<TS,SLayout> const& src,
116
+ Tensor<TD,DLayout> & dst) = delete;
117
+ };
118
+
119
+ // The executable SM100_TMA_2SM_LOAD with tma_desc and tma_mbar
120
+ template <class NumBitsPerTMA>
121
+ struct Copy_Traits<SM100_TMA_2SM_LOAD_OP, NumBitsPerTMA>
122
+ : TMA_LOAD_Unpack<SM100_TMA_2SM_LOAD_OP, NumBitsPerTMA>
123
+ {
124
+ using ThrID = Layout<_2>;
125
+ // Map from (src-thr,src-val) to bit
126
+ using SrcLayout = Layout<Shape<_2,NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
127
+ // Map from (dst-thr,dst-val) to bit
128
+ using DstLayout = Layout<Shape<_2,NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
129
+ // Reference map from (thr,val) to bit
130
+ using RefLayout = SrcLayout;
131
+
132
+ // SM100_TMA_2SM_LOAD arguments
133
+ tuple<
134
+ TmaDescriptor const*,
135
+ uint64_t*, // smem mbarrier
136
+ uint64_t // cache hint
137
+ > const opargs_;
138
+ };
139
+
140
+ //////////////////////////////////////////////////////////////////////////////
141
+ ///////////////////////////// TMA_LOAD_MULTICAST /////////////////////////////
142
+ //////////////////////////////////////////////////////////////////////////////
143
+
144
+ struct SM100_TMA_2SM_LOAD_MULTICAST_OP : SM100_TMA_2SM_LOAD_MULTICAST {};
145
+
146
+ template <class NumBitsPerTMA, class AuxParams_>
147
+ struct Copy_Traits<SM100_TMA_2SM_LOAD_MULTICAST, NumBitsPerTMA, AuxParams_>
148
+ {
149
+ using ThrID = Layout<_2>;
150
+ // Map from (src-thr,src-val) to bit
151
+ using SrcLayout = Layout<Shape<_2,NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
152
+ // Map from (dst-thr,dst-val) to bit
153
+ using DstLayout = Layout<Shape<_2,NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
154
+ // Reference map from (thr,val) to bit
155
+ using RefLayout = SrcLayout;
156
+
157
+ // SM100_TMA_2SM_LOAD_MULTICAST_OP arguments
158
+ TmaDescriptor tma_desc_;
159
+ using AuxParams = AuxParams_;
160
+ AuxParams aux_params_;
161
+
162
+ // Return TmaDescriptor/TensorMap
163
+ CUTE_HOST_DEVICE constexpr
164
+ TmaDescriptor const*
165
+ get_tma_descriptor() const {
166
+ return &tma_desc_;
167
+ }
168
+
169
+ // Construct an executable SM100_TMA_2SM_LOAD_MULTICAST_OP with tma_mbar
170
+ CUTE_HOST_DEVICE constexpr
171
+ Copy_Traits<SM100_TMA_2SM_LOAD_MULTICAST_OP, NumBitsPerTMA>
172
+ with(
173
+ uint64_t& tma_load_mbar,
174
+ uint16_t const& multicast_mask,
175
+ TMA::CacheHintSm100 const& cache_hint = TMA::CacheHintSm100::EVICT_NORMAL) const {
176
+ return {{}, {&tma_desc_, &tma_load_mbar, multicast_mask, static_cast<uint64_t>(cache_hint)}};
177
+ }
178
+
179
+ // Construct an executable SM100_TMA_2SM_LOAD_MULTICAST_OP with tma_mbar (temp. overloaded for grouped gemm/ptr array gemm)
180
+ CUTE_HOST_DEVICE constexpr
181
+ Copy_Traits<SM100_TMA_2SM_LOAD_MULTICAST_OP, NumBitsPerTMA>
182
+ with(
183
+ TmaDescriptor const* new_tma_desc,
184
+ uint64_t& tma_load_mbar,
185
+ uint16_t const& multicast_mask,
186
+ TMA::CacheHintSm100 const& cache_hint = TMA::CacheHintSm100::EVICT_NORMAL) const {
187
+ return {{}, {new_tma_desc, &tma_load_mbar, multicast_mask, static_cast<uint64_t>(cache_hint)}};
188
+ }
189
+
190
+ template <class GShape>
191
+ CUTE_HOST_DEVICE constexpr
192
+ auto
193
+ get_tma_tensor(GShape const& g_shape) const {
194
+ static_assert(is_congruent<decltype(g_shape), decltype(aux_params_.g_stride_)>::value);
195
+ return make_counting_tensor(make_layout(g_shape, aux_params_.g_stride_));
196
+ }
197
+
198
+ // Don't try to execute a copy with SM100_TMA_2SM_LOAD_MULTICAST_OP before calling .with()
199
+ template <class TS, class SLayout,
200
+ class TD, class DLayout>
201
+ CUTE_HOST_DEVICE friend constexpr void
202
+ copy_unpack(Copy_Traits const& traits,
203
+ Tensor<TS,SLayout> const& src,
204
+ Tensor<TD,DLayout> & dst) = delete;
205
+ };
206
+
207
+ template <class NumBitsPerTMA>
208
+ struct Copy_Traits<SM100_TMA_2SM_LOAD_MULTICAST_OP, NumBitsPerTMA>
209
+ : TMA_LOAD_Unpack<SM100_TMA_2SM_LOAD_MULTICAST_OP, NumBitsPerTMA>
210
+ {
211
+ using ThrID = Layout<_2>;
212
+ // Map from (src-thr,src-val) to bit
213
+ using SrcLayout = Layout<Shape<_2,NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
214
+ // Map from (dst-thr,dst-val) to bit
215
+ using DstLayout = Layout<Shape<_2,NumBitsPerTMA>, Stride<NumBitsPerTMA,_1>>;
216
+ // Reference map from (thr,val) to bit
217
+ using RefLayout = SrcLayout;
218
+
219
+ // SM100_TMA_2SM_LOAD_MULTICAST_OP arguments
220
+ tuple<
221
+ TmaDescriptor const*,
222
+ uint64_t*, // smem mbarrier
223
+ uint16_t, // multicast mask
224
+ uint64_t // cache hint
225
+ > const opargs_;
226
+ };
227
+
228
+ ////////////////////////////////////
229
+ // Make TMA
230
+ ///////////////////////////////////
231
+
232
+ #if !defined(__CUDACC_RTC__)
233
+ /** Make a CuTe CTA-collective TiledCopy for a TMA operation.
234
+ *
235
+ * @param CopyOp The target copy operation: SM100_TMA_2SM_LOAD
236
+ * @param gtensor The GMEM Tensor to be involved in the TMA.
237
+ * @param slayout The SMEM Layout to be involved in the TMA.
238
+ * @param cluster_tile The Cluster-local tile that each Cluster will be tiling GMEM with.
239
+ * This is often the cluster_tile_shape that is used to tile the GMEM:
240
+ * local_tile(gtensor, cluster_tile_shape, cluster_coord)
241
+ * -> Cluster-local tile of GMEM
242
+ * @param mma The TiledMMA that defines the Cluster-Tile to Block-Tile partitioning.
243
+ *
244
+ * This code attempts to maximize the TMA box size. It does this by tracing
245
+ * the SMEM "vector" -- the inverse of the smem layout -- to find the largest
246
+ * contiguous array of smem that can be written to/from global memory given
247
+ * the constraints that the TMA instruction imposes.
248
+ *
249
+ * This is accomplished by assigning "basis" strides to the GMEM to track which
250
+ * modes of SMEM map to which modes of GMEM, then reordering the modes of GMEM according
251
+ * to the SMEM vector, and then using those GMEM/SMEM modes to fill in the desc.
252
+ *
253
+ * Examples:
254
+ */
255
+ template <class TmaInternalType = void,
256
+ class CopyOp,
257
+ class GEngine, class GLayout,
258
+ class SLayout,
259
+ class Cluster_Tiler,
260
+ class... Args>
261
+ CUTE_HOST
262
+ auto
263
+ make_tma_copy_A_sm100(CopyOp const& copy_op,
264
+ Tensor<GEngine,GLayout> const& gtensor, // (M, K, ...)
265
+ SLayout const& slayout, // (MMA, MMA_M, MMA_K, ...)
266
+ Cluster_Tiler const& cluster_tiler, // (TILER_M, TILER_N, TILER_K, ...)
267
+ TiledMMA<Args...> const& mma)
268
+ {
269
+ // Keep only MK modes from MNK
270
+ auto cluster_tiler_mk = remove<1>(cluster_tiler);
271
+ // cluster tile coord -> gtensor coord
272
+ auto g_tile = make_identity_layout(shape(gtensor)).compose(cluster_tiler_mk); // (TILE_M, TILE_K, ...)
273
+ // cta val idx -> gmem mode
274
+ auto cta_v_tile = layout<1>(mma.thrfrg_A(g_tile))(_, repeat<rank(g_tile)>(_)); // (MMA, MMA_M, MMA_K, ...)
275
+
276
+ auto cta_t_vmnk_strides = [](){
277
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD_MULTICAST> ||
278
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD_MULTICAST>) {
279
+ return Stride<_0,_0,_1,_0>{}; // VMNK: Use only the N-CTAs in the Multicast
280
+ } else
281
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD> ||
282
+ is_same_v<CopyOp, SM90_TMA_STORE> ||
283
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD>) {
284
+ return Stride<_0,_0,_0,_0>{}; // VMNK: Use no CTAs in Non-Multicast
285
+ } else {
286
+ static_assert(dependent_false<CopyOp>, "Unsupported TMA");
287
+ }
288
+ }();
289
+
290
+ auto cta_t_shape = shape(mma.get_thr_layout_vmnk());
291
+ // cta rank -> logical cta idx
292
+ auto cta_t_map = coalesce(make_layout(cta_t_shape, compact_col_major(cta_t_shape, cta_t_vmnk_strides)));
293
+
294
+ // Prefer TmaInternalType if specified. Fallback to GEngine::value_type
295
+ using TmaType = conditional_t<is_same<void, TmaInternalType>::value, typename GEngine::value_type, TmaInternalType>;
296
+ return detail::make_tma_copy_tiled<TmaType>(copy_op, gtensor, slayout, cta_t_map, cta_v_tile);
297
+ }
298
+
299
+ template <class TmaInternalType = void,
300
+ class CopyOp,
301
+ class GEngine, class GLayout,
302
+ class SLayout,
303
+ class Cluster_Tiler,
304
+ class... Args>
305
+ CUTE_HOST
306
+ auto
307
+ make_tma_copy_B_sm100(CopyOp const& copy_op,
308
+ Tensor<GEngine,GLayout> const& gtensor, // (N, K, ...)
309
+ SLayout const& slayout, // (MMA, MMA_N, MMA_K, ...)
310
+ Cluster_Tiler const& cluster_tiler, // (TILE_M, TILE_N, TILE_K, ...)
311
+ TiledMMA<Args...> const& mma)
312
+ {
313
+ // Keep only NK modes from MNK
314
+ auto cluster_tiler_nk = remove<0>(cluster_tiler);
315
+ // cluster tile coord -> gtensor coord
316
+ auto g_tile = make_identity_layout(shape(gtensor)).compose(cluster_tiler_nk); // (TILE_N, TILE_K, ...)
317
+ // cta val idx -> gmem mode
318
+ auto cta_v_tile = layout<1>(mma.thrfrg_B(g_tile))(_, repeat<rank(g_tile)>(_)); // (MMA, MMA_N, MMA_K, ...)
319
+
320
+ auto cta_t_vmnk_strides = [](){
321
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD_MULTICAST> ||
322
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD_MULTICAST>) {
323
+ return Stride<_0,_1,_0,_0>{}; // VMNK: Use only the M-CTAs in the Multicast
324
+ } else
325
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD> ||
326
+ is_same_v<CopyOp, SM90_TMA_STORE> ||
327
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD>) {
328
+ return Stride<_0,_0,_0,_0>{}; // VMNK: Use no CTAs in Non-Multicast
329
+ } else {
330
+ static_assert(dependent_false<CopyOp>, "Unsupported TMA");
331
+ }
332
+ }();
333
+
334
+ auto cta_t_shape = shape(mma.get_thr_layout_vmnk());
335
+ // cta rank -> logical cta idx
336
+ auto cta_t_map = coalesce(make_layout(cta_t_shape, compact_col_major(cta_t_shape, cta_t_vmnk_strides)));
337
+
338
+ // Prefer TmaInternalType if specified. Fallback to GEngine::value_type
339
+ using TmaType = conditional_t<is_same<void, TmaInternalType>::value, typename GEngine::value_type, TmaInternalType>;
340
+ return detail::make_tma_copy_tiled<TmaType>(copy_op, gtensor, slayout, cta_t_map, cta_v_tile);
341
+ }
342
+
343
+ template <class TmaInternalType = void,
344
+ class CopyOp,
345
+ class GEngine, class GLayout,
346
+ class SLayout,
347
+ class Cluster_Tiler,
348
+ class... Args>
349
+ CUTE_HOST
350
+ auto
351
+ make_tma_copy_C_sm100(CopyOp const& copy_op,
352
+ Tensor<GEngine,GLayout> const& gtensor, // (M, N, ...)
353
+ SLayout const& slayout, // (MMA, MMA_M, MMA_N, ...)
354
+ Cluster_Tiler const& cluster_tiler, // (TILE_M, TILE_N, TILE_K, ...)
355
+ TiledMMA<Args...> const& mma)
356
+ {
357
+ // Keep only MN modes from MNK
358
+ auto cluster_tiler_mn = remove<2>(cluster_tiler);
359
+ // cluster tile coord -> gtensor coord
360
+ auto g_tile = make_identity_layout(shape(gtensor)).compose(cluster_tiler_mn); // (TILE_M, TILE_N, ...)
361
+ // cta val idx -> gmem mode
362
+ auto cta_v_tile = layout<1>(mma.thrfrg_C(g_tile))(_, repeat<rank(g_tile)>(_)); // (MMA, MMA_M, MMA_N, ...)
363
+
364
+ static_assert(is_same_v<CopyOp, SM90_TMA_LOAD> ||
365
+ is_same_v<CopyOp, SM90_TMA_STORE> ||
366
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD>,
367
+ "Unsupported TMA Op, expected a non-multicast TMA");
368
+
369
+ // No multicast, so only 1 CTA involved
370
+ auto cta_t_map = Layout<_1,_0>{};
371
+
372
+ // Prefer TmaInternalType if specified. Fallback to GEngine::value_type
373
+ using TmaType = conditional_t<is_same<void, TmaInternalType>::value, typename GEngine::value_type, TmaInternalType>;
374
+ return detail::make_tma_copy_tiled<TmaType>(copy_op, gtensor, slayout, cta_t_map, cta_v_tile);
375
+ }
376
+
377
+ ////////////////////////////////////
378
+ // Experimental Make TMA Atom
379
+ ///////////////////////////////////
380
+
381
+ template <class TmaInternalType = void,
382
+ class CopyOp,
383
+ class GEngine, class GLayout,
384
+ class SLayout,
385
+ class MMA_Tiler,
386
+ class... Args,
387
+ class ClusterShapeVMNK>
388
+ CUTE_HOST
389
+ auto
390
+ make_tma_atom_A_sm100(CopyOp const& copy_op,
391
+ Tensor<GEngine,GLayout> const& gtensor, // (M, K, ...)
392
+ SLayout const& slayout, // (MMA, MMA_M, MMA_K, ...)
393
+ MMA_Tiler const& mma_tiler, // (TILE_M, TILE_N, TILE_K, ...)
394
+ TiledMMA<Args...> const& mma,
395
+ ClusterShapeVMNK const& cluster_shape) // (CTA_V, CTA_M, CTA_N, CTA_K)
396
+ {
397
+ // Keep only MK modes from MNK
398
+ auto mma_tiler_mk = remove<1>(mma_tiler);
399
+
400
+ // cluster tile coord -> gtensor coord
401
+ auto g_tile = make_identity_layout(shape(gtensor)).compose(mma_tiler_mk); // (TILE_M, TILE_K, ...)
402
+
403
+ // cta val idx -> gmem mode
404
+ auto cta_v_tile = layout<1>(mma.thrfrg_A(g_tile))(_, repeat<rank(g_tile)>(_)); // (MMA, MMA_M, MMA_K, ...)
405
+
406
+ #if 0
407
+ print("(tma_a) slayout: "); print(slayout); print("\n");
408
+ print("(tma_a) mma_tiler_nk: "); print(mma_tiler_nk); print("\n");
409
+ print("(tma_a) g_tile: "); print(g_tile); print("\n");
410
+ print("(tma_a) mma_tiler: "); print(mma_tiler); print("\n");
411
+ print("(tma_a) cta_v_tile: "); print(cta_v_tile); print("\n");
412
+ #endif
413
+
414
+ // The size of the multicasting
415
+ auto num_multicast = [&](){
416
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD_MULTICAST> ||
417
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD_MULTICAST>) {
418
+ return size<2>(cluster_shape); // VMNK: Use only the N-CTAs in the Multicast
419
+ } else
420
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD> ||
421
+ is_same_v<CopyOp, SM90_TMA_STORE> ||
422
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD>) {
423
+ return Int<1>{}; // VMNK: Use no CTAs in Non-Multicast
424
+ } else {
425
+ static_assert(dependent_false<CopyOp>, "Unsupported TMA");
426
+ }
427
+ }();
428
+
429
+ // Prefer TmaInternalType if specified. Fallback to GEngine::value_type
430
+ using TmaType = conditional_t<is_same<void, TmaInternalType>::value, typename GEngine::value_type, TmaInternalType>;
431
+ return detail::make_tma_copy_atom<TmaType>(copy_op, gtensor, slayout, num_multicast, cta_v_tile);
432
+ }
433
+
434
+ template <class TmaInternalType = void,
435
+ class CopyOp,
436
+ class GEngine, class GLayout,
437
+ class SLayout,
438
+ class MMA_Tiler,
439
+ class... Args,
440
+ class ClusterShapeVMNK>
441
+ CUTE_HOST
442
+ auto
443
+ make_tma_atom_B_sm100(CopyOp const& copy_op,
444
+ Tensor<GEngine,GLayout> const& gtensor, // (N, K, ...)
445
+ SLayout const& slayout, // (MMA, MMA_N, MMA_K, ...)
446
+ MMA_Tiler const& mma_tiler, // (TILE_M, TILE_N, TILE_K, ...)
447
+ TiledMMA<Args...> const& mma,
448
+ ClusterShapeVMNK const& cluster_shape) // (CTA_V, CTA_M, CTA_N, CTA_K)
449
+ {
450
+ // Keep only NK modes from MNK
451
+ auto mma_tiler_nk = remove<0>(mma_tiler);
452
+ // cluster tile coord -> gtensor coord
453
+ auto g_tile = make_identity_layout(shape(gtensor)).compose(mma_tiler_nk); // (TILE_N, TILE_K, ...)
454
+ // cta val idx -> gmem mode
455
+ auto cta_v_tile = layout<1>(mma.thrfrg_B(g_tile))(_, repeat<rank(g_tile)>(_)); // (MMA, MMA_N, MMA_K, ...)
456
+
457
+ #if 0
458
+ print("(tma_b) slayout: "); print(slayout); print("\n");
459
+ print("(tma_b) mma_tiler_nk: "); print(mma_tiler_nk); print("\n");
460
+ print("(tma_b) g_tile: "); print(g_tile); print("\n");
461
+ print("(tma_b) mma_tiler: "); print(mma_tiler); print("\n");
462
+ print("(tma_b) cta_v_tile: "); print(cta_v_tile); print("\n");
463
+ #endif
464
+
465
+ // The size of the multicasting
466
+ auto num_multicast = [&](){
467
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD_MULTICAST> ||
468
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD_MULTICAST>) {
469
+ return size<1>(cluster_shape); // VMNK: Use only the M-CTAs in the Multicast
470
+ } else
471
+ if constexpr (is_same_v<CopyOp, SM90_TMA_LOAD> ||
472
+ is_same_v<CopyOp, SM90_TMA_STORE> ||
473
+ is_same_v<CopyOp, SM100_TMA_2SM_LOAD>) {
474
+ return Int<1>{}; // VMNK: Use no CTAs in Non-Multicast
475
+ } else {
476
+ static_assert(dependent_false<CopyOp>, "Unsupported TMA");
477
+ }
478
+ }();
479
+
480
+ // Prefer TmaInternalType if specified. Fallback to GEngine::value_type
481
+ using TmaType = conditional_t<is_same<void, TmaInternalType>::value, typename GEngine::value_type, TmaInternalType>;
482
+ return detail::make_tma_copy_atom<TmaType>(copy_op, gtensor, slayout, num_multicast, cta_v_tile);
483
+ }
484
+
485
+ #endif // !defined(__CUDACC_RTC__)
486
+
487
+ } // end namespace cute