Skip to content

Commit 29a6ed1

Browse files
committed
fix merge
1 parent bd43656 commit 29a6ed1

1 file changed

Lines changed: 28 additions & 25 deletions

File tree

custom_ops/gpu_ops/append_attention/attention_func.cuh

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,33 +1141,36 @@ __global__ void merge_chunks_kernel(
11411141
// Step 2: Intra-warp reduction via warp shuffle
11421142
// Each warp has 2 ty values: ty_low at lanes 0-15, ty_high at lanes 16-31
11431143
// Merge ty_high into ty_low using shuffle
1144-
{
1145-
// Determine the partner ty in the same warp
1146-
// ty_low = ty & ~1, ty_high = ty | 1
1147-
const int partner_lane = lane_id ^ 16; // flip bit 4 to swap low/high ty
1148-
const float m_partner = __shfl_sync(0xffffffff, m, partner_lane);
1149-
const float d_partner = __shfl_sync(0xffffffff, d, partner_lane);
1150-
LoadT partner_vec;
1144+
const int partner_lane = lane_id ^ 16; // flip bit 4 to swap low/high ty
1145+
const float m_partner = __shfl_sync(0xffffffff, m, partner_lane);
1146+
const float d_partner = __shfl_sync(0xffffffff, d, partner_lane);
1147+
// Pack adjacent 16-bit pairs into 32-bit for efficient shuffle.
1148+
// AlignedVector alignment >= 4 bytes, so uint32 reinterpret is safe
1149+
// — no OOB read, no type confusion. This halves shuffle count vs
1150+
// per-element memcpy for bf16/fp16.
1151+
constexpr int PACKED_SIZE = vec_size * sizeof(T) / sizeof(unsigned);
1152+
const unsigned* packed_res = reinterpret_cast<const unsigned*>(&res_vec);
1153+
unsigned packed_partner[PACKED_SIZE];
1154+
#pragma unroll
1155+
for (int j = 0; j < PACKED_SIZE; j++) {
1156+
packed_partner[j] = __shfl_sync(0xffffffff, packed_res[j], partner_lane);
1157+
}
1158+
LoadT partner_vec;
1159+
memcpy(&partner_vec, packed_partner, sizeof(partner_vec));
1160+
1161+
// Merge partner into self (only the "low ty" keeps the result)
1162+
float m_new = max(m, m_partner);
1163+
const float scale1 = __expf(m - m_new);
1164+
const float scale2 = __expf(m_partner - m_new);
1165+
float d_new = d * scale1 + d_partner * scale2;
1166+
if ((ty & 1) == 0) { // low ty keeps merged result
1167+
m = m_new;
1168+
d = d_new;
1169+
const T scale1_T = static_cast<T>(scale1);
1170+
const T scale2_T = static_cast<T>(scale2);
11511171
#pragma unroll
11521172
for (int j = 0; j < vec_size; j++) {
1153-
partner_vec[j] = __shfl_sync(
1154-
0xffffffff, reinterpret_cast<unsigned&>(res_vec[j]), partner_lane);
1155-
}
1156-
1157-
// Merge partner into self (only the "low ty" keeps the result)
1158-
float m_new = max(m, m_partner);
1159-
const float scale1 = __expf(m - m_new);
1160-
const float scale2 = __expf(m_partner - m_new);
1161-
float d_new = d * scale1 + d_partner * scale2;
1162-
if ((ty & 1) == 0) { // low ty keeps merged result
1163-
m = m_new;
1164-
d = d_new;
1165-
const T scale1_T = static_cast<T>(scale1);
1166-
const T scale2_T = static_cast<T>(scale2);
1167-
#pragma unroll
1168-
for (int j = 0; j < vec_size; j++) {
1169-
res_vec[j] = res_vec[j] * scale1_T + partner_vec[j] * scale2_T;
1170-
}
1173+
res_vec[j] = res_vec[j] * scale1_T + partner_vec[j] * scale2_T;
11711174
}
11721175
}
11731176

0 commit comments

Comments
 (0)