Введение

Присвоение задачи определенному ядру CPU обеспечивает связывание и отвязывание процесса или потока от центрального процессора (CPU) или диапазона процессоров, так что процесс или поток будет выполняться только на назначенном процессоре или процессорах, а не на любом доступном. Это можно рассматривать как модификацию алгоритма планирования центральной очереди в симметричной многопроцессорной операционной системе. Каждый элемент в очереди имеет метку, указывающую его "родственный" процессор. При распределении ресурсов каждая задача предпочтительно назначается своему родному процессору. Аффинность процессора использует тот факт, что после выполнения процесса на данном процессоре, в его состоянии могут оставаться следы этого процесса (например, данные в кэш-памяти). Планирование вычислительно-интенсивного процесса с небольшим количеством прерываний для выполнения на одном и том же процессоре может повысить его производительность за счет снижения количества ухудшающих событий, таких как промахи кэша, но может замедлить работу обычных программ, которым придется ждать, пока этот процессор снова станет доступным. Практическим примером аффинности процессора является запуск нескольких экземпляров однопоточного приложения, например, некоторых программ для графического рендеринга. Реализации алгоритмов планирования по-разному реализуют аффинность процессора. В определенных ситуациях некоторые реализации могут разрешить задаче переключиться на другой процессор, если это приведет к повышению эффективности. Например, если две вычислительно-интенсивные задачи (A и B) имеют аффинность к одному процессору, а другой процессор остается неиспользованным, многие планировщики перенесут задачу B на второй процессор для максимального использования ресурсов. Задача B затем получит аффинность ко второму процессору, а задача A продолжит иметь аффинность к исходному процессору.

Использование

Аффинность процессора может эффективно снизить проблемы, связанные с кэшем, но не решает проблему постоянного балансирования нагрузки. Также следует учитывать, что аффинность процессора усложняется в системах с неоднородной архитектурой. Например, система с двумя двухъядерными гиперпоточными процессорами представляет собой задачу для алгоритма планирования. Существует полная аффинность между двумя виртуальными процессорами, реализованными на одном ядре посредством гиперпоточности, частичная аффинность между двумя ядрами на одном физическом процессоре (поскольку ядра совместно используют часть, но не весь кэш) и отсутствие аффинности между отдельными физическими процессорами. Поскольку другие ресурсы также являются общими, аффинность процессора не может служить единственным основанием для диспетчеризации задач. Если процесс недавно выполнялся на одном виртуальном гиперпоточном процессоре в данном ядре, и этот процессор в данный момент занят, а его парный процессор свободен, аффинность к кэшу предполагает, что процесс следует направить на неактивный парный процессор. Однако эти два виртуальных процессора конкурируют практически за все вычислительные ресурсы, кэш и память. В этой ситуации, как правило, более эффективно будет направить процесс на другое ядро или процессор, если таковые имеются. Это может повлечь за собой задержку при повторной загрузке кэша, но общая производительность может быть выше, поскольку процессу не придется конкурировать за ресурсы внутри процессора.

Специфические операционные системы

В 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`.