Suppose that my input consists of seven data points on which some calculation is performed and the results are written back to an output array of size 7. Declaring the block dimension to be 4 results in a grid size of 2, which leads to an attempt to run a kernel with the invalid thread id (using pt_id=blockIdx.x*blockDim.x+threadID.x) of 7 and failing due to an invalid memory access (since I access some of my arrays based on thread id). I could add code in my kernel that specifically compares the thread id to a max_thread_id parameter and does nothing if thread_id>max_thread_id but am wondering if there's a prettier way to handle ragged input arrays.
1 Answers
Having a task of a size which is not multiple of a dimension of block is quite common stuff. The most frequently used solution by me is this. Suppose your input data has size N
and you want to configure your launch with the block size equaling to BLOCK_SIZE
. In this case, your launch configuration could look like this:
kernel_function<<<(N + BLOCK_SIZE - 1) / BLOCK_SIZE, BLOCK_SIZE>>>(...);
And at the kernel code, each thread determines whether it is supposed to do some work, something like this:
int id = blockIdx.x*blockDim.x + threadIdx.x;
if (id < N) { /* do the stuff */ }
else { return; }
If the size of task (N
) depends on the input you have to pass this value into the kernel function as parameter as well. Further, it is quite common to define values of N
and BLOCK_SIZE
as macros or template parameters.
Finally, if your input array has small size, like in your example, GPU remains underutilized and parallelism brings you nothing or even decreases performance of your algorithm.
N
, and check whetherpt_id<N
. I'm not sure what do you like to achieve withmax_thread_id
. I believe that the title of your post is not appropriate. The overall number of threads can be always represented asdimGrid*dimBlock
. This makes me think that you are making some confusion between array size and grid size. – Vitality