You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: content/learning-paths/servers-and-cloud-computing/pinning-threads/_index.md
+29-10Lines changed: 29 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,21 +1,21 @@
1
1
---
2
-
title: Getting Started with CPU Affinity
3
-
4
-
draft: true
5
-
cascade:
6
-
draft: true
2
+
title: Optimize application performance with CPU affinity
7
3
8
4
minutes_to_complete: 30
9
5
10
-
who_is_this_for: Developers, performance engineers and system administrators, looking to fine-tune the performance of their workload on many-core Arm-based systems.
6
+
who_is_this_for: This is an advanced topic for developers, performance engineers, and system administrators looking to fine-tune the performance of their workload on many-core Arm-based systems.
11
7
12
8
learning_objectives:
13
-
- Create CPU Sets and implement directly into sourcecode
14
-
- Understand the performance tradeoff when pinning threads with CPU affinity masks
9
+
- Pin threads to specific CPU cores using taskset and source code modifications
10
+
- Measure cache performance improvements from thread pinning using perf
11
+
- Evaluate performance trade-offs between throughput and latency consistency
12
+
- Implement CPU affinity strategies for co-located workloads
15
13
16
14
prerequisites:
17
-
- Intermediate understanding of multi-threaded object-orientated programming in C++ and Python
18
-
- Foundational understanding of build systems and computer architecture
15
+
- An Arm Linux system with four or more CPU cores
16
+
- Experience with multi-threaded programming in C++ and Python
17
+
- Understanding of build systems and computer architecture concepts
CPU affinity is the practice of binding a process or thread to a specific CPU core or set of cores. This tells the operating system scheduler where that work is allowed to run. By default, the Linux scheduler dynamically migrates threads across cores to balance load and maximize overall throughput. Pinning overrides this behavior by constraining execution to a chosen set of cores.
12
12
13
-
## Pinning
13
+
## Identify use cases for thread pinning
14
14
15
15
Pinning is most often used as a fine-tuning technique for workloads that aim to consume as many CPU cycles as possible while running alongside other demanding applications. Scientific computing pipelines and real-time analytics frequently fall into this category.
16
16
17
17
Applications that pin processes to specific cores are often sensitive to latency variation rather than just average throughput. They may also have intricate memory access patterns. Pinning can reduce execution noise and provide more consistent behavior or better memory access patterns under load.
18
18
19
-
## Memory locality
19
+
## Improve memory locality on NUMA systems
20
20
21
21
Memory locality provides another important motivation for pinning. On modern systems with Non-Uniform Memory Access (NUMA) architectures, different cores have varying memory access times and characteristics. The performance depends on where the data is fetched from.
22
22
23
-
For example, in a server with two CPU sockets that appears as a single processor, memory access times differ depending on which core you use. By pinning threads to cores that are close to the memory they use and allocating memory accordingly, you can reduce memory access latency and improve bandwidth.
23
+
For example, in a server with two CPU sockets that appears as a single processor, memory access times differ depending on which core you use. By pinning threads to cores that are close to the memory they use and allocating memory accordingly, you reduce memory access latency and improve bandwidth.
24
24
25
-
## Setting affinity
25
+
## Choose methods to set CPU affinity
26
26
27
27
You can set affinity directly in source code using system calls. Many parallel frameworks expose higher-level controls, such as OpenMP affinity settings, that manage thread placement automatically.
28
28
29
29
Alternatively, at runtime, system administrators can pin existing processes using utilities like `taskset` or launch applications with `numactl` to control both CPU and memory placement without modifying code.
30
30
31
-
## Conclusion
31
+
## Evaluate trade-offs of thread pinning
32
32
33
-
Pinning is a tradeoff. It can improve determinism and locality, but it can also reduce flexibility and hurt performance if the chosen layout isn't optimal or if system load changes. Over-constraining the scheduler may lead to idle cores while pinned threads contend unnecessarily.
33
+
Thread pinning is a trade-off. It can improve determinism and locality, but it can also reduce flexibility and hurt performance if the chosen layout isn't optimal or if system load changes. Over-constraining the scheduler may lead to idle cores while pinned threads contend unnecessarily.
34
34
35
35
As a general rule, rely on the operating system scheduler initially and introduce pinning only when you're looking to fine-tune performance after measuring baseline behavior.
Copy file name to clipboardExpand all lines: content/learning-paths/servers-and-cloud-computing/pinning-threads/setup.md
+8-8Lines changed: 8 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,11 +12,11 @@ This Learning Path works on any Arm Linux system with four or more CPU cores.
12
12
13
13
For example, you can use an AWS Graviton 3 `m7g.4xlarge` instance running Ubuntu 24.04 LTS, based on the Arm Neoverse V1 architecture.
14
14
15
-
If you're unfamiliar with creating a cloud instance, refer to[Get started with Arm-based cloud instances](/learning-paths/servers-and-cloud-computing/csp/).
15
+
If you're unfamiliar with creating a cloud instance, see[Get started with Arm-based cloud instances](/learning-paths/servers-and-cloud-computing/csp/).
16
16
17
17
The `m7g.4xlarge` instance has a uniform processor architecture, so there's no difference in memory or CPU core performance across the cores.
18
18
19
-
On Linux, you can check this with the following command:
19
+
On Linux, check this with the following command:
20
20
21
21
```bash
22
22
lscpu | grep -i numa
@@ -57,9 +57,9 @@ Finally, install the Linux perf utility for measuring performance. See the [Linu
57
57
58
58
## Create a CPU-intensive example program
59
59
60
-
To demonstrate CPU affinity, you'll create a program that heavily utilizes all available CPU cores. This example repeatedly calculates the [Leibniz equation](https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80) to compute the value of Pi. This is a computationally inefficient algorithm to calculate Pi, and you'll split the work across many threads.
60
+
To demonstrate CPU affinity, you'll create a program that heavily utilizes all available CPU cores. This example repeatedly calculates the [Leibniz equation](https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80) to compute the value of Pi. This is a computationally inefficient algorithm to calculate Pi, and the work is split across many threads.
61
61
62
-
Use an editor to create a file named `use_all_cores.cpp` with the code below:
62
+
Create a file named `use_all_cores.cpp` with the code below. This program spawns multiple threads that calculate Pi using the Leibniz formula:
Now that you've compiled the program, you can observe how it utilizes CPU cores. In a separate terminal, use the `top` utility to view the utilization of each core:
146
+
Observe how the compiled program utilizes CPU cores. In a separate terminal, use the `top` utility to view the utilization of each core:
147
147
148
148
```bash
149
149
top -d 0.1
@@ -157,9 +157,9 @@ Then run the program in the other terminal:
157
157
./prog
158
158
```
159
159
160
-

160
+

161
161
162
-
You should observe all cores on your system being periodically utilized up to 100% and then dropping to idle until the program exits.
162
+
All cores on your system are periodically utilized up to 100% and then drop to idle until the program exits.
Copy file name to clipboardExpand all lines: content/learning-paths/servers-and-cloud-computing/pinning-threads/thread_affinity.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -80,7 +80,7 @@ This program has two atomic variables that are aligned on different cache lines
80
80
81
81
## Create a program with explicit thread pinning
82
82
83
-
Now, copy the code below into a new file named `thread_affinity.cpp`:
83
+
Create a file named `thread_affinity.cpp` with the code below. This program uses `pthread_setaffinity_np` to pin threads to specific CPU cores:
84
84
85
85
```cpp
86
86
#include <benchmark/benchmark.h>
@@ -178,7 +178,7 @@ perf stat -e L1-dcache-loads,L1-dcache-load-misses ./thread-affinity
178
178
179
179
## Analyze the performance results
180
180
181
-
Inspecting the output below, you can see that the `L1-dcache-load-misses` metric (which occurs when the CPU core doesn't have an up-to-date version of the data in the L1 data cache and must perform an expensive operation to fetch data from a different location) reduces from approximately 7.84% to approximately 0.6% as a result of thread pinning.
181
+
The output shows the `L1-dcache-load-misses` metric reduces from approximately 7.84% to approximately 0.6% as a result of thread pinning. This metric measures how often the CPU core doesn't have an up-to-date version of data in the L1 data cache and must perform an expensive operation to fetch data from a different location.
182
182
183
183
This results in a significant reduction in function execution time, dropping from 10.7 ms to 3.53 ms:
0 commit comments