calling the same kernel object multiple times

Can I call the same kernel object “search_kernel” multiple times in a loop, each time supplying different kernel arguments?

For example -


cl_mem args[32];
cl_kernel search_kernel;

search_kernel = clCreateKernel(program, "search_kernel", &err1);

// set and intialize each of memory object args[32]

for (i = 0; i < 32; i++) {
    // we set a different kernel arg for the same kernel in every iteration
    clSetKernelArg(search_kernel, 0, sizeof(cl_mem), &args[i]);
    
    clEnqueuNDRangeKernel(search_kernel); // enqueue the kernel.
}

Because the spec says that - “A kernel is a function declared in a program. A kernel is identified by the __kernel qualifier applied to any function in a program. A kernel object encapsulates the specific __kernel function declared in a program and the argument values to be used when executing this
__kernel function
.”

If I understand what they are saying above, I will have create a new kernel so that the different kernel arguments over each loop iteration are associated with their respective kernel object, and are not set to the same kernel object over each iteration -


cl_mem args[32]; // kernel arguments corresponding to their kernel objects
cl_kernel search_kernel[32]; // define a kernel object for each iteration

for (i = 0; i < 32; i++){
    // create a kernel object for each iteration of the loop
    search_kernel[i] = clCreateKernel(program, "search_kernel", &err1);
}

//initialize and set the buffer memory for args[32]

for (i = 0; i < 32; i++) {
    clSetKernelArg(search_kernel[i], 0, sizeof(cl_mem), &args[i]);

    clEnqueueNDRangeKernel(search_kernel[i]);
}

Yes, you can change the argument values for a kernel using clSetKernelArg and then enqueue a kernel execution using clEnqueueNDRangeKernel (or clEnqueueTask) multiple times for the same kernel. You do not have to created new kernel objects for each instance where you want to change the argument value of an argument to a __kernel function.

Note that as long as you are doing this from a single host thread, the app does not have to do anything extra. If you are trying to change kernel argument values for the same kernel from different host threads, then it is the app’s responsibility to ensure thread-safety. I would recommend that you do not call clSetKernelArg for the same kernel from multiple threads. This will be not as performant. A better option for multiple threads is to create multiple instances of the kernel object and then you can use the kernel object in specific host threads without having to worry about thread safety.

But won’t this affect the kernel object, since the kernel arguments are associated with the kernel object.

If I do a



clSetKernelArg(kernel, 0, value1);
clEnqueueNDKernelRange(kernel,.....);


where I enqueue the kernel and immediately I do this , before this previous kernel enqueue command has even executed -



// immediately I change the kernel arg for the same kernel object to some other value and enqueue the kernel again
clSetKernelArg(kernel, 0, value2);
clEnqueueNDKernelRange(kernel,......);


won’t I end up changing the kernel arguments for this kernel object instance which was enqueued previously, which might lead to side effects? I am not sure what clSetKernelArg() and clSetEnqueueNDRangeKernel(), do at the background. If clSetKernelArg() and clEnqueueNDRangeKernel(), copy the kernel object and its arguments before returning, then the kernel objects’ arguments can be immediately modified to re-enqueue the same kernel object but with new arguments, even before the previous clEnqueueNDRangeKernel() command has finished execution.

clSetKernelArg does change the argument values of the kernel. clEnqueueNDRangeKernel will enqueue a kernel execution with the corresponding argument values associated with the kernel when clEnqueueNDRangeKernel is called.

A call to clSetKernelArg does not impact the kernel argument values used for prior clEnqueueNDRangeKernel calls, only future clEnqueueNDRangeKernel calls.