Skip to content

Commit 3ceb6d9

Browse files
committed
Error if number of dimensions changes during update
See KhronosGroup/OpenCL-Docs#1057 for discussions as to why we shouldn't enable changing to number of dimensions in an update.
1 parent be61020 commit 3ceb6d9

File tree

9 files changed

+128
-86
lines changed

9 files changed

+128
-86
lines changed

include/ur_api.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8532,6 +8532,7 @@ urCommandBufferReleaseCommandExp(
85328532
/// - ::UR_RESULT_ERROR_INVALID_OPERATION
85338533
/// + If ::ur_exp_command_buffer_desc_t::isUpdatable was not set to true on creation of the command buffer `hCommand` belongs to.
85348534
/// + If the command-buffer `hCommand` belongs to has not been finalized.
8535+
/// + If `pUpdateKernelLaunch->newWorkDim` is different from the work-dim used on creation of `hCommand`.
85358536
/// - ::UR_RESULT_ERROR_INVALID_COMMAND_BUFFER_COMMAND_HANDLE_EXP
85368537
/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT
85378538
/// - ::UR_RESULT_ERROR_INVALID_KERNEL_ARGUMENT_INDEX

scripts/core/exp-command-buffer.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,7 @@ returns:
926926
- $X_RESULT_ERROR_INVALID_OPERATION:
927927
- "If $x_exp_command_buffer_desc_t::isUpdatable was not set to true on creation of the command buffer `hCommand` belongs to."
928928
- "If the command-buffer `hCommand` belongs to has not been finalized."
929+
- "If `pUpdateKernelLaunch->newWorkDim` is different from the work-dim used on creation of `hCommand`."
929930
- $X_RESULT_ERROR_INVALID_COMMAND_BUFFER_COMMAND_HANDLE_EXP
930931
- $X_RESULT_ERROR_INVALID_MEM_OBJECT
931932
- $X_RESULT_ERROR_INVALID_KERNEL_ARGUMENT_INDEX

source/adapters/cuda/command_buffer.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,13 @@ UR_APIEXPORT ur_result_t UR_APICALL urCommandBufferUpdateKernelLaunchExp(
867867
return UR_RESULT_ERROR_INVALID_OPERATION;
868868
}
869869

870+
// Error if work dim changes
871+
if (auto NewWorkDim = pUpdateKernelLaunch->newWorkDim) {
872+
if (NewWorkDim != hCommand->WorkDim) {
873+
return UR_RESULT_ERROR_INVALID_OPERATION;
874+
}
875+
}
876+
870877
// Kernel corresponding to the command to update
871878
ur_kernel_handle_t Kernel = hCommand->Kernel;
872879

source/adapters/opencl/command_buffer.cpp

Lines changed: 70 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -437,30 +437,14 @@ UR_APIEXPORT ur_result_t UR_APICALL urCommandBufferReleaseCommandExp(
437437
return commandHandleReleaseInternal(hCommand);
438438
}
439439

440-
UR_APIEXPORT ur_result_t UR_APICALL urCommandBufferUpdateKernelLaunchExp(
441-
ur_exp_command_buffer_command_handle_t hCommand,
440+
namespace {
441+
ur_result_t updateKernelExecInfo(
442+
std::vector<cl_mutable_dispatch_exec_info_khr> &CLExecInfos,
442443
const ur_exp_command_buffer_update_kernel_launch_desc_t
443444
*pUpdateKernelLaunch) {
444-
445-
ur_exp_command_buffer_handle_t hCommandBuffer = hCommand->hCommandBuffer;
446-
cl_context CLContext = cl_adapter::cast<cl_context>(hCommandBuffer->hContext);
447-
cl_ext::clUpdateMutableCommandsKHR_fn clUpdateMutableCommandsKHR = nullptr;
448-
cl_int Res =
449-
cl_ext::getExtFuncFromContext<decltype(clUpdateMutableCommandsKHR)>(
450-
CLContext, cl_ext::ExtFuncPtrCache->clUpdateMutableCommandsKHRCache,
451-
cl_ext::UpdateMutableCommandsName, &clUpdateMutableCommandsKHR);
452-
453-
if (!clUpdateMutableCommandsKHR || Res != CL_SUCCESS)
454-
return UR_RESULT_ERROR_INVALID_OPERATION;
455-
456-
if (!hCommandBuffer->IsFinalized || !hCommandBuffer->IsUpdatable)
457-
return UR_RESULT_ERROR_INVALID_OPERATION;
458-
459-
// Find the CL execution info to update
460445
const uint32_t NumExecInfos = pUpdateKernelLaunch->numNewExecInfos;
461446
const ur_exp_command_buffer_update_exec_info_desc_t *ExecInfoList =
462447
pUpdateKernelLaunch->pNewExecInfoList;
463-
std::vector<cl_mutable_dispatch_exec_info_khr> CLExecInfos;
464448
for (uint32_t i = 0; i < NumExecInfos; i++) {
465449
const ur_exp_command_buffer_update_exec_info_desc_t &URExecInfo =
466450
ExecInfoList[i];
@@ -488,32 +472,41 @@ UR_APIEXPORT ur_result_t UR_APICALL urCommandBufferUpdateKernelLaunchExp(
488472
return UR_RESULT_ERROR_INVALID_ENUMERATION;
489473
}
490474
}
475+
return UR_RESULT_SUCCESS;
476+
}
477+
478+
void updateKernelPointerArgs(
479+
std::vector<cl_mutable_dispatch_arg_khr> &CLUSMArgs,
480+
const ur_exp_command_buffer_update_kernel_launch_desc_t
481+
*pUpdateKernelLaunch) {
491482

492-
// Find the CL USM pointer arguments to the kernel.
493483
// WARNING - This relies on USM and SVM using the same implementation,
494484
// which is not guaranteed.
495485
// See https://github.com/KhronosGroup/OpenCL-Docs/issues/843
496486
const uint32_t NumPointerArgs = pUpdateKernelLaunch->numNewPointerArgs;
497487
const ur_exp_command_buffer_update_pointer_arg_desc_t *ArgPointerList =
498488
pUpdateKernelLaunch->pNewPointerArgList;
499-
std::vector<cl_mutable_dispatch_arg_khr> CLUSMArgs(NumPointerArgs);
489+
490+
CLUSMArgs.resize(NumPointerArgs);
500491
for (uint32_t i = 0; i < NumPointerArgs; i++) {
501492
const ur_exp_command_buffer_update_pointer_arg_desc_t &URPointerArg =
502493
ArgPointerList[i];
503494
cl_mutable_dispatch_arg_khr &USMArg = CLUSMArgs[i];
504495
USMArg.arg_index = URPointerArg.argIndex;
505496
USMArg.arg_value = *(void *const *)URPointerArg.pNewPointerArg;
506497
}
498+
}
507499

508-
// Find the memory object and scalar arguments to the kernel.
500+
void updateKernelArgs(std::vector<cl_mutable_dispatch_arg_khr> &CLArgs,
501+
const ur_exp_command_buffer_update_kernel_launch_desc_t
502+
*pUpdateKernelLaunch) {
509503
const uint32_t NumMemobjArgs = pUpdateKernelLaunch->numNewMemObjArgs;
510504
const ur_exp_command_buffer_update_memobj_arg_desc_t *ArgMemobjList =
511505
pUpdateKernelLaunch->pNewMemObjArgList;
512506
const uint32_t NumValueArgs = pUpdateKernelLaunch->numNewValueArgs;
513507
const ur_exp_command_buffer_update_value_arg_desc_t *ArgValueList =
514508
pUpdateKernelLaunch->pNewValueArgList;
515509

516-
std::vector<cl_mutable_dispatch_arg_khr> CLArgs;
517510
for (uint32_t i = 0; i < NumMemobjArgs; i++) {
518511
const ur_exp_command_buffer_update_memobj_arg_desc_t &URMemObjArg =
519512
ArgMemobjList[i];
@@ -537,45 +530,72 @@ UR_APIEXPORT ur_result_t UR_APICALL urCommandBufferUpdateKernelLaunchExp(
537530
};
538531
CLArgs.push_back(CLArg);
539532
}
533+
}
534+
535+
} // end anonymous namespace
536+
537+
UR_APIEXPORT ur_result_t UR_APICALL urCommandBufferUpdateKernelLaunchExp(
538+
ur_exp_command_buffer_command_handle_t hCommand,
539+
const ur_exp_command_buffer_update_kernel_launch_desc_t
540+
*pUpdateKernelLaunch) {
541+
542+
ur_exp_command_buffer_handle_t hCommandBuffer = hCommand->hCommandBuffer;
543+
cl_context CLContext = cl_adapter::cast<cl_context>(hCommandBuffer->hContext);
544+
cl_ext::clUpdateMutableCommandsKHR_fn clUpdateMutableCommandsKHR = nullptr;
545+
cl_int Res =
546+
cl_ext::getExtFuncFromContext<decltype(clUpdateMutableCommandsKHR)>(
547+
CLContext, cl_ext::ExtFuncPtrCache->clUpdateMutableCommandsKHRCache,
548+
cl_ext::UpdateMutableCommandsName, &clUpdateMutableCommandsKHR);
549+
550+
if (!clUpdateMutableCommandsKHR || Res != CL_SUCCESS)
551+
return UR_RESULT_ERROR_INVALID_OPERATION;
552+
553+
if (!hCommandBuffer->IsFinalized || !hCommandBuffer->IsUpdatable)
554+
return UR_RESULT_ERROR_INVALID_OPERATION;
540555

541556
const cl_uint NewWorkDim = pUpdateKernelLaunch->newWorkDim;
542-
cl_uint &CLWorkDim = hCommand->WorkDim;
543-
if (NewWorkDim != 0 && NewWorkDim != CLWorkDim) {
544-
// Limitation of the cl_khr_command_buffer_mutable_dispatch specification
545-
// that it is an error to change the ND-Range size.
546-
// https://github.com/KhronosGroup/OpenCL-Docs/issues/1057
547-
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
557+
if (NewWorkDim != 0 && NewWorkDim != hCommand->WorkDim) {
558+
return UR_RESULT_ERROR_INVALID_OPERATION;
559+
}
560+
561+
// Find the CL execution info to update
562+
std::vector<cl_mutable_dispatch_exec_info_khr> CLExecInfos;
563+
if (ur_result_t result =
564+
updateKernelExecInfo(CLExecInfos, pUpdateKernelLaunch)) {
565+
return result;
548566
}
549567

550-
// Update the ND-Range configuration of the kernel.
551-
const size_t CopySize = sizeof(size_t) * CLWorkDim;
568+
// Find the CL USM pointer arguments to the kernel to update
569+
std::vector<cl_mutable_dispatch_arg_khr> CLUSMArgs;
570+
updateKernelPointerArgs(CLUSMArgs, pUpdateKernelLaunch);
571+
572+
// Find the memory object and scalar arguments to the kernel to update
573+
std::vector<cl_mutable_dispatch_arg_khr> CLArgs;
574+
575+
updateKernelArgs(CLArgs, pUpdateKernelLaunch);
576+
577+
// Find the updated ND-Range configuration of the kernel.
552578
std::vector<size_t> CLGlobalWorkOffset, CLGlobalWorkSize, CLLocalWorkSize;
579+
cl_uint &CommandWorkDim = hCommand->WorkDim;
580+
581+
// Lambda for N-Dimensional update
582+
auto updateNDRange = [CommandWorkDim](std::vector<size_t> &NDRange,
583+
size_t *UpdatePtr) {
584+
NDRange.resize(CommandWorkDim, 0);
585+
const size_t CopySize = sizeof(size_t) * CommandWorkDim;
586+
std::memcpy(NDRange.data(), UpdatePtr, CopySize);
587+
};
553588

554589
if (auto GlobalWorkOffsetPtr = pUpdateKernelLaunch->pNewGlobalWorkOffset) {
555-
CLGlobalWorkOffset.resize(CLWorkDim);
556-
std::memcpy(CLGlobalWorkOffset.data(), GlobalWorkOffsetPtr, CopySize);
557-
if (CLWorkDim < 3) {
558-
const size_t ZeroSize = sizeof(size_t) * (3 - CLWorkDim);
559-
std::memset(CLGlobalWorkOffset.data() + CLWorkDim, 0, ZeroSize);
560-
}
590+
updateNDRange(CLGlobalWorkOffset, GlobalWorkOffsetPtr);
561591
}
562592

563593
if (auto GlobalWorkSizePtr = pUpdateKernelLaunch->pNewGlobalWorkSize) {
564-
CLGlobalWorkSize.resize(CLWorkDim);
565-
std::memcpy(CLGlobalWorkSize.data(), GlobalWorkSizePtr, CopySize);
566-
if (CLWorkDim < 3) {
567-
const size_t ZeroSize = sizeof(size_t) * (3 - CLWorkDim);
568-
std::memset(CLGlobalWorkSize.data() + CLWorkDim, 0, ZeroSize);
569-
}
594+
updateNDRange(CLGlobalWorkSize, GlobalWorkSizePtr);
570595
}
571596

572597
if (auto LocalWorkSizePtr = pUpdateKernelLaunch->pNewLocalWorkSize) {
573-
CLLocalWorkSize.resize(CLWorkDim);
574-
std::memcpy(CLLocalWorkSize.data(), LocalWorkSizePtr, CopySize);
575-
if (CLWorkDim < 3) {
576-
const size_t ZeroSize = sizeof(size_t) * (3 - CLWorkDim);
577-
std::memset(CLLocalWorkSize.data() + CLWorkDim, 0, ZeroSize);
578-
}
598+
updateNDRange(CLLocalWorkSize, LocalWorkSizePtr);
579599
}
580600

581601
cl_mutable_command_khr command =
@@ -587,7 +607,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urCommandBufferUpdateKernelLaunchExp(
587607
static_cast<cl_uint>(CLArgs.size()), // num_args
588608
static_cast<cl_uint>(CLUSMArgs.size()), // num_svm_args
589609
static_cast<cl_uint>(CLExecInfos.size()), // num_exec_infos
590-
CLWorkDim, // work_dim
610+
CommandWorkDim, // work_dim
591611
CLArgs.data(), // arg_list
592612
CLUSMArgs.data(), // arg_svm_list
593613
CLExecInfos.data(), // exec_info_list

source/loader/ur_libapi.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7916,6 +7916,7 @@ ur_result_t UR_APICALL urCommandBufferReleaseCommandExp(
79167916
/// - ::UR_RESULT_ERROR_INVALID_OPERATION
79177917
/// + If ::ur_exp_command_buffer_desc_t::isUpdatable was not set to true on creation of the command buffer `hCommand` belongs to.
79187918
/// + If the command-buffer `hCommand` belongs to has not been finalized.
7919+
/// + If `pUpdateKernelLaunch->newWorkDim` is different from the work-dim used on creation of `hCommand`.
79197920
/// - ::UR_RESULT_ERROR_INVALID_COMMAND_BUFFER_COMMAND_HANDLE_EXP
79207921
/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT
79217922
/// - ::UR_RESULT_ERROR_INVALID_KERNEL_ARGUMENT_INDEX

source/ur_api.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6687,6 +6687,7 @@ ur_result_t UR_APICALL urCommandBufferReleaseCommandExp(
66876687
/// - ::UR_RESULT_ERROR_INVALID_OPERATION
66886688
/// + If ::ur_exp_command_buffer_desc_t::isUpdatable was not set to true on creation of the command buffer `hCommand` belongs to.
66896689
/// + If the command-buffer `hCommand` belongs to has not been finalized.
6690+
/// + If `pUpdateKernelLaunch->newWorkDim` is different from the work-dim used on creation of `hCommand`.
66906691
/// - ::UR_RESULT_ERROR_INVALID_COMMAND_BUFFER_COMMAND_HANDLE_EXP
66916692
/// - ::UR_RESULT_ERROR_INVALID_MEM_OBJECT
66926693
/// - ::UR_RESULT_ERROR_INVALID_KERNEL_ARGUMENT_INDEX

test/conformance/exp_command_buffer/buffer_fill_kernel_update.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ struct BufferFillCommandTest
1818
sizeof(val) * global_size, nullptr,
1919
&buffer));
2020

21-
// TODO - Enable single code path after https://github.com/oneapi-src/unified-runtime/pull/1176
22-
// is merged
2321
if (backend != UR_PLATFORM_BACKEND_OPENCL) {
2422
// First argument is buffer to fill
2523
ASSERT_SUCCESS(urKernelSetArgMemObj(kernel, 0, nullptr, buffer));

test/conformance/exp_command_buffer/buffer_saxpy_kernel_update.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ struct BufferSaxpyKernelTest
2929
0, nullptr, nullptr));
3030
}
3131

32-
// TODO: Enable single code path once https://github.com/oneapi-src/unified-runtime/pull/1176
33-
// is merged
3432
if (backend != UR_PLATFORM_BACKEND_OPENCL) {
3533
// Index 0 is output buffer
3634
ASSERT_SUCCESS(

test/conformance/exp_command_buffer/ndrange_update.cpp

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -152,15 +152,9 @@ TEST_P(NDRangeUpdateTest, Update3D) {
152152
Validate(global_size, new_local_size, new_global_offset);
153153
}
154154

155-
// Update the kernel work dimensions to 2, and update global size, local size,
156-
// and global offset to new values.
155+
// Update the kernel work dimensions to use 1 in the Z dimension,
156+
// and update global size, local size, and global offset to new values.
157157
TEST_P(NDRangeUpdateTest, Update2D) {
158-
if (backend == UR_PLATFORM_BACKEND_OPENCL) {
159-
// OpenCL cl_khr_command_buffer_mutable_dispatch does not support
160-
// updating the work dimension.
161-
GTEST_SKIP();
162-
}
163-
164158
// Run command-buffer prior to update an verify output
165159
ASSERT_SUCCESS(urCommandBufferEnqueueExp(updatable_cmd_buf_handle, queue, 0,
166160
nullptr, nullptr));
@@ -183,7 +177,7 @@ TEST_P(NDRangeUpdateTest, Update2D) {
183177
0, // numNewPointerArgs
184178
0, // numNewValueArgs
185179
0, // numNewExecInfos
186-
2, // newWorkDim
180+
3, // newWorkDim
187181
nullptr, // pNewMemObjArgList
188182
nullptr, // pNewPointerArgList
189183
nullptr, // pNewValueArgList
@@ -208,37 +202,35 @@ TEST_P(NDRangeUpdateTest, Update2D) {
208202
Validate(new_global_size, new_local_size, new_global_offset);
209203
}
210204

211-
// Update the kernel work dimensions to 1, and check that previously
212-
// set global size, local size, and global offset update accordingly.
205+
// Update the kernel work dimensions to be 1 in Y & Z dimensions, and check
206+
// that the previously set global size, local size, and global offset update
207+
// accordingly.
213208
TEST_P(NDRangeUpdateTest, Update1D) {
214-
if (backend == UR_PLATFORM_BACKEND_OPENCL) {
215-
// OpenCL cl_khr_command_buffer_mutable_dispatch does not support
216-
// updating the work dimension.
217-
GTEST_SKIP();
218-
}
219-
220209
// Run command-buffer prior to update an verify output
221210
ASSERT_SUCCESS(urCommandBufferEnqueueExp(updatable_cmd_buf_handle, queue, 0,
222211
nullptr, nullptr));
223212
ASSERT_SUCCESS(urQueueFinish(queue));
224213
Validate(global_size, local_size, global_offset);
225214

226215
// Set dimensions to 1
216+
std::array<size_t, 3> new_global_size = {9, 1, 1};
217+
std::array<size_t, 3> new_local_size = {3, 1, 1};
218+
std::array<size_t, 3> new_global_offset = {0, 0, 0};
227219
ur_exp_command_buffer_update_kernel_launch_desc_t update_desc = {
228220
UR_STRUCTURE_TYPE_EXP_COMMAND_BUFFER_UPDATE_KERNEL_LAUNCH_DESC, // stype
229221
nullptr, // pNext
230-
0, // numNewMemObjArgs
231-
0, // numNewPointerArgs
232-
0, // numNewValueArgs
233-
0, // numNewExecInfos
234-
1, // newWorkDim
235-
nullptr, // pNewMemObjArgList
236-
nullptr, // pNewPointerArgList
237-
nullptr, // pNewValueArgList
238-
nullptr, // pNewExecInfoList
239-
nullptr, // pNewGlobalWorkOffset
240-
nullptr, // pNewGlobalWorkSize
241-
nullptr, // pNewLocalWorkSize
222+
0, // numNewMemObjArgs
223+
0, // numNewPointerArgs
224+
0, // numNewValueArgs
225+
0, // numNewExecInfos
226+
3, // newWorkDim
227+
nullptr, // pNewMemObjArgList
228+
nullptr, // pNewPointerArgList
229+
nullptr, // pNewValueArgList
230+
nullptr, // pNewExecInfoList
231+
new_global_offset.data(), // pNewGlobalWorkOffset
232+
new_global_size.data(), // pNewGlobalWorkSize
233+
new_local_size.data(), // pNewLocalWorkSize
242234
};
243235

244236
// Reset output to remove old values which will no longer have a
@@ -253,8 +245,31 @@ TEST_P(NDRangeUpdateTest, Update1D) {
253245
ASSERT_SUCCESS(urQueueFinish(queue));
254246

255247
// Verify that update occurred correctly
256-
std::array<size_t, 3> new_global_size = {global_size[0], 1, 1};
257-
std::array<size_t, 3> new_local_size = {local_size[0], 1, 1};
258-
std::array<size_t, 3> new_global_offset = {global_offset[0], 0, 0};
259248
Validate(new_global_size, new_local_size, new_global_offset);
260249
}
250+
251+
// Test error code is returned if work dimension parameter changes
252+
TEST_P(NDRangeUpdateTest, Invalid) {
253+
const size_t new_work_dim = n_dimensions - 1;
254+
ur_exp_command_buffer_update_kernel_launch_desc_t update_desc = {
255+
UR_STRUCTURE_TYPE_EXP_COMMAND_BUFFER_UPDATE_KERNEL_LAUNCH_DESC, // stype
256+
nullptr, // pNext
257+
0, // numNewMemObjArgs
258+
0, // numNewPointerArgs
259+
0, // numNewValueArgs
260+
0, // numNewExecInfos
261+
new_work_dim, // newWorkDim
262+
nullptr, // pNewMemObjArgList
263+
nullptr, // pNewPointerArgList
264+
nullptr, // pNewValueArgList
265+
nullptr, // pNewExecInfoList
266+
nullptr, // pNewGlobalWorkOffset
267+
nullptr, // pNewGlobalWorkSize
268+
nullptr, // pNewLocalWorkSize
269+
};
270+
271+
// Update command to command-buffer to use different work dim
272+
ur_result_t result =
273+
urCommandBufferUpdateKernelLaunchExp(command_handle, &update_desc);
274+
ASSERT_EQ(UR_RESULT_ERROR_INVALID_OPERATION, result);
275+
}

0 commit comments

Comments
 (0)