53 BATCHLAS_KERNEL_TRACE_SCOPE(
"syrk_cuda_custom.gram_tiles");
55 static_assert(NTile % ThreadTile == 0,
"the thread grid has to tile the output exactly");
56 static_assert(ThreadTile % 4 == 0,
"fragments are loaded as 4-wide bands");
57 static_assert(KC % 4 == 0,
"staging moves whole packets");
59 constexpr int Lanes = NTile / ThreadTile;
60 constexpr int TriTiles = Lanes * (Lanes + 1) / 2;
61 constexpr int Threads = ((TriTiles + 31) / 32) * 32;
62 constexpr int SPad = NTile;
63 constexpr int Bands = ThreadTile / 4;
64 constexpr int Packs = NTile / 4;
65 constexpr int SwizzleMask = Packs - 1;
66 constexpr int Packets = KC * Packs;
67 static_assert((Packs & SwizzleMask) == 0,
"the swizzle needs a power-of-two packet count");
69 const int n =
static_cast<int>(C.
rows());
70 const int k = TransOperand ?
static_cast<int>(A.
rows()) :
static_cast<int>(A.
cols());
76 const sycl::range<2> local(1,
static_cast<size_t>(Threads));
77 const sycl::range<2> global(
static_cast<size_t>(batch),
static_cast<size_t>(Threads));
79 impl::check_group_count(*ctx, sycl::nd_range<2>(global, local));
80 ctx->submit([&](sycl::handler& h) {
81 sycl::local_accessor<T, 1> tile(sycl::range<1>(KC * SPad), h);
85 const int lda = A.
ld();
86 const int ldc = C.
ld();
87 const int stride_a = A.
stride();
88 const int stride_c = C.
stride();
91 batchlas::impl::parallel_for<SyrkGramTilesKernel<T, NTile, ThreadTile, KC, TransOperand, Conjugate>>(h,
92 sycl::nd_range<2>(global, local), [=](sycl::nd_item<2> item) {
93 const int bid =
static_cast<int>(item.get_group(0));
97 const int tid =
static_cast<int>(item.get_local_id(1));
98 const bool active = tid < TriTiles;
102 triangular_tile_decode(active ? tid : 0, bi, bj);
103 const int tr = lower ? bi : bj;
104 const int tc = lower ? bj : bi;
106 const T* Ab = a_ptr +
static_cast<std::ptrdiff_t
>(bid) * stride_a;
107 T* Cb = c_ptr +
static_cast<std::ptrdiff_t
>(bid) * stride_c;
108 T* sh = tile.template get_multi_ptr<sycl::access::decorated::no>().get();
113 auto swizzle = [](
int packet,
int kk) {
114 return packet ^ ((kk >> 2) & SwizzleMask);
117 T accum[ThreadTile][ThreadTile];
119 for (
int i = 0; i < ThreadTile; ++i) {
121 for (
int j = 0; j < ThreadTile; ++j) {
126 for (
int k0 = 0; k0 < k; k0 += KC) {
128 if constexpr (TransOperand) {
130 for (
int flat = tid; flat < Packets; flat += Threads) {
131 const int col = flat / (KC / 4);
132 const int kk0 = (flat % (KC / 4)) * 4;
133 const bool col_ok = col < n;
134 const int phys = (swizzle(col >> 2, kk0) << 2) | (col & 3);
136 for (
int i = 0; i < 4; ++i) {
137 const int gk = k0 + kk0 + i;
138 sh[(kk0 + i) * SPad + phys] =
140 ? Ab[gk +
static_cast<std::ptrdiff_t
>(col) * lda]
145 for (
int flat = tid; flat < Packets; flat += Threads) {
146 const int kk = flat / Packs;
147 const int col0 = (flat % Packs) * 4;
148 const int gk = k0 + kk;
149 const bool k_ok = gk < k;
150 const int phys = swizzle(col0 >> 2, kk) << 2;
152 for (
int i = 0; i < 4; ++i) {
153 const int col = col0 + i;
154 sh[kk * SPad + phys + i] =
156 ? Ab[col +
static_cast<std::ptrdiff_t
>(gk) * lda]
161 item.barrier(sycl::access::fence_space::local_space);
165 for (
int p = 0; p < KC; ++p) {
166 const T* row = &sh[p * SPad];
170 for (
int b = 0; b < Bands; ++b) {
175 const int qa = swizzle(tr * Bands + b, p);
176 const int qb = swizzle(tc * Bands + b, p);
177 const TileVec4<T> va = tile_load4(row + qa * 4);
178 const TileVec4<T> vb = tile_load4(row + qb * 4);
180 for (
int e = 0; e < 4; ++e) {
184 if constexpr (Conjugate) {
188 af[b * 4 + e] = va.v[e];
189 bf[b * 4 + e] = vb.v[e];
194 for (
int i = 0; i < ThreadTile; ++i) {
196 for (
int j = 0; j < ThreadTile; ++j) {
197 accum[i][j] = accumulate(accum[i][j], af[i], bf[j]);
202 item.barrier(sycl::access::fence_space::local_space);
211 const bool on_diagonal = bi == bj;
213 for (
int j = 0; j < ThreadTile; ++j) {
214 const int col = tc * ThreadTile + j;
219 for (
int i = 0; i < ThreadTile; ++i) {
220 const int row = tr * ThreadTile + i;
224 if (on_diagonal && (lower ? row < col : row > col)) {
227 T* p = &Cb[row +
static_cast<std::ptrdiff_t
>(col) * ldc];
228 T value = beta == T(0) ? alpha * accum[i][j]
229 : alpha * accum[i][j] + beta * *p;
231 if constexpr (Conjugate) {