It's C++ with three syntax extensions — and one philosophy
At first glance CUDA C++ looks like plain C/C++. You include headers, you write functions, you compile. But three extensions change the game completely:
- Function qualifiers —
__global__,__device__,__host__— decide where a function runs and who may call it. A__global__kernel runs on the GPU but is launched from CPU host code. - The triple-angle launch —
kernel<<<grid, block>>>(args);— is compile-time metadata that the runtime converts into a command buffer for the GPU scheduler. - SIMT built-ins —
threadIdx.x,blockIdx.x,blockDim.x,gridDim.x— give every thread its own coordinates so it knows which slice of work to do.
Otherwise you inherit the full C++17 toolchain: lambdas, templates, <algorithm>, std::vector on the host side. The twist is that device code is funneled through NVCC, which splits your translation unit, compiles GPU sections with PTX/SASS back-ends, then relinks everything into a single binary.
Why a separate compiler? Because GPUs aren't another CPU. They have their own ISA (PTX is the portable intermediate, SASS is the per-architecture binary), their own register file shape, their own memory hierarchy. NVCC is the bilingual translator that lets you write one source file but ship two compiled programs that meet at link time.
The philosophy: SIMT (Single Instruction, Multiple Threads). Thousands of threads run the same kernel body in lockstep, branching on their indices. You don't write a loop over elements; you write what one thread does, then launch enough threads to cover the data.