Skip to content

Commit d58f3c3

Browse files
committed
Memory subsystem with ASCT
1 parent 3fe21b8 commit d58f3c3

16 files changed

Lines changed: 1126 additions & 0 deletions
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
title: Characterize the memory subsystem of an Arm Linux system using ASCT
3+
4+
description: Use ASCT to measure cache latency, streaming bandwidth, and coherency latency on Arm Neoverse systems, and compare results across Graviton generations.
5+
6+
draft: true
7+
cascade:
8+
draft: true
9+
10+
minutes_to_complete: 90
11+
12+
who_is_this_for: This is an advanced topic for software developers and performance engineers who want to understand and characterize the CPU-side memory subsystem of Arm Linux systems.
13+
14+
learning_objectives:
15+
- Identify the core topology, cluster layout, and cache hierarchy of an Arm Linux system using standard tools
16+
- Measure cache and memory latency using a pointer-chase benchmark from ASCT
17+
- Measure single-core and multi-core streaming bandwidth at each level of the memory hierarchy
18+
- Evaluate latency behavior under bandwidth pressure and measure core-to-core coherency latency
19+
- Compare results across Arm systems and draw conclusions
20+
21+
prerequisites:
22+
- Two or more Arm Linux systems with root or sudo access. The examples use AWS Graviton2 and Graviton4 instances, but other systems are possible.
23+
- Arm System Characterization Tool (ASCT) installed on each system.
24+
- A good understanding of CPU memory subsystems, including cache hierarchies, cache lines, and DRAM in the memory hierarchy.
25+
26+
author: Jason Andrews
27+
28+
skilllevels: Advanced
29+
subjects: Performance and Architecture
30+
armips:
31+
- Neoverse
32+
tools_software_languages:
33+
- ASCT
34+
- Perf
35+
operatingsystems:
36+
- Linux
37+
38+
further_reading:
39+
- resource:
40+
title: Inside Nvidia GB10's Memory Subsystem, from the CPU Side
41+
link: https://chipsandcheese.com/p/inside-nvidia-gb10s-memory-subsystem
42+
type: blog
43+
- resource:
44+
title: Memory latency for application software developers
45+
link: /learning-paths/cross-platform/memory-latency/
46+
type: website
47+
- resource:
48+
title: Arm Neoverse N1 Software Optimization Guide
49+
link: https://developer.arm.com/documentation/109896/latest/
50+
type: documentation
51+
- resource:
52+
title: Arm Neoverse V2 Software Optimization Guide
53+
link: https://developer.arm.com/documentation/109898/latest/
54+
type: documentation
55+
56+
### FIXED, DO NOT MODIFY
57+
# ================================================================================
58+
weight: 1 # _index.md always has weight of 1 to order correctly
59+
layout: "learningpathall" # All files under learning paths have this same wrapper
60+
learning_path_main_page: "yes" # This should be surfaced when looking for related content. Only set for _index.md of learning path content.
61+
---
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
# ================================================================================
3+
# FIXED, DO NOT MODIFY THIS FILE
4+
# ================================================================================
5+
weight: 21 # Set to always be larger than the content in this path to be at the end of the navigation.
6+
title: "Next Steps" # Always the same, html page title.
7+
layout: "learningpathall" # All files under learning paths have this same wrapper for Hugo processing.
8+
---
18.3 KB
Loading
16.5 KB
Loading
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
---
2+
title: Understand the cache hierarchy
3+
weight: 3
4+
5+
### FIXED, DO NOT MODIFY
6+
layout: learningpathall
7+
---
8+
9+
## Why cache hierarchy matters
10+
11+
Every memory access from the CPU passes through a hierarchy of caches before reaching DRAM. Each level trades capacity for speed: L1 is tiny but fast, L2 is larger but slower, and L3 (or a system-level cache) is the largest on-chip cache but has the highest latency. Understanding this hierarchy for your specific system tells you where performance "cliffs" will occur as your working set grows.
12+
13+
## Cache levels on Arm systems
14+
15+
Both systems use 4-way L1 caches with 64-byte lines and 8-way L2 caches, also with 64-byte lines. The key architectural differences are in L2 size and whether a shared last-level cache is present.
16+
17+
Graviton2 (Neoverse N1) has a 1 MB private L2 per core and a 32 MB shared L3 across all 64 cores. Graviton4 (Neoverse V2) doubles the L2 to 2 MB and has a 36 MB shared L3. The larger L2 on V2 reduces traffic to the shared L3 and lowers contention in multi-threaded workloads, which is especially beneficial for workloads with per-thread working sets between 1 MB and 2 MB.
18+
19+
Some SoCs add a System Level Cache (SLC) beyond L3, sitting between the CPU cluster and the memory controllers and serving both CPU and GPU traffic.
20+
21+
## Read cache properties from the kernel
22+
23+
You already saw the `sysfs` approach in the previous section. You can also create a structured summary across all cache levels.
24+
25+
Save the following script as `cache2.sh`:
26+
27+
```bash
28+
for cpu in 0; do
29+
echo "=== CPU $cpu ==="
30+
for idx in /sys/devices/system/cpu/cpu${cpu}/cache/index*; do
31+
level=$(cat $idx/level)
32+
type=$(cat $idx/type)
33+
size=$(cat $idx/size)
34+
ways=$(cat $idx/ways_of_associativity)
35+
line=$(cat $idx/coherency_line_size)
36+
shared=$(cat $idx/shared_cpu_list)
37+
echo " L${level} ${type}: ${size}, ${ways}-way, ${line}B line, shared with CPUs: ${shared}"
38+
done
39+
done
40+
```
41+
42+
Run the script on each instance.
43+
44+
```bash
45+
bash ./cache2.sh
46+
```
47+
48+
On Graviton2 the output is:
49+
50+
```output
51+
=== CPU 0 ===
52+
L1 Data: 64K, 4-way, 64B line, shared with CPUs: 0
53+
L1 Instruction: 64K, 4-way, 64B line, shared with CPUs: 0
54+
L2 Unified: 1024K, 8-way, 64B line, shared with CPUs: 0
55+
L3 Unified: 32768K, 16-way, 64B line, shared with CPUs: 0-63
56+
```
57+
58+
On Graviton4 the output is:
59+
60+
```output
61+
=== CPU 0 ===
62+
L1 Data: 64K, 4-way, 64B line, shared with CPUs: 0
63+
L1 Instruction: 64K, 4-way, 64B line, shared with CPUs: 0
64+
L2 Unified: 2048K, 8-way, 64B line, shared with CPUs: 0
65+
L3 Unified: 36864K, 12-way, 64B line, shared with CPUs: 0-63
66+
```
67+
68+
Pay attention to:
69+
- **Associativity**: higher associativity reduces conflict misses but can increase access latency.
70+
- **Line size**: almost universally 64 bytes on Arm, which matters for stride-based benchmarks.
71+
- **Shared CPU list**: tells you exactly which cores share each cache level.
72+
73+
## Key concepts to carry forward
74+
75+
The following concepts explain why latency plots have the shape they do, and are worth keeping in mind as you work through the benchmarks.
76+
77+
### Cache line and spatial locality
78+
79+
When you access a single byte, the hardware fetches an entire 64-byte cache line. Sequential access patterns benefit from this because nearby data is already cached. Random access patterns do not, because each access potentially fetches a new line.
80+
81+
### Associativity and conflict misses
82+
83+
A 4-way set associative cache can hold 4 lines that map to the same set. If your access pattern happens to map many addresses to the same set, lines get evicted even though the cache isn't full. This is rare in practice for pointer-chase benchmarks but worth understanding.
84+
85+
### Prefetching
86+
87+
Modern Arm cores have hardware prefetchers that detect sequential and strided access patterns. They pull data into the cache before the CPU requests it, which can mask latency for predictable patterns. The pointer-chase benchmark in the next section defeats prefetching by design, giving you the true hardware latency rather than the prefetcher-assisted latency.
88+
89+
### Why nanoseconds matter more than cycles
90+
91+
When comparing systems with different clock speeds, cycles are misleading. A 3 GHz core with 12-cycle L2 latency has 4 ns L2 access time, but a 2.8 GHz core with the same 12-cycle latency has 4.3 ns. When the goal is comparing systems, nanoseconds normalize the comparison.
92+
93+
## Cross-check with documentation
94+
95+
For Arm Neoverse cores, the Technical Reference Manuals (TRMs) list:
96+
- Default and configurable cache sizes
97+
- Associativity
98+
- Prefetcher behavior
99+
- Expected cycle-count latencies
100+
101+
Compare your `sysfs` findings with the TRM. If the sizes differ, the SoC vendor may have chosen a non-default configuration. For example, Neoverse V2 allows L2 sizes of 1 MB or 2 MB, and the TRM documents both options.
102+
103+
{{% notice Tip %}}
104+
Arm publishes TRMs on the [Arm Developer documentation portal](https://developer.arm.com/documentation/). Search for the specific core name (for example, "Neoverse N1 TRM" or "Neoverse V2 TRM") to find the detailed cache specifications.
105+
{{% /notice %}}
106+
107+
## What you've accomplished and what's next
108+
109+
In this section you:
110+
- Reviewed the cache hierarchy for Neoverse N1 (Graviton2) and Neoverse V2 (Graviton4)
111+
- Learned the key concepts of cache lines, associativity, prefetching, and ns-vs-cycles that explain benchmark results
112+
- Cross-checked kernel-reported values against Arm documentation
113+
114+
The next section uses the ASCT `latency-sweep` benchmark to measure the actual access latency at each level of the hierarchy.

0 commit comments

Comments
 (0)