Processor Groups
The 64-bit versions of Windows 7 and Windows Server 2008 R2 and later versions of Windows support more than 64 logical processors on a single computer. This functionality is not available on 32-bit versions of Windows.
Systems with more than one physical processor or systems with physical processors that have multiple cores provide the operating system with multiple logical processors. A logical processor is one logical computing engine from the perspective of the operating system, application or driver. A core is one processor unit, which can consist of one or more logical processors. A physical processor can consist of one or more cores. A physical processor is the same as a processor package, a socket, or a CPU.
Support for systems that have more than 64 logical processors is based on the concept of a processor group, which is a static set of up to 64 logical processors that is treated as a single scheduling entity. Processor groups are numbered starting with 0. Systems with fewer than 64 logical processors always have a single group, Group 0.
Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: Processor groups are not supported.
When the system starts, the operating system creates processor groups and assigns logical processors to the groups. If the system is capable of hot-adding processors, the operating system allows space in groups for processors that might arrive while the system is running. The operating system minimizes the number of groups in a system. For example, a system with 128 logical processors would have two processor groups with 64 processors in each group, not four groups with 32 logical processors in each group.
For better performance, the operating system takes physical locality into account when assigning logical processors to groups. All of the logical processors in a core, and all of the cores in a physical processor, are assigned to the same group, if possible. Physical processors that are physically close to one another are assigned to the same group. A NUMA node is assigned to a single group unless the capacity of the node exceeds the maximum group size. For more information, see NUMA Support.
On systems with 64 or fewer processors, existing applications will operate correctly without modification. Applications that do not call any functions that use processor affinity masks or processor numbers will operate correctly on all systems, regardless of the number of processors. To operate correctly on systems with more than 64 logical processors, the following kinds of applications might require modification:
- Applications that manage, maintain, or display per-processor information for the entire system must be modified to support more than 64 logical processors. An example of such an application is Windows Task Manager, which displays the workload of each processor in the system.
- Applications for which performance is critical and that can scale efficiently beyond 64 logical processors must be modified to run on such systems. For example, database applications might benefit from modifications.
- If an application uses a DLL that has per-processor data structures, and the DLL has not been modified to support more than 64 logical processors, all threads in the application that call functions exported by the DLL must be assigned to the same group.
By default, an application is constrained to a single group, which should provide ample processing capability for the typical application. The operating system initially assigns each process to a single group in a round-robin manner across the groups in the system. A process begins its execution assigned to one group. The first thread of a process initially runs in the group to which the process is assigned. Each newly created thread is assigned to the same group as the thread that created it.
An application that requires the use of multiple groups so that it can run on more than 64 processors must explicitly determine where to run its threads and is responsible for setting the threads' processor affinities to the desired groups. The INHERIT_PARENT_AFFINITY flag can be used to specify a parent process (which can be different than the current process) from which to generate the affinity for a new process. If the process is running in a single group, it can read and modify its affinity using GetProcessAffinityMask and SetProcessAffinityMask while remaining in the same group; if the process affinity is modified, the new affinity is applied to its threads.
A thread's affinity can be specified at creation using the PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY extended attribute with the CreateRemoteThreadEx function. After the thread is created, its affinity can be changed by calling SetThreadAffinityMask or SetThreadGroupAffinity. If a thread is assigned to a different group than the process, the process's affinity is updated to include the thread's affinity and the process becomes a multi-group process. Further affinity changes must be made for individual threads; a multi-group process's affinity cannot be modified using SetProcessAffinityMask. The GetProcessGroupAffinity function retrieves the set of groups to which a process and its threads are assigned.
To specify affinity for all processes associated with a job object, use the SetInformationJobObject function with the JobObjectGroupInformation or JobObjectGroupInformationEx information class.
A logical processor is identified by its group number and its group-relative processor number. This is represented by a PROCESSOR_NUMBER structure. Numeric processor numbers used by legacy functions are group-relative.
For a discussion of operating system architecture changes to support more than 64 processors, see the white paper Supporting Systems That Have More Than 64 Processors.
For a list of new functions and structures that support processor groups, see What's New in Processes and Threads.
Behavior starting with Windows 11 and Windows Server 2022
Note
Starting with Windows 11 and Windows Server 2022, it is no longer the case that applications are constrained by default to a single processor group. Instead, processes and their threads have processor affinities that by default span all processors in the system, across multiple groups on machines with more than 64 processors.
In order for applications to automatically take advantage of all the processors in a machine with more than 64 processors, starting with Windows 11 and Windows Server 2022 the OS has changed to make processes and their threads span all processors in the system, across all processor groups, by default. This means that applications no longer need to explicitly set their threads' affinities in order to access multiple processor groups.
For compatibility reasons, the OS uses a new Primary Group concept for both processes and threads. Each process is assigned a primary group at creation, and by default all of its threads' primary group is the same. Each thread's ideal processor is in the thread's primary group, so threads will preferentially be scheduled to processors on their primary group, but they are able to be scheduled to processors on any other group. Affinity APIs that are not group-aware or operate on a single group implicitly use the primary group as the process/thread processor group; for more information on the new behaviors check the Remarks sections for the following:
- GetProcessAffinityMask
- SetProcessAffinityMask
- SetThreadAffinityMask
- GetProcessGroupAffinity
- GetThreadGroupAffinity
- SetThreadGroupAffinity
- SetThreadIdealProcessor
- SetThreadIdealProcessorEx
Applications can use CPU Sets to effectively manage a process' or thread's affinity over multiple processor groups.
Related topics