The traditional first kernel — every GPU thread prints its coordinates
This is the smallest CUDA program that proves your toolchain works end-to-end: the driver loads the kernel, the runtime launches threads, the threads execute device code, and cudaDeviceSynchronize flushes their output back to the CPU stdout.
Read the source carefully. Every line corresponds to one of the three CUDA extensions you saw in lesson 1:
__global__ void say_hello()— function qualifier marking this as a kernel.say_hello<<<1, 4>>>()— triple-angle launch: 1 block, 4 threads.blockIdx.x,threadIdx.x— SIMT built-ins giving each thread its identity.
The launch syntax <<<grid, block>>> is one of the few CUDA constructs that looks like template syntax but isn't. NVCC parses it as a special launch expression. After NVCC's pre-pass, what reaches your normal C++ compiler is a regular function call into the runtime API with grid/block dimensions packed as arguments.