$RodHat_
Syscall reference · Processes

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

NameWhat it does
pidA thread ID, not a whole process; 0 means the calling thread. Other threads keep their own masks.
cpusetsizeSize of mask in bytes; normally sizeof(cpu_set_t).
maskcpu_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

errnoMeaning
EINVALmask has no CPUs that are physically present and permitted by cpuset cgroups.
EPERMCaller's EUID doesn't match the target's real/effective UID and it lacks CAP_SYS_NICE.
ESRCHNo thread with that ID.
EFAULTA 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 ./myapp

Trimmed 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

  1. sched_setaffinity(2), man7.org
  2. taskset(1), man7.org
  3. cpuset_setaffinity(2), FreeBSD

Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.