How to Set Process Affinity on Linux

Learn how to set Linux process affinity with taskset, systemd, numactl, Docker, and Kubernetes using clear examples.

Linux is wonderfully democratic about CPU time. Left alone, the scheduler will move tasks around,
balance load, chase cache locality, and generally behave like a very caffeinated traffic cop.
Most of the time, that is exactly what you want. But sometimes you need a specific process to run
only on certain CPU cores. Maybe you are tuning a low-latency service, testing benchmark results,
isolating a noisy workload, running a game server, or trying to keep your laptop fan from auditioning
for a jet engine.

That is where process affinity on Linux comes in. CPU affinity tells the Linux scheduler
which CPUs a process or thread is allowed to run on. It does not magically make bad code fast, and it
will not turn a potato server into a supercomputer, but it can improve predictability, reduce cache
thrashing, and help you keep critical workloads away from background chaos.

In this guide, you will learn how to set process affinity on Linux using practical commands such as
taskset, how to check CPU affinity with /proc, how to use numactl for
NUMA-aware systems, and when to manage affinity through systemd, Docker, or Kubernetes. We will also
cover common mistakes, real-world examples, and hands-on experience from Linux tuning work where one
wrong CPU mask can make a production box behave like it just heard bad news.

What Is Process Affinity in Linux?

Process affinity, also called CPU affinity or processor affinity,
is a scheduling setting that limits a process or thread to a specific set of CPUs. On a machine with
eight logical CPUs numbered 0 through 7, you might allow a process to run only on
CPUs 2 and 3. The Linux scheduler will then choose from that allowed set instead
of using the entire machine.

This matters because modern CPUs are not just “one big pile of compute.” They have cores, hardware
threads, sockets, NUMA nodes, shared caches, and sometimes performance and efficiency cores. Moving a
process from one CPU to another can affect cache warmth, memory locality, latency, and throughput.
The scheduler is smart, but it is not psychic. If you know more about your workload than the kernel
can infer, affinity gives you a steering wheel.

When Should You Set CPU Affinity?

You should set Linux CPU affinity when you have a specific performance, isolation, or troubleshooting
goal. Randomly pinning processes “because tuning sounds cool” is how servers end up with trust issues.
Affinity is useful when you need more predictable latency, cleaner benchmark results, workload separation,
or better NUMA locality.

Good Use Cases

Common examples include pinning a database helper process away from web workers, reserving CPUs for
real-time audio or trading workloads, keeping a CPU-hungry batch job off interactive services, assigning
emulator threads to selected cores, or testing whether performance changes when a workload stays on one
CPU group.

CPU affinity is also helpful in benchmarking. If a test process bounces across cores during a run,
cache effects and scheduler migration can make results noisy. Pinning the benchmark to a fixed CPU set
can make measurements easier to compare. It will not make every benchmark “more true,” but it removes
one source of surprise from the soup.

Bad Use Cases

Do not use affinity as a first response to every performance problem. If your service is slow because
of inefficient queries, low memory, disk I/O, lock contention, or a wildly ambitious logging level,
CPU pinning is basically putting racing stripes on a shopping cart. It may look technical, but the cart
is still a cart.

Also be careful with highly dynamic workloads. A process pinned to too few CPUs can become artificially
bottlenecked while the rest of the system sits idle. Affinity is a boundary, not a boost button.

Understanding Linux CPU Numbering

Before setting process affinity, you need to know how Linux numbers CPUs. Linux typically starts logical
CPU numbering at 0. A four-core processor with simultaneous multithreading may show eight
logical CPUs: 0-7. These logical IDs are what tools like taskset, lscpu,
systemd, and container runtimes use.

Run this command to inspect your CPU layout:

Look for fields such as CPU count, threads per core, cores per socket, sockets, NUMA nodes, and online
CPU lists. For a more compact view of available logical CPUs, try:

On many systems, sibling CPU numbers may share a physical core. Pinning a latency-sensitive task to
CPU 2 while another hot task runs on its sibling hardware thread may not isolate as much as
you think. For serious tuning, understand the topology before assigning CPUs.

The Fastest Way: Set Process Affinity with taskset

The most common tool for setting process affinity on Linux is taskset. It is part of the
util-linux package on many distributions and is usually already installed. If not, install it using your
package manager.

Check the Affinity of a Running Process

First, find the process ID:

Then check its CPU affinity:

You may see output like this:

The value ff is a hexadecimal bitmask. If your brain just made a tiny escape attempt,
do not worry. You can use a friendlier CPU list format with -c.

Example output:

That means the process is allowed to run on logical CPUs 0 through 7.

Set Affinity for a Running Process

To pin process 12345 to CPU 2, run:

To allow it to run on CPUs 2, 3, and 4:

To use a comma-separated list:

The -p option means you are modifying an existing process, and -c lets you use
human-readable CPU numbers instead of hexadecimal masks. Humans invented hex masks, then immediately
invented -c because humans also enjoy mercy.

Start a New Process with CPU Affinity

You can also launch a command with affinity already set:

Or run a CPU-heavy compression job only on CPUs 6 and 7:

This is a clean way to control short-lived jobs without chasing their process IDs after they start.

CPU Lists vs Hex Masks

Linux affinity can be expressed as a CPU list or a hexadecimal mask. A CPU list is easier for everyday
use:

A hexadecimal mask represents CPUs as bits. CPU 0 is bit 0, CPU 1 is bit 1,
and so on. For example, mask 1 means CPU 0, mask 2 means CPU
1, mask 3 means CPUs 0 and 1, and mask ff
means CPUs 0-7.

Unless you are scripting low-level behavior or reading old documentation, use CPU lists. They are clearer,
easier to review, and less likely to cause the classic “I pinned it to the wrong core and now everyone
is looking at me” incident.

Check Affinity Through /proc

Linux exposes process details through the /proc filesystem. To check affinity for a process,
inspect /proc/<PID>/status:

Example:

You can also see the hexadecimal mask:

The list format is usually easier to understand, while the mask is useful when comparing against tools
or APIs that report affinity as bitsets.

Important Detail: Processes, Threads, and Affinity

On Linux, CPU affinity is applied at the thread level. Many tools make this feel like process affinity,
but a multi-threaded application may have several threads, each with its own schedulable identity. When
you set affinity on a process ID, you may need to verify whether all threads inherited or retained the
expected mask.

To view threads for a process:

You can inspect thread-specific affinity under:

Each thread has its own task directory. For careful tuning, especially with Java, databases, media
applications, or high-performance workloads, check individual threads instead of assuming the main PID
tells the whole story.

Using numactl for NUMA-Aware Affinity

On larger servers, CPU affinity is only part of the story. NUMA, or Non-Uniform Memory Access, means
memory is divided into nodes that are closer to some CPUs than others. If a process runs on CPUs in one
NUMA node but constantly accesses memory from another, performance may suffer.

Use numactl to view NUMA topology:

Run a command on CPUs from a specific NUMA node:

Bind both CPU execution and memory allocation to node 0:

This can help databases, scientific workloads, analytics jobs, and high-throughput services. However,
memory binding can backfire if the node runs out of memory or if the workload needs more flexibility.
NUMA tuning is powerful, but it is not a seasoning you sprinkle everywhere like performance paprika.

Set CPU Affinity for systemd Services

Many production Linux services are managed by systemd. Instead of manually running taskset
after every restart, set affinity in the service configuration.

Create an override file:

Add:

Then reload and restart:

Check the property:

This approach is cleaner than ad hoc shell scripts because the affinity setting travels with the service.
It also survives restarts, which is useful because production services have a habit of restarting at the
least poetic moment.

Set CPU Affinity for Docker Containers

Containers can also be restricted to selected CPUs. With Docker, use --cpuset-cpus:

Or use a range:

This does not merely set a nice suggestion. It restricts which CPUs the container can run on through
the kernel’s CPU set mechanisms. It is useful for keeping containers from trampling each other on busy
hosts, especially when one container thinks “background worker” means “consume the universe.”

CPU Pinning in Kubernetes

In Kubernetes, CPU affinity is usually handled through resource requests, limits, QoS classes, and the
CPU Manager. With the static CPU Manager policy, Kubernetes can assign exclusive CPUs to eligible
containers, typically those in the Guaranteed QoS class with integer CPU requests.

A simplified container resource example looks like this:

Kubernetes CPU pinning is not the same as running taskset inside a random pod. In orchestrated
environments, the node agent and container runtime manage CPU sets. Manual changes inside containers may
be overwritten, blocked, or misleading. For serious Kubernetes tuning, configure CPU Manager policies at
the node level and test placement carefully.

How CPU Affinity Interacts with cpusets and cgroups

A common surprise is that affinity cannot grant access to CPUs outside the process’s allowed cpuset.
If a cgroup restricts a service to CPUs 0-3, trying to pin it to CPU 7 will not
work the way you hope. The kernel enforces cpuset boundaries.

This matters in containers, systemd slices, Kubernetes pods, and high-performance environments where
administrators divide CPUs between workloads. If taskset appears to accept a command but the
process does not run where expected, check the surrounding cgroup or cpuset configuration.

Practical Examples

Example 1: Pin a Backup Job to Background CPUs

Suppose CPUs 0-3 handle interactive services, and CPUs 4-7 are safer for background
work:

This keeps the backup process from competing directly with latency-sensitive services.

Example 2: Move a Running Process Away from CPU 0

CPU 0 often handles a lot of general system activity on some machines. To move a process to
CPUs 2 and 3:

Verify:

Example 3: Start a Test Server on One CPU

To test how a service behaves under a single logical CPU:

This can reveal whether the application depends on parallelism or whether a single-thread bottleneck
is hiding behind multiple worker processes.

Best Practices for Linux Process Affinity

Start by measuring before and after. Use tools such as top, htop, pidstat,
perf, application metrics, and latency dashboards. Affinity tuning without measurement is
basically astrology with root permissions.

Avoid pinning everything. Leave the scheduler room to balance normal workloads. Reserve affinity for
workloads that need isolation, predictable latency, or controlled experiments. Document every CPU mask
you set, especially on production servers, because future you will not remember why CPU 6
became sacred.

Be aware of CPU topology. On systems with hyperthreading, two logical CPUs may share one physical core.
On NUMA systems, CPUs and memory nodes have locality relationships. On virtual machines, the CPU topology
reported by Linux may reflect the guest configuration rather than the physical host.

Test under realistic load. A CPU affinity setting that looks perfect during a quiet afternoon may behave
differently during peak traffic, backups, log rotation, batch processing, and whatever mysterious cron job
someone created in 2019 and named final_final2.sh.

Common Mistakes and How to Avoid Them

Using the Wrong CPU Number

CPU numbering starts at 0. On a four-CPU system, valid logical CPUs are usually
0, 1, 2, and 3, not 1 through 4.
Always confirm with lscpu.

Confusing CPU Affinity with CPU Priority

Affinity controls where a process may run. It does not control how important the process is. For priority,
look at nice, renice, real-time scheduling policies, and cgroup CPU weights or
quotas. Affinity chooses the lanes; priority affects how aggressively the process gets to drive.

Pinning to Too Few CPUs

If a multi-threaded workload needs eight CPUs and you pin it to two, performance may drop. Sometimes that
is intentional, such as when containing a background job. But if your goal is speed, do not accidentally
turn a racehorse into a hallway.

Ignoring cgroup Limits

In containers or systemd-managed environments, cgroups may already restrict CPU access. Check both the
process affinity and the cgroup configuration when results are confusing.

Advanced Option: Use sched_setaffinity in Code

Developers can set affinity programmatically with the Linux sched_setaffinity() system call.
This is useful for applications that manage worker threads directly, such as low-latency servers,
simulation software, media engines, and specialized compute tools.

A simplified C example:

Passing 0 as the process ID applies the setting to the calling thread. In multi-threaded
programs, you may need to set affinity for each worker thread intentionally.

Troubleshooting: Why Did taskset Fail?

If taskset fails, check permissions first. Changing another user’s process may require root
privileges. Next, confirm the CPU number exists and is online. Then check whether a cpuset or container
boundary blocks access to the requested CPU.

Useful commands include:

If the process is managed by systemd, Docker, Kubernetes, or another supervisor, set affinity at the
supervisor level whenever possible. Otherwise, your manual setting may vanish after restart, redeploy,
or rescheduling.

Real-World Experience: What Setting Process Affinity on Linux Teaches You

After working with Linux affinity in real systems, the first lesson is simple: CPU pinning is most useful
when you know exactly what problem you are solving. It is tempting to treat taskset like a
magic performance wand. Run a command, pin a process, feel powerful, maybe whisper “optimization” at the
monitor. But the best results come from clear goals: reduce jitter, isolate a noisy neighbor, stabilize
benchmark data, or align CPU and memory locality.

One practical experience is that affinity often improves consistency before it improves raw speed.
For example, a service might not become dramatically faster after being pinned to CPUs 2-5,
but its latency graph may become less dramatic. Fewer spikes can matter more than a small average-speed
gain. Users rarely complain that the average was fine; they complain when one request takes five seconds
and makes the application feel haunted.

Another lesson is that CPU topology matters more than beginners expect. On a small laptop, pinning to
CPU 1 may be good enough for testing. On a dual-socket server, that same casual approach can
create strange results. A process may run on one socket while its memory lives closer to another socket.
The code still works, but performance may wobble. That is when numactl --hardware becomes
less of an optional command and more of a flashlight in a basement.

In container environments, the biggest surprise is that the host still matters. A process inside a
container may report only the CPUs allowed by its cpuset. Running taskset inside the container
can show a limited world, while the host controls the real boundaries. For Docker, setting
--cpuset-cpus at launch is usually cleaner than modifying processes after the fact. For
Kubernetes, node CPU Manager settings and pod resource definitions are the proper place to solve the
problem. Manual pinning inside a pod can become a tiny rebellion against the orchestrator, and the
orchestrator usually wins.

Affinity is also excellent for protecting interactive work. On development machines, you can push a
compile, compression job, emulator, or local test suite onto selected CPUs and leave the rest for your
desktop. The machine feels less sluggish, and you spend less time wondering why typing in a terminal has
the emotional pace of a fax machine. This does not reduce total CPU work, but it shapes where the work
lands.

The final experience-based tip is to document everything. CPU affinity settings are invisible enough to
be forgotten and powerful enough to cause confusion months later. Add comments in systemd overrides,
deployment manifests, runbooks, or tuning notes. Include the reason, the date, the expected CPU range,
and how to verify it. When a future engineer asks why a service avoids CPU 0, “because Dave
once saw a latency spike” is not a strategy. Clear notes save time, prevent accidental regressions, and
make performance tuning look like engineering instead of folklore with shell commands.

Conclusion

Learning how to set process affinity on Linux gives you more control over how workloads
use CPU resources. The fastest everyday tool is taskset, especially with the readable
-c CPU list format. For persistent services, use systemd’s CPUAffinity. For
NUMA-aware workloads, consider numactl. For containers and clusters, manage CPU sets through
Docker, Kubernetes, or your platform’s resource controls.

The golden rule is simple: measure first, pin carefully, verify afterward, and document your choices.
Linux already has a capable scheduler, so your job is not to outsmart it for sport. Your job is to give
it better boundaries when your workload genuinely needs them.

Starvibedaily Blog Information

Privacy Policy Terms of Service Cookie Policy Do Not Sell or Share My Info Editorial Independence Statement Accessibility Statement About US Send Us a Tip
© 2010 - 2026 Starvibedaily Blog Insights. All Rights Reserved.
Starvibedaily Blog Smart Insurance Guide – Compare Car, Home & Health Insurance
Email [email protected]