@@ -259,15 +259,20 @@ __global__ void compute_block_score_gemm_kernel(
259259 mma_sync (c_frag, a_frag, b_frag, c_frag);
260260 }
261261
262+ __shared__ float c_stage[16 * 16 ];
263+ store_matrix_sync (c_stage, c_frag, 16 , mem_row_major);
264+ __syncthreads ();
265+
262266 // Write: AMD Wave32 layout lane t, elem i → row = t%16, col = (t/16)*8 + i
263267 const int lane = threadIdx .x ;
264268 const int r_base = m_tile * 16 + (lane % 16 );
265269 const int c_base = n_tile * 16 + (lane / 16 ) * 8 ;
270+ const float * c_row = c_stage + (size_t )(lane % 16 ) * 16 + (lane / 16 ) * 8 ;
266271 float * Sp = score + (size_t )b * s_S_b + (size_t )qh * s_S_h;
267272 #pragma unroll
268273 for (int i = 0 ; i < 8 ; ++i) {
269274 if (r_base < M && c_base + i < M)
270- Sp[(size_t )r_base * s_S_m + (size_t )(c_base + i) * s_S_n] = c_frag [i] * sm_scale;
275+ Sp[(size_t )r_base * s_S_m + (size_t )(c_base + i) * s_S_n] = c_row [i] * sm_scale;
271276 }
272277}
273278
@@ -438,20 +443,28 @@ __global__ void sparse_flash_forward_kernel_bf16(
438443 }
439444 }
440445
441- // ── Causal mask + rowmax (AMD RDNA3 layout) ──
442- // lane t: row = t%16, col = (t/16)*8 + elem_i
446+ // ── Causal mask + rowmax ──
447+ // Store accumulator fragments through rocWMMA's public API before
448+ // scalar reads; direct fragment element layout is implementation-specific.
443449 const int row_g = q_tile_idx * Q_TILE + wid * MMA_M + row_in_warp;
450+ float * s_stage = reinterpret_cast <float *>(KV_sh);
444451 float lm = -INFINITY ;
445452 #pragma unroll
446453 for (int nt = 0 ; nt < NNK ; ++nt) {
454+ store_matrix_sync (s_stage + (size_t )(wid * MMA_M ) * MMA_N ,
455+ S_frag[nt], MMA_N , mem_row_major);
456+ __syncthreads ();
457+ const float * s_row = s_stage + (size_t )(wid * MMA_M + row_in_warp) * MMA_N
458+ + col_half * 8 ;
447459 #pragma unroll
448460 for (int i = 0 ; i < 8 ; ++i) {
449461 const int col_g = k_lo + nt * MMA_N + col_half * 8 + i;
450462 bool valid = (col_g < seq_len);
451463 if (is_diag) valid = valid && (col_g <= row_g);
452- if (! valid) S_frag[nt][ i] = -INFINITY ;
453- lm = fmaxf (lm, S_frag[nt][i] );
464+ const float v = valid ? s_row[ i] : -INFINITY ;
465+ lm = fmaxf (lm, v );
454466 }
467+ __syncthreads ();
455468 }
456469 // Merge rowmax: lane t and t+16 own the same row; shfl_xor(16) swaps them.
457470 lm = fmaxf (lm, __shfl_xor (lm, 16 ));
@@ -467,14 +480,23 @@ __global__ void sparse_flash_forward_kernel_bf16(
467480 float rs = 0 .0f ;
468481 #pragma unroll
469482 for (int nt = 0 ; nt < NNK ; ++nt) {
483+ store_matrix_sync (s_stage + (size_t )(wid * MMA_M ) * MMA_N ,
484+ S_frag[nt], MMA_N , mem_row_major);
485+ __syncthreads ();
486+ const float * s_row = s_stage + (size_t )(wid * MMA_M + row_in_warp) * MMA_N
487+ + col_half * 8 ;
470488 #pragma unroll
471489 for (int i = 0 ; i < 8 ; ++i) {
472- const float v = S_frag[nt][i];
490+ const int col_g = k_lo + nt * MMA_N + col_half * 8 + i;
491+ bool valid = (col_g < seq_len);
492+ if (is_diag) valid = valid && (col_g <= row_g);
493+ const float v = valid ? s_row[i] : -INFINITY ;
473494 const float p = (v == -INFINITY ) ? 0 .0f : exp2f (v - m_new);
474495 rs += p;
475496 const int col_k = nt * MMA_N + col_half * 8 + i;
476497 P_sh[(size_t )(wid * MMA_M + row_in_warp) * K_TILE + col_k] = hip_bfloat16 (p);
477498 }
499+ __syncthreads ();
478500 }
479501 // Merge rowsum across the two lane-halves sharing a row
480502 rs += __shfl_xor (rs, 16 );
@@ -485,12 +507,16 @@ __global__ void sparse_flash_forward_kernel_bf16(
485507 row_l[row_warp] = alpha * l_old + rs;
486508 }
487509
488- // Rescale O accumulator (all 8 elements per lane belong to the same row)
510+ // Rescale O accumulator in registers. rocWMMA accumulator element
511+ // access is valid for mutation on ROCm 7.2.4 gfx1151 and avoids a
512+ // store/sync/load round trip per output D tile.
489513 #pragma unroll
490- for (int d = 0 ; d < NDK ; ++d)
514+ for (int d = 0 ; d < NDK ; ++d) {
491515 #pragma unroll
492- for (int i = 0 ; i < 8 ; ++i)
516+ for (int i = 0 ; i < 8 ; ++i) {
493517 O_frag[d][i] *= alpha;
518+ }
519+ }
494520
495521 __syncthreads (); // P_sh writes visible before V load overwrites KV_sh
496522
0 commit comments