@@ -197,25 +197,55 @@ __global__ void split_q_block(const int *__restrict__ seq_lens_q,
197197 const int *__restrict__ seq_lens_encoder,
198198 int *__restrict__ batch_ids,
199199 int *__restrict__ tile_ids_per_batch,
200- int *__restrict__ num_blocks_x, const int bsz,
200+ int *__restrict__ num_blocks_x,
201+ const int bsz,
201202 const int num_rows_per_block,
202203 const int group_size) {
203- if (threadIdx .x == 0 ) {
204- int gridx = 0 ;
205- int index = 0 ;
206- for (uint32_t bid = 0 ; bid < bsz; bid++) {
204+ // one block one warp
205+ const int lane_id = threadIdx .x % warpSize ;
206+ int prev_offset = 0 ;
207+
208+ // loop on warp tile:[base, base+32)
209+ for (int base = 0 ; base < bsz; base += warpSize ) {
210+ const int bid = base + lane_id;
211+
212+ // calculate loop_times for bid
213+ int loop_times = 0 ;
214+ if (bid < bsz) {
207215 int seq_len = seq_lens_q[bid];
208216 if (seq_lens_encoder && seq_lens_encoder[bid] > 0 ) {
209217 seq_len = 0 ;
210218 }
211- const int loop_times = div_up (seq_len * group_size, num_rows_per_block);
212- for (uint32_t tile_id = 0 ; tile_id < loop_times; tile_id++) {
213- batch_ids[index] = bid;
214- tile_ids_per_batch[index++] = tile_id;
219+ loop_times = div_up (seq_len * group_size, num_rows_per_block);
220+ }
221+
222+ // prefix sum for each lane, get the start offset in this tile
223+ // inclusive scan
224+ int x = loop_times;
225+ for (int offset = 1 ; offset < warpSize ; offset <<= 1 ) {
226+ int y = __shfl_up_sync (0xffffffff , x, offset);
227+ if (lane_id >= offset) x += y;
228+ }
229+ // exclusive prefix sum
230+ int bid_offset = x - loop_times;
231+ int tile_sum = __shfl_sync (0xffffffff , x, warpSize - 1 );
232+
233+ // write batch_ids and tile_ids_per_batch
234+ if (bid < bsz && loop_times > 0 ) {
235+ int write_base = prev_offset + bid_offset;
236+ for (int t = 0 ; t < loop_times; ++t) {
237+ int pos = write_base + t;
238+ batch_ids[pos] = bid;
239+ tile_ids_per_batch[pos] = t;
215240 }
216- gridx += loop_times;
217241 }
218- *num_blocks_x = gridx;
242+
243+ // for next warp tile
244+ prev_offset += tile_sum;
245+ }
246+
247+ if (threadIdx .x == 0 ) {
248+ *num_blocks_x = prev_offset;
219249 }
220250}
221251
0 commit comments