Введение
Присвоение задачи определенному ядру CPU обеспечивает связывание и отвязывание процесса или потока от центрального процессора (CPU) или диапазона процессоров, так что процесс или поток будет выполняться только на назначенном процессоре или процессорах, а не на любом доступном. Это можно рассматривать как модификацию алгоритма планирования центральной очереди в симметричной многопроцессорной операционной системе. Каждый элемент в очереди имеет метку, указывающую его "родственный" процессор. При распределении ресурсов каждая задача предпочтительно назначается своему родному процессору. Аффинность процессора использует тот факт, что после выполнения процесса на данном процессоре, в его состоянии могут оставаться следы этого процесса (например, данные в кэш-памяти). Планирование вычислительно-интенсивного процесса с небольшим количеством прерываний для выполнения на одном и том же процессоре может повысить его производительность за счет снижения количества ухудшающих событий, таких как промахи кэша, но может замедлить работу обычных программ, которым придется ждать, пока этот процессор снова станет доступным. Практическим примером аффинности процессора является запуск нескольких экземпляров однопоточного приложения, например, некоторых программ для графического рендеринга. Реализации алгоритмов планирования по-разному реализуют аффинность процессора. В определенных ситуациях некоторые реализации могут разрешить задаче переключиться на другой процессор, если это приведет к повышению эффективности. Например, если две вычислительно-интенсивные задачи (A и B) имеют аффинность к одному процессору, а другой процессор остается неиспользованным, многие планировщики перенесут задачу B на второй процессор для максимального использования ресурсов. Задача B затем получит аффинность ко второму процессору, а задача A продолжит иметь аффинность к исходному процессору.
Processor affinity, or 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. 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 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 misses, but may slow down ordinary programs because they would need to wait for that CPU to become available again. A practical example of processor affinity is executing multiple instances of a non threaded application, such as some graphics rendering software. 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.
Использование
Аффинность процессора может эффективно снизить проблемы, связанные с кэшем, но не решает проблему постоянного балансирования нагрузки. Также следует учитывать, что аффинность процессора усложняется в системах с неоднородной архитектурой. Например, система с двумя двухъядерными гиперпоточными процессорами представляет собой задачу для алгоритма планирования. Существует полная аффинность между двумя виртуальными процессорами, реализованными на одном ядре посредством гиперпоточности, частичная аффинность между двумя ядрами на одном физическом процессоре (поскольку ядра совместно используют часть, но не весь кэш) и отсутствие аффинности между отдельными физическими процессорами. Поскольку другие ресурсы также являются общими, аффинность процессора не может служить единственным основанием для диспетчеризации задач. Если процесс недавно выполнялся на одном виртуальном гиперпоточном процессоре в данном ядре, и этот процессор в данный момент занят, а его парный процессор свободен, аффинность к кэшу предполагает, что процесс следует направить на неактивный парный процессор. Однако эти два виртуальных процессора конкурируют практически за все вычислительные ресурсы, кэш и память. В этой ситуации, как правило, более эффективно будет направить процесс на другое ядро или процессор, если таковые имеются. Это может повлечь за собой задержку при повторной загрузке кэша, но общая производительность может быть выше, поскольку процессу не придется конкурировать за ресурсы внутри процессора.
Специфические операционные системы
В Linux аффинность процессора процесса может быть изменена с помощью программы `taskset(1)` и системного вызова `sched_setaffinity(2)`. Аффинность потока может быть изменена одной из функций библиотеки: `pthread_setaffinity_np(3)` или `pthread_attr_setaffinity_np(3)`. В системах SGI `dplace` связывает процесс с набором процессоров. В DragonFly BSD 1.9 (2007) и более поздних версиях системный вызов `usched_set` может использоваться для управления аффинностью процесса. В NetBSD 5.0, FreeBSD 7.2, DragonFly BSD 4.7 и более поздних версиях можно использовать `pthread_setaffinity_np` и `pthread_getaffinity_np`. В NetBSD утилита `psrset` используется для установки аффинности потока к определенному набору процессоров. В FreeBSD утилита `cpuset` используется для создания наборов процессоров и назначения процессов этим наборам. В DragonFly BSD 3.1 (2012) и более поздних версиях утилита `usched` может использоваться для назначения процессов определенному набору процессоров. В Windows NT и его преемниках аффинность потоков и процессов к процессору может быть установлена отдельно с помощью API-вызовов `SetThreadAffinityMask` и `SetProcessAffinityMask` или через интерфейс Task Manager (только для аффинности процесса). macOS предоставляет API аффинности, который предоставляет ядру рекомендации о том, как планировать потоки в соответствии с наборами аффинности. В Solaris можно управлять связыванием процессов и LWPs с процессором с помощью программы `pbind(1)`. Для программного управления аффинностью можно использовать `processor_bind(2)`. Существуют более общие интерфейсы, такие как `pset_bind(2)` или `lgrp_affinity_get(3LGRP)`, использующие концепции набора процессоров и локальных групп. В AIX можно управлять связыванием процессов с помощью команды `bindprocessor` и API `bindprocessor`.