Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

How a GPU organises its threads

After this lesson: I can say how a GPU organises its threads and work out the global index of one.

60 min lesson2 commandsParallel computing lab: how a GPU thinks, without a GPU, in JupyterLab

How a GPU groups its threads into blocks

A GPU, or graphics processing unit, is a chip built to run thousands of simple threads at once. It groups them into blocks, and the blocks into a grid. Every thread works out which piece of the data is its own from its place in that grid.

This lab has no GPU. It shows the same arrangement in plain Python, so you can follow every thread by eye.

By the end of this lesson

Note

I can say how a GPU organises its threads and work out the global index of one.

Key words

WordWhat it meansExample
Threadone small worker that runs the kernel once
Blocka group of threads that run together
Gridall the blocks of one launch
Block sizehow many threads are in each blockblock_dim = 4
Global indexa thread's place among all the threads of the grid
Coreone processing unit that runs instructions

The cells students fill in are left blank in this preview.

A CPU has few cores, a GPU many

A CPU, the central processing unit, has a few powerful cores. Each is good at running one tricky sequence of steps quickly.

A GPU has thousands of simple cores. One of its threads is slower than a CPU's, but thousands run together. That wins when the job is the same small step on a great many independent items.

Each thread works out its own element

Every thread runs the same function, so it must find its own piece of the data. It does that with one line of arithmetic:

global index = block number x block size + thread number within the block

The thread knows its block number and its place in the block. The block size is the same for every block.

Worked example: 3 blocks of 4 threads

BlockThread 0Thread 1Thread 2Thread 3
00123
14567
2891011

The cells students fill in are left blank in this preview.

Run the global index sum

Code: python
# Which element does each thread own? 2 blocks of 5 threads.
block_dim = 5
for block_idx in range(2):
    for thread_idx in range(block_dim):
        i = block_idx * block_dim + thread_idx
        print("block", block_idx, "thread", thread_idx, "owns element", i)
# Change block_dim to 3 and the number of blocks to 4, then run again.

The lab simulates a launch of 3 blocks

The lab's kernel.py launches 3 blocks of 4 threads over 10 elements. It prints the block, the thread and the global index of each of the 12 threads.

Twelve threads cover ten elements, so the last two have no element. The script tells you which ones. The second Run works one index by hand: block 3, thread 1, block size 4, then 7 turned back into a block and a thread.

Print the simulated launch

Command
docker exec jupyter python3 steps/kernel.py

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Work an index and reverse another

Command
docker exec jupyter python3 -c "print(3 * 4 + 1, 7 // 4, 7 % 4)"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

A common mistake

Warning

Many people think a GPU thread is a faster CPU thread. It is slower and simpler. The GPU's speed comes from the number of threads, so it helps only when there is a lot of independent work to give them.

About this lab and its source: Parallel computing lab: how a GPU thinks, without a GPU, in JupyterLab

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.