liveBook · Manning

GPGPU

As explained in Fast Python: High performance techniques for large datasets

GPGPU is the use of graphics processing units to perform general-purpose computations, often by exploiting their parallel processing capabilities.

General-purpose computing on graphics processing units (GPGPU) uses GPUs for work beyond graphics. A GPU has many relatively simple processing units suited to performing similar operations across large numbers of independent data points. This makes arrays, matrices, and many AI workloads promising candidates, but existing sequential CPU code cannot simply be recompiled for a GPU. section 1.2.1 section 9.0

Start with the shape of the work, not the device's advertised computing power. Doubling every array element is parallel; doubling one value offers little opportunity to use thousands of processing units. In an illustrative latency calculation, processing many values takes 18,200 time units on a sequential CPU model versus 240 on a parallel GPU model. For one value, the same models take 202 and 240 units respectively. These are model results, not benchmark timings. section 9.1.1

For an explicit Python GPU implementation with Numba:

  • Check the environment first: GPU drivers and the CUDA toolkit are required; `numba -s` reports whether a supported device and needed libraries are available. section 9.2.1
  • Replace the sequential loop with a `@cuda.jit` kernel that handles one array element per thread. Obtain its position with `cuda.grid(1)` and modify the array in place rather than returning a value. section 9.2.2
  • Launch the kernel with explicit block and thread counts. Cover every element, guard against positions beyond the array when the launch is larger, and check the resulting values. section 9.2.2
@cuda.jit
def double_safe_explicit(my_array):
    position = cuda.blockIdx.x * cuda.blockDim.x + cuda.threadIdx.x
    if position >= my_array.shape[0]:
        return
    my_array[position] *= 2

This kernel makes the thread's array position and the out-of-bounds guard explicit. Its `>=` check allows a launch whose total thread count exceeds the array length. section 9.2.2

Direct kernel programming is not the only route. CuPy offers a NumPy-like GPU interface, and cuDF offers a pandas-like one. Numba instead supports redesigning a highly parallel operation as GPU code while retaining NumPy in the surrounding Python workflow. The choice depends on the operation: GPU computing favors substantial, similar work across many data points, not isolated operations or an unchanged sequential loop. section 9.4 section 9.1.1

How Fast Python: High performance techniques for large datasets covers it

How deep it goes
Develops per-element Numba kernels, launch dimensions, indexing, and bounds checks; defers algorithms that exploit fast shared state within blocks.
Examples
Uses array doubling, matrix indexing, a CPU-versus-GPU latency calculation, and a Mandelbrot generator as implementation examples.
What it assumes
Assumes familiarity with Python arrays and NumPy; introduces the GPU execution mindset while pointing elsewhere for a prior CPU-side Numba introduction.
What you can do after
Build it from scratch with Numba by writing a per-element GPU kernel, configuring its launch, and checking its output.
How it connects
Connects GPU architecture and memory latency to data parallelism, NumPy arrays, Numba kernels, CuPy, and cuDF.

Also explained in

Compare how 3 books explain GPGPU →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Fast Python: High performance techniques for large datasets. The section links point to the parts of the book it draws on.