Skip to content

Commit 00fa7cb

Browse files
authored
opencl: handle OOB write in noshuffle GEMV kernels (odd ne01) (ggml-org#25640)
1 parent a4ce259 commit 00fa7cb

11 files changed

Lines changed: 63 additions & 11 deletions

ggml/src/ggml-opencl/kernels/gemv_noshuffle_iq4_nl_f32.cl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,12 @@ kernel void kernel_gemv_noshuffle_iq4_nl_f32(
296296
// 2 outputs per fiber in wave 0
297297
if (groupId == 0) {
298298
dst = (global float*)((global char*)dst + offsetd);
299-
vstore2(totalSum, 0, &(dst[gid * 2]));
299+
// Guard the two output rows. The x-grid is padded to CEIL_DIV(ne01/2,64)*64,
300+
// so when ne01 is not a multiple of 128 the tail row-pairs run past row ne01
301+
// and would overrun dst into the adjacent tensor. No-op / byte-identical when
302+
// ne01 % 128 == 0 (M/2 already a multiple of 64 -> no padding).
303+
if (gid * 2 + 0 < M) dst[gid * 2 + 0] = totalSum.s0;
304+
if (gid * 2 + 1 < M) dst[gid * 2 + 1] = totalSum.s1;
300305
}
301306

302307
}

ggml/src/ggml-opencl/kernels/gemv_noshuffle_q1_0_f32.cl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ __kernel void kernel_gemv_noshuffle_q1_0_f32(
116116

117117
if (groupId == 0) {
118118
dst = (global float*)((global char*)dst + offsetd);
119-
dst[gid] = totalSum;
119+
// Guard the output row. The x-grid is padded to CEIL_DIV(M,wavesize)*wavesize,
120+
// so when ne01 is not a multiple of the wave size the tail work-items run past
121+
// row ne01 and would overrun dst into the adjacent tensor. No-op / byte-identical
122+
// when ne01 is wave-aligned (no padding).
123+
if (gid < M) dst[gid] = totalSum;
120124
}
121125
}

ggml/src/ggml-opencl/kernels/gemv_noshuffle_q4_0_f32.cl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,12 @@ __kernel void kernel_gemv_noshuffle_q4_0_f32(
268268
// 2 outputs per fiber in wave 0
269269
if (groupId == 0) {
270270
dst = (global float*)((global char*)dst + offsetd);
271-
vstore2(totalSum, 0, &(dst[gid * 2]));
271+
// Guard the two output rows. The x-grid is padded to CEIL_DIV(ne01/2,64)*64,
272+
// so when ne01 is not a multiple of 128 the tail row-pairs run past row ne01
273+
// and would overrun dst into the adjacent tensor. No-op / byte-identical when
274+
// ne01 % 128 == 0 (M/2 already a multiple of 64 -> no padding).
275+
if (gid * 2 + 0 < M) dst[gid * 2 + 0] = totalSum.s0;
276+
if (gid * 2 + 1 < M) dst[gid * 2 + 1] = totalSum.s1;
272277
}
273278

274279
}

ggml/src/ggml-opencl/kernels/gemv_noshuffle_q4_0_f32_spec.cl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,11 @@ __kernel void kernel_gemv_noshuffle_q4_0_f32(
262262
// 2 outputs per fiber in wave 0
263263
if (groupId == 0) {
264264
dst = (global float*)((global char*)dst + offsetd);
265-
vstore2(totalSum, 0, &(dst[gid * 2]));
265+
// Guard the two output rows against the padded x-grid tail overrunning dst.
266+
// The current shape specializations are all ne01 % 128 == 0 (no padding), so
267+
// this is a no-op / byte-identical today; keep it in lockstep with the base kernel.
268+
if (gid * 2 + 0 < ne01) dst[gid * 2 + 0] = totalSum.s0;
269+
if (gid * 2 + 1 < ne01) dst[gid * 2 + 1] = totalSum.s1;
266270
}
267271

268272
}

ggml/src/ggml-opencl/kernels/gemv_noshuffle_q4_1_f32.cl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,12 @@ kernel void kernel_gemv_noshuffle_q4_1_f32(
277277
// 2 outputs per fiber in wave 0
278278
if (groupId == 0) {
279279
dst = (global float*)((global char*)dst + offsetd);
280-
vstore2(totalSum, 0, &(dst[gid * 2]));
280+
// Guard the two output rows. The x-grid is padded to CEIL_DIV(ne01/2,64)*64,
281+
// so when ne01 is not a multiple of 128 the tail row-pairs run past row ne01
282+
// and would overrun dst into the adjacent tensor. No-op / byte-identical when
283+
// ne01 % 128 == 0 (M/2 already a multiple of 64 -> no padding).
284+
if (gid * 2 + 0 < M) dst[gid * 2 + 0] = totalSum.s0;
285+
if (gid * 2 + 1 < M) dst[gid * 2 + 1] = totalSum.s1;
281286
}
282287

283288
}

ggml/src/ggml-opencl/kernels/gemv_noshuffle_q4_k_f32.cl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,12 @@ kernel void kernel_gemv_noshuffle_q4_k_f32(
312312
// 2 outputs per fiber in wave 0
313313
if (groupId == 0) {
314314
dst = (global float*)((global char*)dst + offsetd);
315-
vstore2(totalSum, 0, &(dst[gid * 2]));
315+
// Guard the two output rows. The x-grid is padded to CEIL_DIV(ne01/2,64)*64,
316+
// so when ne01 is not a multiple of 128 the tail row-pairs run past row ne01
317+
// and would overrun dst into the adjacent tensor. No-op / byte-identical when
318+
// ne01 % 128 == 0 (M/2 already a multiple of 64 -> no padding).
319+
if (gid * 2 + 0 < M) dst[gid * 2 + 0] = totalSum.s0;
320+
if (gid * 2 + 1 < M) dst[gid * 2 + 1] = totalSum.s1;
316321
}
317322

318323
}

ggml/src/ggml-opencl/kernels/gemv_noshuffle_q5_0_f32.cl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,12 @@ __kernel void kernel_gemv_noshuffle_q5_0_f32(
285285
// 2 outputs per fiber in wave 0
286286
if (groupId == 0) {
287287
dst = (global float*)((global char*)dst + offsetd);
288-
vstore2(totalSum, 0, &(dst[gid * 2]));
288+
// Guard the two output rows. The x-grid is padded to CEIL_DIV(ne01/2,64)*64,
289+
// so when ne01 is not a multiple of 128 the tail row-pairs run past row ne01
290+
// and would overrun dst into the adjacent tensor. No-op / byte-identical when
291+
// ne01 % 128 == 0 (M/2 already a multiple of 64 -> no padding).
292+
if (gid * 2 + 0 < M) dst[gid * 2 + 0] = totalSum.s0;
293+
if (gid * 2 + 1 < M) dst[gid * 2 + 1] = totalSum.s1;
289294
}
290295

291296
}

ggml/src/ggml-opencl/kernels/gemv_noshuffle_q5_1_f32.cl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,12 @@ __kernel void kernel_gemv_noshuffle_q5_1_f32(
288288
// 2 outputs per fiber in wave 0
289289
if (groupId == 0) {
290290
dst = (global float*)((global char*)dst + offsetd);
291-
vstore2(totalSum, 0, &(dst[gid * 2]));
291+
// Guard the two output rows. The x-grid is padded to CEIL_DIV(ne01/2,64)*64,
292+
// so when ne01 is not a multiple of 128 the tail row-pairs run past row ne01
293+
// and would overrun dst into the adjacent tensor. No-op / byte-identical when
294+
// ne01 % 128 == 0 (M/2 already a multiple of 64 -> no padding).
295+
if (gid * 2 + 0 < M) dst[gid * 2 + 0] = totalSum.s0;
296+
if (gid * 2 + 1 < M) dst[gid * 2 + 1] = totalSum.s1;
292297
}
293298

294299
}

ggml/src/ggml-opencl/kernels/gemv_noshuffle_q5_k_f32.cl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,11 @@ kernel void kernel_gemv_noshuffle_q5_k_f32(
321321
// 2 outputs per fiber in wave 0
322322
if (groupId == 0) {
323323
dst = (global float*)((global char*)dst + offsetd);
324-
vstore2(totalSum, 0, &(dst[gid * 2]));
324+
// Guard the two output rows. The x-grid is padded to CEIL_DIV(ne01/2,64)*64,
325+
// so when ne01 is not a multiple of 128 the tail row-pairs run past row ne01
326+
// and would overrun dst into the adjacent tensor. No-op / byte-identical when
327+
// ne01 % 128 == 0 (M/2 already a multiple of 64 -> no padding).
328+
if (gid * 2 + 0 < M) dst[gid * 2 + 0] = totalSum.s0;
329+
if (gid * 2 + 1 < M) dst[gid * 2 + 1] = totalSum.s1;
325330
}
326331
}

ggml/src/ggml-opencl/kernels/gemv_noshuffle_q6_k_f32.cl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,11 @@ kernel void kernel_gemv_noshuffle_q6_K_f32(
288288

289289
if (grp == 0) {
290290
dst = (global float*)((global char*)dst + offsetd);
291-
vstore2(total_sum, 0, &(dst[gid * 2]));
291+
// Guard the two output rows. The x-grid is padded to CEIL_DIV(ne01/2,64)*64,
292+
// so when ne01 is not a multiple of 128 the tail row-pairs run past row ne01
293+
// and would overrun dst into the adjacent tensor (garbage downstream).
294+
// No-op / byte-identical when ne01 % 128 == 0 (no padding).
295+
if (gid * 2 + 0 < ne01) dst[gid * 2 + 0] = total_sum.s0;
296+
if (gid * 2 + 1 < ne01) dst[gid * 2 + 1] = total_sum.s1;
292297
}
293298
}

0 commit comments

Comments
 (0)