Frontiers of Systems Programming

SIMT versus SIMD

/ SIM-tee versus SIM-dee /

Both a modern CPU and a GPU can apply one operation to many pieces of data at once - that is the whole point of parallel hardware. But they expose it to the programmer in two different mental models, and confusing them leads to wrong intuitions about how each performs. SIMD and SIMT are those two models: two ways of saying 'one instruction, many data items.'

SIMD, single instruction, multiple data, is the CPU-vector view. You write code that operates on a wide register holding, say, 8 floats at once; one add instruction adds all 8 lanes in a single step. The lanes are not threads - there is one program counter, one instruction stream, and the parallelism is explicit in the data width. You think 'I have a vector of 8 and one operation hits all of it.' Masking handles the awkward case where you want only some lanes to act. SIMT, single instruction, multiple threads, is the GPU view (NVIDIA's term). Here you write code as if for one scalar thread - 'compute c[i] = a[i] + b[i] for my i' - and the hardware runs many such threads, a warp of 32, in lockstep on shared instruction-issue logic. It feels like ordinary threads, but they march together; when threads in a warp take different branch directions, the hardware must serialize the branches (this is warp divergence), executing the if-takers while the else-takers idle, then swapping - so a branch that splits a warp can halve throughput.

Getting the distinction right matters because it tells you where performance comes from and where it leaks away. With SIMD you think in vector width and you, the programmer (or the auto-vectorizer), must shape the data; with SIMT you think in independent threads, but the cost of branches and of scattered memory access is hidden until it bites. They are genuinely close cousins - SIMT is essentially SIMD with a friendlier per-thread programming model and hardware-managed masking - and the honest summary is: same underlying idea (one instruction over many data), different abstraction, different failure modes.

// SIMD (CPU): one instruction over a vector of lanes // __m256 v = _mm256_add_ps(a, b); // adds 8 floats at once; one PC, 8 lanes // SIMT (GPU): write a scalar thread; the warp runs 32 in lockstep // c[i] = a[i] + b[i]; // your 'i'; 32 threads issue this same add together

SIMD makes the vector explicit in one instruction stream; SIMT looks like 32 ordinary threads that secretly march in lockstep as a warp.

The two are close cousins, not opposites: SIMT is essentially SIMD with a per-thread programming model and hardware masking. The key practical difference is warp divergence - in SIMT, a branch that sends threads of one warp down different paths serializes those paths and wastes lanes, a cost the scalar-looking code hides.

Also called
single instruction multiple threadssingle instruction multiple data單指令多執行緒對單指令多資料