a cache miss
When the processor needs a number, it first looks in the cache — the small, fast scratchpad next to the core. If the number is already sitting there, that is a cache hit and the value arrives almost instantly. If it is not there, that is a cache miss: the processor must reach down into slower memory to fetch it, and meanwhile it largely stalls, twiddling its thumbs for tens or hundreds of cycles. A cache miss is, quite simply, the moment your fast computer turns into a slow one.
There is a subtlety that makes locality pay off: memory is not fetched one number at a time. On a miss the hardware hauls up a whole contiguous chunk called a cache line — typically 64 bytes, which is eight double-precision numbers. So if you touch one element of an array and then march on to the next neighbouring element, the neighbour is already in cache (a hit) — you paid for the line once and got eight numbers from it. But if you stride through memory jumping far apart, every access lands in a fresh line, every access misses, and you waste seven-eighths of every line you fetch. Misses come in flavours: compulsory (the first time you ever touch data), capacity (the working set is bigger than the cache, so old data gets evicted before reuse), and conflict (unlucky addresses collide in the cache's slots).
Cache misses are the hidden tax on real numerical code. A textbook would say multiplying two n-by-n matrices the naive way costs 2*n^3 flops; on a real machine the naive triple loop is slow not because of the flops but because one of its loops strides across rows, generating a cache miss on nearly every inner step. The whole craft of high-performance numerics — blocking, choosing row-major vs column-major traversal, packing data — is largely the craft of converting misses into hits. Counting misses, not flops, predicts the runtime of a memory-bound kernel.
Summing a 2D array of doubles stored row-major: looping rows-then-columns touches consecutive addresses, so each 64-byte line serves 8 numbers — about one miss per 8 accesses. Loop columns-then-rows instead and each access jumps a whole row apart, landing in a fresh line every time — about one miss per access, roughly 8x more memory traffic and often several times slower, for byte-identical arithmetic.
Same flops, same sum — but the wrong loop order misses on nearly every access.
A miss fetches a whole line (often 8 doubles), not one number — so the cost is amortised only if you use the neighbours you dragged in. The common mistake is to assume 'one access = one fetch'; on real hardware a single badly-strided access can waste seven-eighths of the bandwidth it triggers.