Skip to content

Commit fe85e5a

Browse files
Merge pull request #3091 from jasonrandrews/review3
Memory subsystem with ASCT
2 parents 32484de + 6721e7d commit fe85e5a

16 files changed

Lines changed: 1125 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: 60
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
17+
- Measure single-core and multi-core streaming bandwidth at each level of the memory hierarchy
18+
- Evaluate latency behavior under bandwidth pressure
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: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
---
2+
title: Understand the cache hierarchy
3+
weight: 3
4+
5+
### FIXED, DO NOT MODIFY
6+
layout: learningpathall
7+
---
8+
9+
## Cache levels and performance clifs
10+
11+
Each memory access is satisfied by the closest level of the hierarchy that contains the requested data. If the data is not found in the private caches, the request falls through to the next cache level and eventually to 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 Graviton 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 the last level cache size. If you investigate a variety of Arm Linux systems you will see many different cache sizes and configurations.
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 Neoverse 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+
## Read cache properties from the kernel
20+
21+
You already saw the `sysfs` approach in the previous section. You can also create a structured summary across all cache levels.
22+
23+
Save the following script as `cache2.sh`:
24+
25+
```bash
26+
for cpu in 0; do
27+
echo "=== CPU $cpu ==="
28+
for idx in /sys/devices/system/cpu/cpu${cpu}/cache/index*; do
29+
level=$(cat $idx/level)
30+
type=$(cat $idx/type)
31+
size=$(cat $idx/size)
32+
ways=$(cat $idx/ways_of_associativity)
33+
line=$(cat $idx/coherency_line_size)
34+
shared=$(cat $idx/shared_cpu_list)
35+
echo " L${level} ${type}: ${size}, ${ways}-way, ${line}B line, shared with CPUs: ${shared}"
36+
done
37+
done
38+
```
39+
40+
Run the script on each instance.
41+
42+
```bash
43+
bash ./cache2.sh
44+
```
45+
46+
On Graviton2 the output is:
47+
48+
```output
49+
=== CPU 0 ===
50+
L1 Data: 64K, 4-way, 64B line, shared with CPUs: 0
51+
L1 Instruction: 64K, 4-way, 64B line, shared with CPUs: 0
52+
L2 Unified: 1024K, 8-way, 64B line, shared with CPUs: 0
53+
L3 Unified: 32768K, 16-way, 64B line, shared with CPUs: 0-63
54+
```
55+
56+
On Graviton4 the output is:
57+
58+
```output
59+
=== CPU 0 ===
60+
L1 Data: 64K, 4-way, 64B line, shared with CPUs: 0
61+
L1 Instruction: 64K, 4-way, 64B line, shared with CPUs: 0
62+
L2 Unified: 2048K, 8-way, 64B line, shared with CPUs: 0
63+
L3 Unified: 36864K, 12-way, 64B line, shared with CPUs: 0-63
64+
```
65+
66+
Pay attention to:
67+
- **Associativity**: higher associativity reduces conflict misses but can increase access latency.
68+
- **Line size**: almost universally 64 bytes on modern Arm server cores, which matters for stride-based benchmarks.
69+
- **Shared CPU list**: tells you exactly which cores share each cache level.
70+
71+
## Key concepts to carry forward
72+
73+
The following concepts explain why latency plots have the shape they do, and are worth keeping in mind as you work through the benchmarks.
74+
75+
### Cache line and spatial locality
76+
77+
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.
78+
79+
### Associativity and conflict misses
80+
81+
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 less likely with randomized pointer-chase patterns, but can still occur depending on address distribution and cache indexing but worth understanding.
82+
83+
### Prefetching
84+
85+
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.
86+
87+
### Why nanoseconds matter more than cycles
88+
89+
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.
90+
91+
## Cross-check with documentation
92+
93+
For Arm Neoverse cores, the Technical Reference Manuals (TRMs) list:
94+
- Default and configurable cache sizes
95+
- Associativity
96+
- Prefetcher behavior
97+
- Expected cycle-count latencies
98+
99+
Compare your `sysfs` findings with the TRM. If the sizes differ, the SoC vendor may have chosen a different configuration. Many Arm CPUs have multiple options for cache size. For example, Neoverse V2 allows L2 sizes of 1 MB or 2 MB, and the TRM documents both options.
100+
101+
{{% notice Tip %}}
102+
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.
103+
{{% /notice %}}
104+
105+
## What you've accomplished and what's next
106+
107+
In this section you:
108+
- Reviewed the cache hierarchy for Neoverse N1 (Graviton2) and Neoverse V2 (Graviton4)
109+
- Learned the key concepts of cache lines, associativity, prefetching, and ns-vs-cycles that explain benchmark results
110+
- Cross-checked kernel-reported values against Arm documentation
111+
112+
The next section uses the ASCT `latency-sweep` benchmark to measure the actual access latency at each level of the memory hierarchy.

0 commit comments

Comments
 (0)