Processor affinity: Difference between revisions

From Wikipedia, the free encyclopedia
Jump to navigation Jump to search
imported>Suruena
Put in bold face "cache affinity"
 
Line 3: Line 3:
In [[computer science]], '''processor affinity''', also called '''CPU pinning''' or '''cache affinity''', enables the binding and unbinding of a [[Process (computing)|process]] or a [[Thread (computing)|thread]] to a [[central processing unit]] (CPU) or a range of CPUs, so that the process or thread will execute only on the designated CPU or CPUs rather than any CPU. This can be viewed as a modification of the native central queue [[scheduling algorithm]] in a [[symmetric multiprocessing]] operating system. Each item in the queue has a tag indicating its kin [[central processing unit|processor]]. At the time of resource allocation, each task is allocated to its kin processor in preference to others.
In [[computer science]], '''processor affinity''', also called '''CPU pinning''' or '''cache affinity''', enables the binding and unbinding of a [[Process (computing)|process]] or a [[Thread (computing)|thread]] to a [[central processing unit]] (CPU) or a range of CPUs, so that the process or thread will execute only on the designated CPU or CPUs rather than any CPU. This can be viewed as a modification of the native central queue [[scheduling algorithm]] in a [[symmetric multiprocessing]] operating system. Each item in the queue has a tag indicating its kin [[central processing unit|processor]]. At the time of resource allocation, each task is allocated to its kin processor in preference to others.


Processor affinity takes advantage of the fact that remnants of a process that was run on a given processor may remain in that processor's state (for example, data in the [[CPU cache|cache memory]]) after another process was run on that processor. Scheduling a CPU-intensive process that has few interrupts to execute on the same processor may improve its performance by reducing degrading events such as [[cache miss]]es, but may slow down ordinary programs because they would need to wait for that CPU to become available again.<ref>{{cite web|url=https://www.ibm.com/docs/en/aix/7.2?topic=architecture-processor-affinity-binding|title=Processor affinity and binding|website=[[IBM]] |access-date=2021-06-08}}</ref> A practical example of processor affinity is executing multiple instances of a non-threaded application, such as some graphics-rendering software. {{citation needed|date=June 2021}}
Scheduling-algorithm implementations vary in adherence to processor affinity. Under certain circumstances, some implementations will allow a task to change to another processor if it results in higher efficiency. For example, when two processor-intensive tasks (A and B) have affinity to one processor while another processor remains unused, many schedulers will shift task B to the second processor in order to maximize processor use. Task B will then acquire affinity with the second processor, while task A will continue to have affinity with the original processor.{{citation needed|date=June 2021}}
 
On most operating systems, the set of processors a process or thread is allowed (or preferred) to run on is expressed as an '''affinity mask''', which is a [[mask (computing)|bit mask]] corresponding to the system's cores.<ref name=":0">{{Cite web |date=January 27, 2022 |title=SetThreadAffinityMask function (winbase.h) - Win32 apps |url=https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setthreadaffinitymask |access-date=April 7, 2023 |website=learn.microsoft.com |language=en-us}}</ref>
 
== Purpose ==
There are several reasons for processor affinity to be used.
 
=== Locality of cache and memory ===
The execution of a thread may be interrupted by the OS scheduler to make space for other programs or threads during an interrupt. If the thread was later dispatched to the processor it was previously running on, there may be some remaining data in the [[CPU cache]] that can be reused, allowing for fewer [[cache miss]]es. Setting the processor affinity would make sure the thread always runs on the same processor(s), but at the same time forces it to wait for the processor(s) to become available again. This feature is especially useful for CPU-intensive processes with few interrupts. Doing the same to an ordinary program might instead slow it down as they tend to be interrupted more frequently and end up waiting more.<ref name=aix>{{cite web|url=https://www.ibm.com/docs/en/aix/7.2?topic=architecture-processor-affinity-binding|title=Processor affinity and binding|website=[[IBM]] |access-date=2021-06-08}}</ref> A practical example of processor affinity is executing multiple instances of a single-threaded application, such as some graphics-rendering software.{{citation needed|date=June 2021}}
 
On CPUs with [[simultaneous multi-threading]] (SMT, also loosely known as [[hyper-threading]], a [[genericized trademark]] of Intel), the two or more "threads" (logical processors, "virtual cores") on a physical core share the L1 and L2 caches. As far as affinity for locality purposes is concerned, they are identical.<ref name=tmurgent>[http://www.tmurgent.com/WhitePapers/ProcessorAffinity.pdf "White Paper - Processor Affinity"] - From [http://www.tmurgent.com tmurgent.com]. Accessed 2007-07-06.</ref>


Scheduling-algorithm implementations vary in adherence to processor affinity. Under certain circumstances, some implementations will allow a task to change to another processor if it results in higher efficiency. For example, when two processor-intensive tasks (A and B) have affinity to one processor while another processor remains unused, many schedulers will shift task B to the second processor in order to maximize processor use. Task B will then acquire affinity with the second processor, while task A will continue to have affinity with the original processor.{{citation needed|date=June 2021}}
On [[non-uniform memory access]] (NUMA) systems a similar problem exists, except the latency comes not from L1/L2 cache misses, but from L3 misses and cross-node memory access. Constraining all threads of a program to the same NUMA node (or at least the same CPU socket) would ensure they can share their L3 caches. Additional configuration may be necessary to ensure that memory is allocated from the local NUMA node.<ref>{{cite web |title=Chapter 27. Configuring CPU Affinity and NUMA policies using systemd |url=https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/8/html/managing_monitoring_and_updating_the_kernel/assembly_configuring-cpu-affinity-and-numa-policies-using-systemd_managing-monitoring-and-updating-the-kernel}}</ref>


==Usage==
=== Division of resources ===
Processor affinity can effectively reduce cache problems, but it does not reduce the persistent [[Load balancing (computing)|load-balancing]] problem.<ref>[http://www.tmurgent.com/WhitePapers/ProcessorAffinity.pdf "White Paper - Processor Affinity"] - From [http://www.tmurgent.com tmurgent.com]. Accessed 2007-07-06.</ref> Also note that processor affinity becomes more complicated in systems with non-uniform architectures. For example, a system with two [[Multi-core processor|dual-core]] [[hyper-threading|hyper-threaded]] [[Central processing unit|CPUs]] presents a challenge to a scheduling algorithm.
Processor affinity also enforces a static division of processing resources. As a result, it can be used to limit the amount of CPU cores used by a CPU-intensive process, leaving other cores available for the other programs to use. This is, of course, not optimal, as it would leave resources completely unused when there are no other programs running as well as still allow other programs to compete with the CPU-intensive program for resources on the few cores it's allowed to run on. More advanced methods to divide resources include CPU priority settings, CPU utilization shares, and hard utilization percentage limits.<ref>{{cite web |title=Chapter 24. Using cgroups-v2 to control distribution of CPU time for applications {{!}} Managing, monitoring, and updating the kernel {{!}} Red Hat Enterprise Linux {{!}} 8 {{!}} Red Hat Documentation |url=https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/8/html/managing_monitoring_and_updating_the_kernel/using-cgroups-v2-to-control-distribution-of-cpu-time-for-applications_managing-monitoring-and-updating-the-kernel |website=docs.redhat.com}}</ref><ref name=tmurgent/>


There is complete affinity between two virtual CPUs implemented on the same core via hyper-threading, partial affinity between two cores on the same physical processor (as the cores share some, but not all, cache), and no affinity between separate physical processors. As other resources are also shared, processor affinity alone cannot be used as the basis for CPU dispatching. If a process has recently run on one virtual hyper-threaded CPU in a given core, and that virtual CPU is currently busy but its partner CPU is not, cache affinity would suggest that the process should be dispatched to the idle partner CPU. However, the two virtual CPUs compete for essentially all computing, cache, and memory resources. In this situation, it would typically be more efficient to dispatch the process to a different core or CPU, if one is available. This could incur a penalty when process repopulates the cache, but overall performance could be higher as the process would not have to compete for resources within the CPU.{{citation needed|date=June 2021}}
Again on CPUs with SMT, non-SMT-aware schedulers might make the mistake of scheduling work on a non-busy core with a busy partner when non-busy physical cores are present. This would cause unnecessary competition for resources between the two threads. As a result, multithreaded CPU-intensive programs often manually assign the affinity of its threads to make sure they do not end fighting over the same physical core.<ref>{{cite web |title=Thread Affinity Interface |url=https://www.intel.com/content/www/us/en/docs/dpcpp-cpp-compiler/developer-guide-reference/2023-0/thread-affinity-interface.html |website=Intel |language=en}}</ref>


==Specific operating systems==
==Specific operating systems==
On [[Linux]], the CPU affinity of a process can be altered with the taskset(1) program<ref>{{man|1|taskset|Linux}}</ref> and the sched_setaffinity(2) system call. The affinity of a thread can be altered with one of the library functions: pthread_setaffinity_np(3) or pthread_attr_setaffinity_np(3).
 
=== Unix-like ===
On [[Linux]], the CPU affinity of a process can be altered with the taskset(1) program<ref>{{man|1|taskset|Linux}}</ref> and the sched_setaffinity(2) system call. The affinity of a thread can be altered with one of the library functions: <code>pthread_setaffinity_np</code>(3) or <code>pthread_attr_setaffinity_np</code>(3).


On [[Silicon Graphics|SGI]] systems, [https://web.archive.org/web/20070701091047/http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=linux&db=man&fname=%2Fusr%2Fshare%2Fcatman%2Fman1%2Fdplace.1.html dplace] binds a process to a set of CPUs.<ref>[http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=linux&db=man&fname=/usr/share/catman/man1/dplace.1.html dplace.1] {{webarchive|url=https://web.archive.org/web/20070701091047/http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=linux&db=man&fname=%2Fusr%2Fshare%2Fcatman%2Fman1%2Fdplace.1.html |date=2007-07-01 }} - From ''[http://www.sgi.com sgi.com]''. Accessed 2007-07-06.</ref>
On [[Silicon Graphics|SGI]] systems, [https://web.archive.org/web/20070701091047/http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=linux&db=man&fname=%2Fusr%2Fshare%2Fcatman%2Fman1%2Fdplace.1.html dplace] binds a process to a set of CPUs.<ref>[http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=linux&db=man&fname=/usr/share/catman/man1/dplace.1.html dplace.1] {{webarchive|url=https://web.archive.org/web/20070701091047/http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=linux&db=man&fname=%2Fusr%2Fshare%2Fcatman%2Fman1%2Fdplace.1.html |date=2007-07-01 }} - From ''[http://www.sgi.com sgi.com]''. Accessed 2007-07-06.</ref>


On [[DragonFly BSD]] 1.9 (2007) and later versions, usched_set system call can be used to control the affinity of a process.<ref>{{cite web |url= http://mdoc.su/d/usched_set.2 |title= <code>usched_set(2)</code> — setting up a proc's usched |work= DragonFly System Calls Manual |publisher= [[DragonFly BSD]] |access-date= 2019-07-28 }}</ref><ref>{{cite web |url= http://bxr.su/d/sys/kern/kern_usched.c#sys_usched_set |title= <code>kern/kern_usched.c § sys_usched_set</code> |website= BSD Cross Reference |publisher= [[DragonFly BSD]] |access-date= 2019-07-28 }}</ref> On [[NetBSD]] 5.0, [[FreeBSD]] 7.2, [[DragonFly BSD]] 4.7 and later versions can use pthread_setaffinity_np and pthread_getaffinity_np.<ref><code>{{URL|http://mdoc.su/n,f,d/pthread_setaffinity_np.3|pthread_setaffinity_np(3)}}</code> – [[NetBSD]], [[FreeBSD]] and [[DragonFly BSD]] Library Functions Manual</ref> In [[NetBSD]], the psrset utility<ref>{{man|8|psrset|NetBSD}}</ref> to set a thread's affinity to a certain CPU set. In [[FreeBSD]], cpuset<ref>{{man|1|cpuset|FreeBSD}}</ref> utility is used to create CPU sets and to assign processes to these sets. In [[DragonFly BSD]] 3.1 (2012) and later, usched utility can be used for assigning processes to a certain CPU set.<ref>{{cite web |url= http://mdoc.su/d/usched.8 |title= <code>usched(8)</code> — run a program with a specified userland scheduler and cpumask |work= DragonFly System Manager's Manual |publisher= [[DragonFly BSD]] |access-date= 2019-07-28 }}</ref>
On [[NetBSD]] 5.0, [[FreeBSD]] 7.2, [[DragonFly BSD]] 4.7 and later versions can use <code>pthread_setaffinity_np</code> and <code>pthread_getaffinity_np</code>.<ref><code>{{URL|http://mdoc.su/n,f,d/pthread_setaffinity_np.3|pthread_setaffinity_np(3)}}</code> – [[NetBSD]], [[FreeBSD]] and [[DragonFly BSD]] Library Functions Manual</ref> In [[NetBSD]], the psrset utility<ref>{{man|8|psrset|NetBSD}}</ref> to set a thread's affinity to a certain CPU set. In [[FreeBSD]], cpuset<ref>{{man|1|cpuset|FreeBSD}}</ref> utility is used to create CPU sets and to assign processes to these sets.
 
On [[DragonFly BSD]] 1.9 (2007) and later versions, <code>usched_set</code> system call can be used to control the affinity of a process.<ref>{{cite web |url= http://mdoc.su/d/usched_set.2 |title= <code>usched_set(2)</code> — setting up a proc's usched |work= DragonFly System Calls Manual |publisher= [[DragonFly BSD]] |access-date= 2019-07-28 }}</ref><ref>{{cite web |url= http://bxr.su/d/sys/kern/kern_usched.c#sys_usched_set |title= <code>kern/kern_usched.c § sys_usched_set</code> |website= BSD Cross Reference |publisher= [[DragonFly BSD]] |access-date= 2019-07-28 }}</ref> In [[DragonFly BSD]] 3.1 (2012) and later, usched utility can be used for assigning processes to a certain CPU set.<ref>{{cite web |url= http://mdoc.su/d/usched.8 |title= <code>usched(8)</code> — run a program with a specified userland scheduler and cpumask |work= DragonFly System Manager's Manual |publisher= [[DragonFly BSD]] |access-date= 2019-07-28 }}</ref>
 
On [[Solaris (operating system)|Solaris]] it is possible to control bindings of processes and LWPs to processor using the pbind(1)<ref>[http://docs.oracle.com/cd/E23824_01/html/821-1462/pbind-1m.html pbind(1M)] - Solaris man page</ref> program. To control the affinity programmatically processor_bind(2)<ref>[http://docs.oracle.com/cd/E19109-01/tsolaris8/817-0881/6mglbsoma/index.html processor_bind(2)] - Solaris man page</ref> can be used. There are more generic interfaces available such as pset_bind(2)<ref>[http://docs.oracle.com/cd/E26502_01/html/E29032/pset-bind-2.html#REFMAN2pset-bind-2 pset_bind(2)] - Oracle Solaris 11.1 Information Library - man pages section 2</ref> or lgrp_affinity_get(3LGRP)<ref>[http://docs.oracle.com/cd/E19120-01/open.solaris/820-1691/lgroups-193/index.html lgrp_affinity_get(3LGRP)] - Memory and Thread Placement Optimization Developer's Guide</ref> using processor set and locality groups concepts.
 
On [[IBM AIX|AIX]] it is possible to control bindings of processes using the bindprocessor command<ref name="processor-affinity-on-aix">{{cite web|url=https://www.ibm.com/developerworks/aix/library/au-processinfinity.html|title=Processor affinity on AIX|author1=Umesh Prabhakar Gaikwad|author2=Kailas S. Zadbuke|website=[[IBM]] |date=November 16, 2006}}</ref><ref>{{cite web|url=https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/b_commands/bindprocessor.html|title=bindprocessor Command|website=IBM}}</ref> and the bindprocessor() API.<ref name="processor-affinity-on-aix"/><ref>{{cite web|url=https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/b_bostechref/bindprocessor.html|title=bindprocessor Subroutine|website=IBM}}</ref> The AIX scheduler is SMT-aware and is able to switch the SMT states of the POWER7/8/9 cores from 1 to 8 threads to maximize throughput.<ref>{{cite web |title=POWER CPU Memory Affinity 3 - Scheduling processes to SMT and Virtual Processors |url=https://www.ibm.com/support/pages/power-cpu-memory-affinity-3-scheduling-processes-smt-and-virtual-processors |website=www.ibm.com |language=en |date=13 June 2023}}</ref>
 
==== macOS ====
[[macOS]] does not offer an API that manages the set of processors a process, task, or thread is allowed to run on. Instead it offers the Thread Affinity API, which tells the kernel which threads should be scheduled to share the same L2 cache, i.e. run on the same physical CPU core.<ref>{{cite web|url=https://developer.apple.com/library/mac/#releasenotes/Performance/RN-AffinityAPI/index.html|title=Thread Affinity API Release Notes|website=Developer.apple.com}}</ref> The [[XNU]] kernel internally translates each affinity tag to a set of allowed logical cores corresponding to a physical core. When a tag is set, it creates a Thread Affinity namespace when there is not one already. It then becomes bound to the core with the fewest tags already bound. A tag do not migrate between cores in XNU version 8792; as a result, so long as there are not more tags than there are physical cores, each tag will correspond to exactly one physical core. Namespaces as well as tags are inherited between parent and child processes.<ref>{{cite web |title=xnu/osfmk/kern/affinity.c at e3723e1f17661b24996789d8afc084c0c3303b26 · apple-oss-distributions/xnu |url=https://github.com/apple-oss-distributions/xnu/blob/e3723e1f17661b24996789d8afc084c0c3303b26/osfmk/kern/affinity.c |website=GitHub |language=en}}</ref>
 
The API is not available on arm64 (Apple Silicon), where {{code|ml_get_max_affinity_sets}} is hardcoded to return 0.<ref>XNU source code: xnu/osfmk/arm/cpu_affinity.h</ref>


=== Windows NT ===
On [[Windows NT]] and its successors, thread and process CPU affinities can be set separately by using SetThreadAffinityMask<ref>[http://msdn2.microsoft.com/en-us/library/ms686247(VS.85).aspx SetThreadAffinityMask] - [[MSDN Library]]</ref> and SetProcessAffinityMask<ref>[http://msdn2.microsoft.com/en-us/library/ms686223(VS.85).aspx SetProcessAffinityMask] - [[MSDN Library]]</ref> API calls or via the Task Manager interface (for process affinity only).
On [[Windows NT]] and its successors, thread and process CPU affinities can be set separately by using SetThreadAffinityMask<ref>[http://msdn2.microsoft.com/en-us/library/ms686247(VS.85).aspx SetThreadAffinityMask] - [[MSDN Library]]</ref> and SetProcessAffinityMask<ref>[http://msdn2.microsoft.com/en-us/library/ms686223(VS.85).aspx SetProcessAffinityMask] - [[MSDN Library]]</ref> API calls or via the Task Manager interface (for process affinity only).


[[macOS]] exposes an affinity API<ref>{{cite web|url=https://developer.apple.com/library/mac/#releasenotes/Performance/RN-AffinityAPI/index.html|title=Thread Affinity API Release Notes|website=Developer.apple.com}}</ref> that provides hints to the kernel how to schedule threads according to affinity sets.
Forcing of each [[OpenMP]] thread to distinct logical cores in Windows can be accomplished by means of the following [[C (programming language)|C]] code, with the [[Windows.h|{{mono|<Windows.h>}}]] header:
 
<syntaxhighlight lang="c">
On [[Solaris (operating system)|Solaris]] it is possible to control bindings of processes and LWPs to processor using the pbind(1)<ref>[http://docs.oracle.com/cd/E23824_01/html/821-1462/pbind-1m.html pbind(1M)] - Solaris man page</ref> program. To control the affinity programmatically processor_bind(2)<ref>[http://docs.oracle.com/cd/E19109-01/tsolaris8/817-0881/6mglbsoma/index.html processor_bind(2)] - Solaris man page</ref> can be used. There are more generic interfaces available such as pset_bind(2)<ref>[http://docs.oracle.com/cd/E26502_01/html/E29032/pset-bind-2.html#REFMAN2pset-bind-2 pset_bind(2)] - Oracle Solaris 11.1 Information Library - man pages section 2</ref> or lgrp_affinity_get(3LGRP)<ref>[http://docs.oracle.com/cd/E19120-01/open.solaris/820-1691/lgroups-193/index.html lgrp_affinity_get(3LGRP)] - Memory and Thread Placement Optimization Developer's Guide</ref> using processor set and locality groups concepts.
#include <Windows.h>
#include <omp.h>


On [[IBM AIX|AIX]] it is possible to control bindings of processes using the bindprocessor command<ref name="processor-affinity-on-aix">{{cite web|url=https://www.ibm.com/developerworks/aix/library/au-processinfinity.html|title=Processor affinity on AIX|author1=Umesh Prabhakar Gaikwad|author2=Kailas S. Zadbuke|website=[[IBM]] |date=November 16, 2006}}</ref><ref>{{cite web|url=https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/b_commands/bindprocessor.html|title=bindprocessor Command|website=IBM}}</ref> and the bindprocessor API.<ref name="processor-affinity-on-aix"/><ref>{{cite web|url=https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/b_bostechref/bindprocessor.html|title=bindprocessor Subroutine|website=IBM}}</ref>
// Set OpenMP thread affinity
void setThreadAffinity() {
    #pragma omp parallel default(shared)
    {
        DWORD_PTR mask = (DWORD_PTR)1 << omp_get_thread_num();
        SetThreadAffinityMask(GetCurrentThread(), mask);
    }
}
</syntaxhighlight>


== See also ==
== See also ==
* [[Affinity mask]]
* [[hwloc]]


== References ==
== References ==
{{reflist}}
{{reflist}}
== External links ==
*[http://msdn.microsoft.com/en-us/library/ms686247(VS.85).aspx MSDN article on SetThreadAffinityMask function]
*[https://web.archive.org/web/20041114215425/http://linuxcommand.org/man_pages/taskset1.html Taskset, a tool to set the affinity mask on Linux]
*[http://cpubalancer.brels.net/ CPU Balancer, a free, open-source utility that distributes Windows XP processes uniformly over logical processors using the affinity mask]


{{Processor scheduling}}
{{Processor scheduling}}
Line 37: Line 75:
[[Category:Processor scheduling algorithms]]
[[Category:Processor scheduling algorithms]]
[[Category:Load balancing (computing)]]
[[Category:Load balancing (computing)]]
[[Category:Job scheduling]]

Revision as of 07:26, 17 November 2025

Template:Short description Script error: No such module "Unsubst". In computer science, processor affinity, also called CPU pinning or cache affinity, enables the binding and unbinding of a process or a thread to a central processing unit (CPU) or a range of CPUs, so that the process or thread will execute only on the designated CPU or CPUs rather than any CPU. This can be viewed as a modification of the native central queue scheduling algorithm in a symmetric multiprocessing operating system. Each item in the queue has a tag indicating its kin processor. At the time of resource allocation, each task is allocated to its kin processor in preference to others.

Scheduling-algorithm implementations vary in adherence to processor affinity. Under certain circumstances, some implementations will allow a task to change to another processor if it results in higher efficiency. For example, when two processor-intensive tasks (A and B) have affinity to one processor while another processor remains unused, many schedulers will shift task B to the second processor in order to maximize processor use. Task B will then acquire affinity with the second processor, while task A will continue to have affinity with the original processor.Script error: No such module "Unsubst".

On most operating systems, the set of processors a process or thread is allowed (or preferred) to run on is expressed as an affinity mask, which is a bit mask corresponding to the system's cores.[1]

Purpose

There are several reasons for processor affinity to be used.

Locality of cache and memory

The execution of a thread may be interrupted by the OS scheduler to make space for other programs or threads during an interrupt. If the thread was later dispatched to the processor it was previously running on, there may be some remaining data in the CPU cache that can be reused, allowing for fewer cache misses. Setting the processor affinity would make sure the thread always runs on the same processor(s), but at the same time forces it to wait for the processor(s) to become available again. This feature is especially useful for CPU-intensive processes with few interrupts. Doing the same to an ordinary program might instead slow it down as they tend to be interrupted more frequently and end up waiting more.[2] A practical example of processor affinity is executing multiple instances of a single-threaded application, such as some graphics-rendering software.Script error: No such module "Unsubst".

On CPUs with simultaneous multi-threading (SMT, also loosely known as hyper-threading, a genericized trademark of Intel), the two or more "threads" (logical processors, "virtual cores") on a physical core share the L1 and L2 caches. As far as affinity for locality purposes is concerned, they are identical.[3]

On non-uniform memory access (NUMA) systems a similar problem exists, except the latency comes not from L1/L2 cache misses, but from L3 misses and cross-node memory access. Constraining all threads of a program to the same NUMA node (or at least the same CPU socket) would ensure they can share their L3 caches. Additional configuration may be necessary to ensure that memory is allocated from the local NUMA node.[4]

Division of resources

Processor affinity also enforces a static division of processing resources. As a result, it can be used to limit the amount of CPU cores used by a CPU-intensive process, leaving other cores available for the other programs to use. This is, of course, not optimal, as it would leave resources completely unused when there are no other programs running as well as still allow other programs to compete with the CPU-intensive program for resources on the few cores it's allowed to run on. More advanced methods to divide resources include CPU priority settings, CPU utilization shares, and hard utilization percentage limits.[5][3]

Again on CPUs with SMT, non-SMT-aware schedulers might make the mistake of scheduling work on a non-busy core with a busy partner when non-busy physical cores are present. This would cause unnecessary competition for resources between the two threads. As a result, multithreaded CPU-intensive programs often manually assign the affinity of its threads to make sure they do not end fighting over the same physical core.[6]

Specific operating systems

Unix-like

On Linux, the CPU affinity of a process can be altered with the taskset(1) program[7] and the sched_setaffinity(2) system call. The affinity of a thread can be altered with one of the library functions: pthread_setaffinity_np(3) or pthread_attr_setaffinity_np(3).

On SGI systems, dplace binds a process to a set of CPUs.[8]

On NetBSD 5.0, FreeBSD 7.2, DragonFly BSD 4.7 and later versions can use pthread_setaffinity_np and pthread_getaffinity_np.[9] In NetBSD, the psrset utility[10] to set a thread's affinity to a certain CPU set. In FreeBSD, cpuset[11] utility is used to create CPU sets and to assign processes to these sets.

On DragonFly BSD 1.9 (2007) and later versions, usched_set system call can be used to control the affinity of a process.[12][13] In DragonFly BSD 3.1 (2012) and later, usched utility can be used for assigning processes to a certain CPU set.[14]

On Solaris it is possible to control bindings of processes and LWPs to processor using the pbind(1)[15] program. To control the affinity programmatically processor_bind(2)[16] can be used. There are more generic interfaces available such as pset_bind(2)[17] or lgrp_affinity_get(3LGRP)[18] using processor set and locality groups concepts.

On AIX it is possible to control bindings of processes using the bindprocessor command[19][20] and the bindprocessor() API.[19][21] The AIX scheduler is SMT-aware and is able to switch the SMT states of the POWER7/8/9 cores from 1 to 8 threads to maximize throughput.[22]

macOS

macOS does not offer an API that manages the set of processors a process, task, or thread is allowed to run on. Instead it offers the Thread Affinity API, which tells the kernel which threads should be scheduled to share the same L2 cache, i.e. run on the same physical CPU core.[23] The XNU kernel internally translates each affinity tag to a set of allowed logical cores corresponding to a physical core. When a tag is set, it creates a Thread Affinity namespace when there is not one already. It then becomes bound to the core with the fewest tags already bound. A tag do not migrate between cores in XNU version 8792; as a result, so long as there are not more tags than there are physical cores, each tag will correspond to exactly one physical core. Namespaces as well as tags are inherited between parent and child processes.[24]

The API is not available on arm64 (Apple Silicon), where ml_get_max_affinity_sets is hardcoded to return 0.[25]

Windows NT

On Windows NT and its successors, thread and process CPU affinities can be set separately by using SetThreadAffinityMask[26] and SetProcessAffinityMask[27] API calls or via the Task Manager interface (for process affinity only).

Forcing of each OpenMP thread to distinct logical cores in Windows can be accomplished by means of the following C code, with the <templatestyles src="Mono/styles.css" /><Windows.h> header:

#include <Windows.h>
#include <omp.h>

// Set OpenMP thread affinity
void setThreadAffinity() {
    #pragma omp parallel default(shared)
    {
        DWORD_PTR mask = (DWORD_PTR)1 << omp_get_thread_num();
        SetThreadAffinityMask(GetCurrentThread(), mask);
    }
}

See also

References

<templatestyles src="Reflist/styles.css" />

  1. ↑ Script error: No such module "citation/CS1".
  2. ↑ Script error: No such module "citation/CS1".
  3. ↑ a b "White Paper - Processor Affinity" - From tmurgent.com. Accessed 2007-07-06.
  4. ↑ Script error: No such module "citation/CS1".
  5. ↑ Script error: No such module "citation/CS1".
  6. ↑ Script error: No such module "citation/CS1".
  7. ↑ taskset(1) – Linux User Manual – User Commands
  8. ↑ dplace.1 Script error: No such module "webarchive". - From sgi.com. Accessed 2007-07-06.
  9. ↑ Script error: No such module "URL".Script error: No such module "Check for unknown parameters". – NetBSD, FreeBSD and DragonFly BSD Library Functions Manual
  10. ↑ psrset(8) – NetBSD System Manager's Manual
  11. ↑ cpuset(1) – FreeBSD General Commands Manual
  12. ↑ Script error: No such module "citation/CS1".
  13. ↑ Script error: No such module "citation/CS1".
  14. ↑ Script error: No such module "citation/CS1".
  15. ↑ pbind(1M) - Solaris man page
  16. ↑ processor_bind(2) - Solaris man page
  17. ↑ pset_bind(2) - Oracle Solaris 11.1 Information Library - man pages section 2
  18. ↑ lgrp_affinity_get(3LGRP) - Memory and Thread Placement Optimization Developer's Guide
  19. ↑ a b Script error: No such module "citation/CS1".
  20. ↑ Script error: No such module "citation/CS1".
  21. ↑ Script error: No such module "citation/CS1".
  22. ↑ Script error: No such module "citation/CS1".
  23. ↑ Script error: No such module "citation/CS1".
  24. ↑ Script error: No such module "citation/CS1".
  25. ↑ XNU source code: xnu/osfmk/arm/cpu_affinity.h
  26. ↑ SetThreadAffinityMask - MSDN Library
  27. ↑ SetProcessAffinityMask - MSDN Library

Script error: No such module "Check for unknown parameters".

External links

Template:Processor scheduling