Pre-allocation and Pre-fetching

Memory hierarchy

From fastest to slowest:

  • Registers (1 CPU cycle, a few bytes per register)
  • L0 cache (around 16 KB)
  • L1 cache (128 KB; 0.5 ns for the data cache, 5 ns for a branch misprediction on the instruction cache)
  • L2 cache (instruction and data, shared; 256 KB to 8 MB; access around 5-7 ns)
  • L3 cache (shared; 32 to 64 MB; around 12 ns). L1 and L2 sit per core; L3 can live on the CPU itself and is the shared cache for all cores
  • L4 cache (shared; 64 to 128 MB; around 40 ns)
  • Main memory (16 to 256 GB; around 60 ns). NUMA machines experience non-uniform access times
  • Disk storage (terabytes; 100 microseconds)

Pre-fetching

Pre-fetching also happens as part of branch prediction (instruction pre-fetching).

Data is not loaded a few bytes at a time, but one or a few pages (a few kilobytes) at a time. Subsequent references to the same data lead to cache hits and experience lower access latencies.

Locality

The principle of locality: related datasets placed near each other in memory allow for more efficient caching. You must know how big each cache is, how much data fits in a cache line, and the cache access times, for the specific architecture.