Skip to content

Commit aee2651

Browse files
committed
opencl: never enqueue a zero-size NDRange
clEnqueueNDRangeKernel returns CL_INVALID_GLOBAL_WORK_SIZE if any global_work_size[i] is 0, and the CL_CHECK around it aborts the process. Most drivers accept a zero-size range and do nothing, so the bug is invisible on them; strict drivers enforce the spec and take the process down. This is a spec violation on our side, not a device quirk. Skip the enqueue when any global dimension is zero, at the single choke point all dispatches funnel through. A dimension that is wrongly zero still surfaces as a wrong result rather than being masked. Scope was established by running the op suite on an UNGUARDED build: of the 74 ops in test-backend-ops, SET_ROWS is the only one that emits a zero-size dispatch (a row-less tensor, ne01 == 0). Verified on device: Adreno 619 aborted at SET_ROWS(f32->f32,i64,ne=[33,5,1,1],nr23=[2,3]) -> runs Adreno 642L same abort -> runs Adreno 840 op suite unchanged (lax driver, never hit the path) Adreno 740 op suite unchanged
1 parent ec2ad85 commit aee2651

1 file changed

Lines changed: 12 additions & 0 deletions

File tree

ggml/src/ggml-opencl/ggml-opencl.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,6 +1066,17 @@ struct ggml_backend_opencl_context {
10661066
}
10671067

10681068
void enqueue_ndrange_kernel(cl_kernel kernel, cl_uint work_dim, size_t *global_work_size, size_t *local_work_size, const ggml_tensor * tensor) {
1069+
// An empty range is a no-op, but the spec says a zero global size is
1070+
// CL_INVALID_GLOBAL_WORK_SIZE, so enqueuing it is an error rather than nothing. Most
1071+
// drivers return CL_SUCCESS and do nothing; strict drivers (Adreno 642L, 619) return
1072+
// -63 and the CL_CHECK below aborts the process. Skip it, which is what every other
1073+
// driver effectively does. A dimension that is wrongly zero still shows up as a wrong
1074+
// result. Check first, before the profiling path, so no mode enqueues it.
1075+
for (cl_uint i = 0; i < work_dim; i++) {
1076+
if (global_work_size[i] == 0) {
1077+
return;
1078+
}
1079+
}
10691080
#ifdef GGML_OPENCL_PROFILING
10701081
cl_event evt;
10711082
CL_CHECK(clEnqueueNDRangeKernel(queue, kernel, work_dim, NULL, global_work_size, local_work_size, 0, NULL, &evt));
@@ -11977,6 +11988,7 @@ static void ggml_cl_set_rows(ggml_backend_t backend, const ggml_tensor * src0, c
1197711988
(size_t)ne03};
1197811989
size_t local_work_size[] = {(size_t)nth0, (size_t)rows_per_workgroup, 1};
1197911990

11991+
// ne01 == 0 makes global_work_size[0] zero here; enqueue_ndrange_kernel drops the empty range.
1198011992
backend_ctx->enqueue_ndrange_kernel(kernel, 3, global_work_size, local_work_size, dst);
1198111993
}
1198211994

0 commit comments

Comments
 (0)