Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Course
  • Reading Path
  • Cache Coherency Glossary
  • The Shared Course Model
  • Cache Coherency Revision Sheet
  • Why Coherence Exists8
  • States and Protocols12
  • Transactions12
  • Races and Controller Design8
  • Progress and the Fabric16
  • Ordering and Synchronization12
  • Performance and Scalability12
    • False Sharing
      • True Versus False Sharing
      • Counting Coherence Traffic
      • Padding and Data Layout
      • Finding False Sharing
    • Directory Capacity and Sharers
    • Hotspots and Placement
  • Real Protocols12
  • SoC Integration12
  • Power, Clocking and Reliability12
  • Verification12
  • Debug and Bring-up12
  • Interview and Design Review17
  • Capstone: A Coherent Model Lab5
Loading lesson

‹False Sharing
  1. Topics
  2. Cache Coherency
  3. Performance and Scalability
  4. False Sharing
  5. Padding and Data Layout

Part 7 · Performance and Scalability · All levels

Padding and Data Layout

Separate independently written fields without confusing spacing, alignment and allocation footprint.

Is adding 64 bytes enough?

Only if the actual addresses end up in distinct coherence lines under the selected layout. In the course's 64-byte-line model, fields at offsets 0 and 8 collide; offsets 0 and 64 do not. A struct's base alignment, field offsets and array stride all matter. Padding between fields is different from aligning each repeated object.

Worked layout, with byte offsets from the array base and line = offset // 64. A long is 8 bytes. The padded type is struct slot { long v; char pad[56]; }: 8 data bytes plus 56 pad bytes, so the object stride is 64.

Layout

Field byte ranges

Lines, offset // 64

Consequence

long c[2], C0 writes c[0], C1 writes c[1]

c[0]: 0-7, c[1]: 8-15

0, 0

False sharing: one permission unit for both writers.

struct slot s[2], base aligned to 64, stride 64

s[0].v: 0-7, s[1].v: 64-71

0, 1

Separate lines: each core keeps its own write permission.

Same struct slot s[2], base at offset 60, stride 64

s[0].v: 60-67, s[1].v: 124-131

0-1, 1-2

Both fields span line 1, so the writers still false-share it.

Unpadded 8-byte objects, stride 8, fields at 64 and 72

64-71, 72-79

1, 1

Different objects can still false-share.

The third row is why padding alone is not enough: the padding fixes the stride, but only alignment of the base to 64 puts each field at the start of its own line. (A compiler keeps a long 8-byte aligned, so offset 60 arises from a packed or hand-built buffer, but the same arithmetic applies to any base that is not a multiple of 64.) The allocation must therefore provide 64-byte alignment: alignas(64) on the type plus an allocator that honours it, such as C11 aligned_alloc(64, size) or C++17 aligned new. Default allocations are not 64-byte aligned (common 64-bit allocators guarantee 16 bytes), so a padded struct from a plain malloc can land exactly like row three.

A general guideline beyond the course model: some cores prefetch lines in adjacent pairs, so a write to one line can pull its 128-byte neighbour too. For the hottest independently written fields, separating by 128 bytes avoids that second-order effect. Check the target's documented coherence granule and prefetch behaviour before choosing 64 or 128.

The process computes line ranges, checks cross-core writes and weighs separation against footprint and locality.
A layout fix is checked at field and array boundaries, not inferred from a padding declaration.

For X/Y, separating lines preserves the logical result because each core writes a different word. For a genuinely shared X, copying the counter into per-core counters changes the algorithm: a reduction step must define how and when the global result is assembled. That can be a good design, but it is not padding alone.

The cost side includes more cache lines, potentially more page translations and poorer spatial locality for readers that need all fields. Group fields by the cores and phases that write them, not simply by source-code aesthetics. A producer-written payload and consumer-written status can need separate lines, while a read-mostly record may benefit from packing.

Use a controlled comparison with identical work and a stable writer placement. Inspect the final values as well as traffic. If the padded footprint triggers extra evictions, the saved holder transfers may be offset by capacity misses; measure both rather than declaring either layout universally better.

Common pitfall

Applying the course's 64-byte assumption to a target without checking its documented coherence granule and actual object layout.

Interview

Discuss alignment, stride, writer affinity and read-side footprint together. Explain which fixes preserve the algorithm and which require a new aggregation contract.

Check yourself Why can an array still false-share when every object has padding?

The total object stride and base alignment determine where adjacent writable fields land. Unused bytes do not prove that the actual field ranges occupy disjoint lines.

Related topics

  • Shared course model

  • Traffic and value-preserving comparison

Previous

76 / 167

Next: Finding False Sharing

Up next

Up nextFinding False Sharing

Sign in to save progress

Practice this lessonReport an error

See also

  • True Versus False Sharing