What is memory alignment?
Memory alignment means placing a value at an address that is a multiple of a chosen power of two — for example 4, 8, 16, or 64 bytes — so the hardware can load and store it efficiently, and so SIMD instructions can use their fast aligned forms.
Why do CPUs care whether an address is a multiple of 4, 8, or 16?
Natural alignment matches a type’s size: a 4-byte float at an address divisible by 4, an 8-byte pointer at a multiple of 8. On many architectures, misaligned access is slower, split across two bus transactions, or in extreme cases faulted. Even on platforms that allow unaligned loads, wide SIMD instructions often require 16- or 32-byte alignment for their fastest variants, falling back to slower unaligned paths — or to multiple scalar ops — when the base address is wrong. Cache lines add another alignment scale: starting a hot structure at a line boundary can keep the whole record in one line instead of straddling two, which halves miss cost on first touch. Alignment is therefore both a correctness concern on strict ISAs and a performance concern everywhere HNSW runs vectorized distance kernels.
Those distance kernels are exactly where alignment shows up first in an HNSW codebase.
How does alignment affect HNSW vector storage and SIMD distances?
A vectorized inner-product or L2 loop wants to issue wide loads from the start of each candidate vector. If every vector begins at a 16- or 32-byte-aligned address — and the row stride is chosen so successive vectors stay aligned — the compiler or intrinsics can use aligned SIMD loads throughout the main loop. If vectors are packed with an awkward header byte or a stride that drifts out of alignment, every candidate may take the slow path, quietly erasing much of the SIMD win. Allocating the big vector arena with aligned_alloc (or equivalent), sizing dimensions so byte length meets the alignment, and adding padding between rows when needed are the usual fixes. Production distance paths, including those used in systems like Weaviate, assume this kind of disciplined layout so architecture-specific kernels can run at full width.
Neighbor lists and node records have a milder but still real alignment story.
What should be aligned in HNSW graph metadata, not only in vectors?
Arrays of 32-bit neighbor IDs should start on at least 4-byte boundaries; 64-bit IDs on 8-byte. Per-node mutexes and atomics often require alignment to their size — and padding to a full cache line when avoiding false sharing. An array-of-structures node record whose Natural alignment is 8 bytes will have its stride rounded up by the compiler so each element stays correctly aligned, which is one source of padding bytes inside the struct. Over-aligning every tiny field to 64 bytes wastes memory; under-aligning wide loads wastes cycles. Match the alignment to the access: cache-line align hot per-thread counters and locks, SIMD-align vector bases, natural-align integer ID arrays.
Alignment interacts with serialization and memory mapping too, where on-disk offsets become in-memory addresses.
How do mmap, allocators, and binary formats constrain HNSW alignment?
A memory-mapped index file preserves whatever alignment the writer baked into offsets. If vectors were written at file offsets that are 16-byte aligned relative to the map base — and the map itself is page-aligned — the process can search without copying into a freshly aligned buffer. If the format packs fields tightly with no padding, the reader may need to copy vectors into an aligned arena before SIMD search, paying bandwidth and memory. Custom allocators for node slabs should return suitably aligned chunks; ordinary malloc is usually aligned enough for 8- or 16-byte needs on modern platforms but not always for 32- or 64-byte SIMD preferences or page-multiple huge-page strategies. Specifying alignment in the binary format and in the allocator contract is part of making HNSW persistence and fast search coexist.
Memory alignment places data on addresses the CPU and SIMD units can use at full speed — essential for HNSW vector arenas, and still relevant for IDs, atomics, and mapped files. From here, the padding page explains the bytes inserted to satisfy alignment inside structs, SIMD and vectorized distance computation show why wide loads care, contiguous layout covers packing without breaking strides, and the chapter on laying out HNSW in memory puts these rules into a concrete index design.