Processor affinity, also known as CPU pinning, is a feature available in Linux that enables us to bind a process to a specific set of CPUs. This technique is crucial in improving system performance, especially in multi-threaded environments where managing how processes use CPU resources can make a significant difference. By setting processor affinity, we can control the execution of processes on a particular core, optimizing for cache utilization and preventing the CPU from switching between cores, which can introduce latency.

To adjust processor affinity, Linux provides utilities such as taskset and system calls like sched_setaffinity. The taskset command is straightforward and commonly used for modifying the CPU affinity of running processes or launching new ones with specified CPU settings. With sched_setaffinity, which requires a bit more code, we can achieve a similar result programmatically in C or C++ languages. It’s our responsibility to use these tools effectively to enhance our system’s performance and ensure optimal operation of our critical applications. By harnessing the power of CPU pinning, we can reduce context switching and cache misses, ensuring our applications run more efficiently on the designated CPUs.
Contents
Understanding Processor Affinity
Processor affinity, also known as CPU pinning, allows us to bind a process or a thread to a specific CPU or set of CPUs. It can be vital for performance optimization, especially in systems with high processor counts.

Basics of CPU Affinity
By enforcing processor affinity, we avoid the potential penalties due to cache misses when a process is switched from one CPU to another, what we refer to as the “context switch overhead”. The default behavior without setting affinity is that the Linux scheduler will dynamically distribute processes across all available CPUs to balance the load.
Affinity vs. Scheduling
| Affinity | Scheduling |
| Affinity binds processes to specific CPU(s), limiting the scheduler’s freedom to move processes across CPUs. | Without affinity, the scheduler has full discretion to allocate processes to any CPU, aiming for optimal load distribution. |
| This control can optimize cache performance and may enhance bandwidth usage for memory-intensive processes. | Dynamic scheduling can adapt to changing system loads but may lead to more cache misses and non-uniform memory access (NUMA) issues. |
| Best for applications that are sensitive to latency, such as real-time data processing. | Ideal for general-purpose workloads that benefit from the scheduler’s ability to manage tasks efficiently. |
We should consider processor affinity when consistent performance and low latency are required, but keep in mind that it may restrict the scheduler’s ability to balance the system load. It offers a more predictable performance pattern by providing dedicated CPU bandwidth to critical processes, which makes it easier for system administrators to allocate the hardware resources strategically.
Setting Affinity with Taskset
We understand that setting processor affinity is crucial for optimizing system performance. The taskset command in Linux is the tool we use for this purpose. It binds processes to a set of CPUs, enhancing efficiency and resource management.
Using the Taskset Command
To set a process’s affinity, we need the process ID (PID) and the CPUs to which we want to assign it.
Here is how we operate the command:
| Command Format | Example | Description |
| taskset -cp [CPUs] [PID] | taskset -cp 0,2 1234 | Assigns process with PID 1234 to CPUs 0 and 2. |
| taskset -p [Mask] [PID] | taskset -p 0x3 1234 | Sets affinity to CPUs interpreted from the mask 0x3. |
Using taskset, we also check the current affinity of a process with “taskset -p [PID]”.
Interpreting Affinity Mask Values
Affinity mask values are pivotal in assigning CPU cores to processes. A mask specifies which cores a process can utilize.
Each bit of the mask corresponds to a CPU core.
For instance, a mask of ‘0x1’ would restrict the process to CPU 0, while a mask of ‘0xFF’ allows the process to run on any of the first 8 CPUs. Understanding binary representation is essential for setting custom affinity masks.
Here’s a note on masks:
- A bit value of 1 allows running on the corresponding CPU.
- A bit value of 0 prevents running on the corresponding CPU.
Interpreting these masks accurately ensures that we leverage taskset to its full potential.
Advanced Processor Affinity Management
Processor affinity provides us with the precise control we need to assign specific processes to particular CPUs. By managing processor affinity, we can optimize system performance, especially cache performance, and reduce cache misses.
Working with sched_setaffinity
#define _GNU_SOURCE #include <sched.h> cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(0, &mask); CPU_SET(1, &mask); pid_t pid = 12345; // Replace with your process ID int result = sched_setaffinity(pid, sizeof(mask), &mask);
If the return value is 0, the call was successful. A non-zero return indicates an error.
Optimizing for Cache Performance
Cache performance is pivotal in system optimization due to its impact on reducing costly cache misses. By assigning a process to a local and preferred CPU, data loads faster as it’s more likely to be found in the CPU’s local cache. When we set processor affinity appropriately, we limit the number of cache misses, leading to performance gains.
We further optimize performance using sched_setscheduler() alongside processor affinity to define both the processor a process will run on and the scheduling policy it should use. Our insights have shown that these adjustments can yield a significant positive effect on high-load systems, especially those with a high context switch rate. By strategically placing process execution on designated cores, we make sure that CPU caches are used proficiently.
It’s important to remember that these techniques should be applied in environments where the overhead of moving processes between CPUs is detrimental to performance. In most average consumer-use cases, the Linux kernel’s scheduler is adept at managing processor affinity without intervention.
Monitoring and Testing Affinity Settings
Setting processor affinity on Linux can streamline a process’s CPU use. Monitoring and evaluating these settings is crucial to harness the intended performance benefits. We delve into tools like ‘ps’ and ‘sched_getaffinity’ and assess how these configurations impact performance.
Checking Affinity with ps and sched_getaffinity
We utilize the ‘ps’ command for reviewing a process’s CPU affinity. The command provides details about running processes and their associated CPU affinity masks, which define the CPUs on which they can run.
We also use ‘sched_getaffinity’, a system call that retrieves the CPU affinity mask of a certain process identified by its PID. To find a process’s CPU affinity using ‘sched_getaffinity’, we must view the relevant man page for precise usage.
Performance Benefits and Evaluation
We attribute enhanced performance in Linux systems to proper use of CPU affinity, especially within high-performance computing environments. By restricting processes to specific CPUs, we often observe improved cache usage and reduced context switching.
Performance evaluation involves establishing baseline metrics and comparing them post-affinity adjustments. We might employ tools like ‘Perf’ and ‘cgroups’ for comprehensive performance metrics and managing system resources. Red Hat Enterprise Linux users can leverage ‘tuned’ and ‘tuna’ utilities for a more Red Hat-specific approach to performance tuning.
| Method | Usage | Purpose |
| sched_getaffinity | system call | Retrieves CPU affinity mask |
| ps | -o pid,cpuset | Displays CPU affinity |
| cgroups | systemd integration | Manages resource allocation |
Using ‘systemd’ for persistent affinity settings on system services is another aspect we consider. The ‘CPUAffinity’ directive allows us to establish CPU affinity mask directly within service unit files. This ensures that affinity settings persist across system reboots.