sched_setaffinity(2)
Set the set of CPUs a thread may run on (taskset is the CLI wrapper).
- Since
- Linux 2.5.8check your kernel →
- glibc
- glibc 2.3
- System
- Linux
- Man page
- sched_setaffinity(2)
Synopsis
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <sched.h>
int sched_setaffinity(pid_t pid, size_t cpusetsize,
const cpu_set_t *mask);
int sched_getaffinity(pid_t pid, size_t cpusetsize,
cpu_set_t *mask);Rod's take
The scheduler can do its job perfectly and still trash your L3 by shuffling a hot thread across cores every few hundred milliseconds. sched_setaffinity, usually through taskset, pins it. Know your topology first: hyperthread siblings share a core, and another socket means every cache miss crosses the NUMA interconnect. Affinity says nothing about where memory lands; that's numactl's job. Mind that it's per-thread, so pinning a running PID without -a leaves its other threads wherever they were. And profile first. Pinning without evidence is chasing shadows and adding complexity you'll forget about in six months.
Flags and arguments that matter
| Name | What it does |
|---|---|
| pid | A thread ID, not a whole process; 0 means the calling thread. Other threads keep their own masks. |
| cpusetsize | Size of mask in bytes; normally sizeof(cpu_set_t). |
| mask | cpu_set_t built with the CPU_SET(3) macros. If the thread isn't on an allowed CPU it gets migrated. |
Errors you will actually hit
| errno | Meaning |
|---|---|
| EINVAL | mask has no CPUs that are physically present and permitted by cpuset cgroups. |
| EPERM | Caller's EUID doesn't match the target's real/effective UID and it lacks CAP_SYS_NICE. |
| ESRCH | No thread with that ID. |
| EFAULT | A supplied memory address was invalid. |
Example
lscpu -e # topology: node, socket, core, HT siblings
taskset -c 0-3 ./myapp # launch pinned to CPUs 0-3
taskset -cp "$pid" # read current affinity
taskset -a -cp 0-7 "$pid" # re-pin every thread of a running process
# CPU and memory both on NUMA node 0
numactl --cpunodebind=0 --membind=0 ./myappTrimmed from the full walkthrough in taskset pins a process to specific CPUs. numactl keeps its memory local too..
BSD equivalent
FreeBSD: cpuset_setaffinity(2) (FreeBSD 7.1) and the cpuset(1) tool. OpenBSD: none.
The long version, from the console
Sources
Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.
