Skip to content

Commit 5bb00c9

Browse files
authored
perf(hip): speed up PFlash compression with rocWMMA FlashPrefill (#456)
1 parent c0beb2a commit 5bb00c9

1 file changed

Lines changed: 35 additions & 9 deletions

File tree

server/src/flashprefill_kernels.hip.cu

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)