taskset Cheatsheet - CPU Affinity & Core Pinning Guide

taskset answers one question: which CPUs is this process allowed to run on. Three situations call for it. Latency spikes that do not come with high CPU utilisation, often caused by a multi-threaded process migrating across physical cores or touching memory on a remote NUMA node. Benchmark runs where you want to measure the code rather than the scheduler. And shared machines where pinning your workload to idle cores keeps a noisy neighbour from starving it. The mechanism is narrow, it just rewrites the task CPU affinity mask, which is why you can confirm the result at any time by reading Cpus_allowed_list from /proc/<pid>/status or from jobs -l. Pinning is not automatically faster: too few cores cuts parallelism, and pinning only the main thread of a threaded process achieves little, so the sheet lines up list format, hex masks, retargeting running processes, NUMA commands and the isolcpus kernel parameter for comparison.

SysOps·37 commands·Last updated 2026-07-21
tasksetcpuPerformance Tuning

Typical Use Case

For performance engineers isolating a noisy neighbour. taskset pins a process to a set of logical CPUs, which is the cheapest possible scheduling intervention - no kernel change, no cgroup, instant and reversible on a running PID. This sheet covers reading and writing affinity masks in both list and hexadecimal form, batch-changing every PID of a service, and the important boundary: taskset binds CPUs, not NUMA nodes, and inside a container it only sees the CPUs the cgroup actually granted.

Basic Usage 6

taskset -p <pid>
Show a process's CPU affinity mask
taskset -c -p <pid>
Show affinity in CPU-list format
taskset -c 0,1 <command>
Pin to CPUs 0 and 1 on launch
taskset -c 0-3 <command>
Pin to CPUs 0-3 on launch
taskset -p <mask> <pid>
Change a running process's CPU mask
taskset -cp 0,1 <pid>
Repin a running process to CPUs 0,1

CPU Mask & List Format 7

0x00000001
Hex mask: CPU 0
0x00000003
Hex mask: CPUs 0 and 1
0x0000000f
Hex mask: CPUs 0-3
-c 0
CPU-list format, more readable
-c 0,2,4
Specify discrete CPUs
-c 0-3,8-11
Mixed range list
taskset -c 0xff <command>
Bind to CPUs 0-7 with a hex mask

Pin Running Processes 4

taskset -cp 0 $(pgrep nginx)
Change the nginx master's affinity
for p in $(pgrep -f app); do taskset -cp 0-3 $p; done
Batch-repin matching processes
taskset -cp 0-3 <pid>
Bind a PID to CPUs 0-3
taskset -ap 0-1 <pid>
Set affinity for the process and all its threads

Affinity & System Info 5

cat /proc/<pid>/status | grep Cpus_allowed
View a process's CPU mask
cat /sys/devices/system/cpu/online
View online CPU numbers
nproc
View the number of available CPU cores
lscpu
View CPU architecture details (cores, cache, NUMA)
lscpu | grep NUMA
View NUMA node information

NUMA Optimization 5

numactl --hardware
View NUMA topology and node layout
numactl -c 0 -m 0 ./app
Bind CPU and memory to NUMA node 0
numactl --cpunodebind=0 --membind=0 ./app
Full NUMA binding (CPU + memory)
numastat -p <pid>
View a process's memory distribution per NUMA node
numactl --interleave=all ./app
Interleave memory across all nodes

Practical Scenarios 5

taskset -c 0-3 ./cpu_intensive_app
Limit an app to specific cores
taskset -c 4-7 ./realtime_app
Isolate cores for a real-time app
taskset -c 0 nginx
Pin Nginx workers to specific cores
taskset -c 1,2 mysql
Pin MySQL to specific cores
isolcpus=2,3
Kernel param: isolate CPUs 2,3 from scheduling at boot

Parameter matrix

ParameterEffectExample
-c <list>CPU-list form of the affinity mask; readable, accepts 0,1, 0-3 and mixed rangestaskset -c 0-3 <command>
-p <mask> <pid>Read or rewrite the affinity of a running process, no restart neededtaskset -cp 0,1 <pid>
0x0000000fHexadecimal mask form, equivalent to CPUs 0-3; taskset parses masks by defaulttaskset -c 0xff <command>
-aApply to every thread of the process, not just the main one - required for threaded servicestaskset -ap 0-1 <pid>
Cpus_allowed_listThe observable field in /proc/<pid>/status that confirms the binding took effectcat /proc/<pid>/status | grep Cpus_allowed

Common pitfalls

Symptomtaskset -cp 0,1 <pid> fails with "Invalid argument", or binding an out-of-range CPU fails outright.

CauseInside a container you see host CPU numbers but the real allowance comes from the cgroup; tasks outside it are refused by the kernel.

FixCheck cat /sys/devices/system/cpu/online and cat /proc/<pid>/status | grep Cpus_allowed first, then pick from that set.

SymptomAfter binding a threaded process, htop still shows threads on other cores.

CauseWithout -a only the main thread (the thread-group leader) is affected.

FixUse taskset -ap 0-1 <pid> to cover every thread.

SymptomPinning made latency worse because the process keeps reading memory across nodes.

Causetaskset pins CPUs but not memory; the process runs on node 1 cores while touching node 0 memory.

FixUse numactl -c 0 -m 0 ./app, or the full form numactl --cpunodebind=0 --membind=0 ./app.

Symptomtaskset -c 0-3 <command> refuses to start, saying the affinity set must contain an online CPU.

CauseThe range contains offline CPUs, or online CPU numbers are not contiguous from 0.

FixRead the real set with nproc and cat /sys/devices/system/cpu/online, then re-pick the values.

Troubleshooting

  1. 1Confirm the binding actually took effect

    cat /proc/<pid>/status | grep Cpus_allowed

    Cpus_allowed is the mask form, Cpus_allowed_list the list form; both must match taskset -p output.

  2. 2Change affinity for every process of a service

    for p in $(pgrep -f app); do taskset -cp 0-3 $p; done

    pgrep -f matches the command line; without -a only the main thread moves, so use taskset -ap 0-3 $p.

  3. 3Survey CPU and NUMA topology before pinning

    nproc && lscpu | grep NUMA && numactl --hardware

    You need the real online CPU set and node count, otherwise the mask is illegal.

  4. 4Watch per-core usage after pinning

    mpstat -P ALL 1

    Requires sysstat. Work should spread only across the intended cores; pidstat -t -p <pid> 1 shows thread-level detail.

Command Examples

Confine a CPU-bound application to CPUs 0-3

taskset -c 0-3 ./cpu_intensive_app

The application can never be scheduled outside CPUs 0-3, which effectively isolates it from other workloads on the box.

Pin MySQL to two discrete cores

taskset -c 1,2 mysql

Discrete entries and ranges can be mixed: write 0-3,8-11 when you want both styles in one mask.

Batch-pin every matching process to CPUs 0-3

for p in $(pgrep -f app); do taskset -cp 0-3 $p; done

When one parent spawns several children this changes each of them; pgrep -f matches the whole command line, so check that you are not sweeping in unrelated processes.

Verify the CPU mask a process really ended up with

cat /proc/12345/status | grep Cpus_allowed

The Cpus_allowed_list line is the kernel-side truth, and it settles arguments better than the command you remember typing.

Common Pitfalls

  • Record the original mask with taskset -p before you change anything, and restore exactly that value if the change turns out to be bad.
  • Always add -a for multithreaded services; pinning only the main thread leaves the remaining threads free to roam every core, so nothing is actually isolated.
  • Inside a container taskset can only bind CPUs the cgroup already granted you, and naming a CPU outside that range fails outright with Invalid argument.
  • An affinity set must contain at least one online CPU; if every CPU you name is offline, taskset refuses to run.
  • Overly tight pinning can backfire because cross-core memory traffic eats the gains, and on NUMA machines use numactl when CPU and memory must share a node.

Tips

  • CPU affinity reduces cache misses and boosts performance, but over-pinning can cause uneven load.
  • Real-time apps (HFT, A/V processing) suit isolated cores.
  • Under NUMA, binding CPU and memory nodes cuts cross-node access latency.
  • taskset -c's CPU-list format is more readable than hex masks; use it daily.
  • The isolcpus kernel param isolates CPUs at boot — more thorough than taskset but needs a reboot.
  • Multi-threaded processes need -a to set all threads, or only the main thread is affected.

FAQ

Does taskset bind CPU cores or NUMA nodes?

It binds a set of logical CPUs. With SMT enabled one physical core shows up as two logical CPUs, and logical CPUs are what taskset operates on. Pinning both CPU and memory to the same NUMA node is a different job entirely: that is numactl territory, for example numactl --cpunodebind=0 --membind=0, and you should read the topology with numactl --hardware before deciding.

What is the difference between taskset -c 0,1 command and taskset -cp 0,1 pid?

The first pins at launch: the process is confined to CPU 0 and 1 for as long as it lives, and the mask disappears when it exits. The second retargets an already running process: hand it an existing PID and the affinity changes immediately, no restart, while the process keeps running. Before you change it, run taskset -p on that PID to record the original mask so you can roll back.

I pinned a multithreaded service, so why does htop still show threads on other CPUs?

Without -a only the main thread gets the new mask; every other thread keeps the affinity it already had. To cover the whole process use taskset -ap 0-1 pid, where -a applies the change to every thread of that PID. To confirm what a thread really has, read Cpus_allowed under /proc/<pid>/status.

Which CPUs does the hex mask 0x0000000f actually cover?

Count from the low bit: bits 0 through 3 are set, so it means CPU 0, 1, 2 and 3, which is exactly the list form 0-3. Along the same logic 0x00000001 is CPU 0 alone, 0x00000003 is CPU 0 and 1, and 0xff covers CPU 0-7. Since masks have to be decoded by hand, the -c list format is the better everyday choice.

How do I confirm an affinity change actually took effect?

Read cat /proc/<pid>/status and grep for Cpus_allowed; the Cpus_allowed_list line is the set of CPUs the process is genuinely allowed on, and it has to match what you asked for. For the wider picture, htop shows per-core usage and mpstat -P ALL 1 shows per-core load in real time, so whether the cores actually separated is the most direct verdict.

Official References

Each command links to its official documentation below, so you can verify the latest usage and read deeper.

Maintained by LaoHand

Publicly updated on Jul 21, 2026, continuously proofread against official docs.

Contact Us

Wrong command or description? Send us corrections, business inquiries or product feedback by email.

Contact Us