Metal学习(7) - Threads & Threadgroups

Metal executes the set kernel function on a 1D, 2D or 3D mesh while the GPU is doing texturing (or computation).

Each point in the grid represents an instance of a kernel function, called Threads.

For example, in image processing, a grid is usually a 2D matrix of threads, representing the entire image, with each thread corresponding to a single pixel of the image being processed.

Threads are organized into thread groups (Threadgroups), these thread groups execute together and can share a common memory block. While sometimes kernel functions are designed to make threads run independently of each other, it is also common for threads in a thread group to cooperate on their working sets.

The diagram below shows how the compute core divides the image being processed into thread groups, and how each thread group consists of individual threads. Each thread processes one pixel.

image.png

Identify threads by position in the grid

A thread can be identified by its position in the grid; it is this unique position that allows kernel functions to do different things for each thread.

The following example kernel function shows how the position of the thread in the grid can be passed as an argument to the function. In this case, the parameter gidis a vector representing the 2D coordinates used to read and write to a specific location in the texture.

kernel void
grayscaleKernel(texture2d<half, access::read>  inTexture  [[texture(AAPLTextureIndexInput)]],
                texture2d<half, access::write> outTexture [[texture(AAPLTextureIndexOutput)]],
                uint2                          gid        [[thread_position_in_grid]])
{
    if((gid.x >= outTexture.get_width()) || (gid.y >= outTexture.get_height()))
    {
        return;
    }
    half4 inColor  = inTexture.read(gid);
    half  gray     = dot(inColor.rgb, kRec709Luma);
    outTexture.write(half4(gray, gray, gray, 1.0), gid);
}
复制代码

[[thread_position_in_grid]]is an attribute qualifier . Property qualifiers, which can be identified by their square bracket syntax. The attribute qualifier, indicating that this value is the position of the thread in the grid.

For example, given a grid of 16 x 16 threads divided into 2 x 4 thread groups of 8 x 4 threads, the position of a single thread (shown in red in the figure) in the grid is (9,10):

image.png

Identify threads by their position in a thread group

Using the following code, a thread's position in the grid can be calculated based on the thread's position in its thread group and the size and position of that thread group in the grid:

kernel void 
myKernel(uint2 threadgroup_position_in_grid   [[ threadgroup_position_in_grid ]],
         uint2 thread_position_in_threadgroup [[ thread_position_in_threadgroup ]],
         uint2 threads_per_threadgroup        [[ threads_per_threadgroup ]]) 
{

    uint2 thread_position_in_grid = 
        (threadgroup_position_in_grid * threads_per_threadgroup) + 
        thread_position_in_threadgroup;
}
复制代码

[[threadgroup_position_in_grid]]The position of the thread group in the grid

[[thread_position_in_threadgroup]]the thread's position within its thread group

For example: a thread is in a thread group with position (1,2) in the grid, and its position in this thread group is (1,2)

image.png

Guess you like

Origin juejin.im/post/7085633906501746724