Функция KeQueryNodeActiveAffinity2 (wdm.h)

Эта подпрограмма возвращает текущее сходство процессоров с несколькими группами заданного узла NUMA.

Синтаксис

NTSTATUS KeQueryNodeActiveAffinity2(
  [in]  USHORT          NodeNumber,
  [out] PGROUP_AFFINITY GroupAffinities,
  [in]  USHORT          GroupAffinitiesCount,
  [out] PUSHORT         GroupAffinitiesRequired
);

Параметры

[in] NodeNumber

Предоставляет номер узла для запроса.

[out] GroupAffinities

Предоставляет указатель на массив GROUP_AFFINITY структур, которые при успешном выполнении получают номер группы и маску сходства определенной группы.

[in] GroupAffinitiesCount

Значение типа USHORT, указывающее количество элементов в массиве сопоставлений групп. Если массив слишком мал, чтобы вместить сходство узлов, возвращается STATUS_BUFFER_TOO_SMALL и необходимое количество элементов возвращается в GroupAffinitiesRequired.

[out] GroupAffinitiesRequired

Указатель на значение типа USHORT, которое получает количество сопоставлений групп, необходимых для представления сходства узла. В случае узла NUMA, доступного только для памяти, возвращается ноль.

Возвращаемое значение

STATUS_SUCCESS , если сопоставление узлов было успешно запрошено.

STATUS_INVALID_PARAMETER , если указан недопустимый номер узла.

STATUS_BUFFER_TOO_SMALL , если предоставленный массив слишком мал.

Комментарии

Начиная с Windows Server 2022 операционная система больше не разделяет большие узлы NUMA; Вместо этого Windows сообщает об истинной топологии NUMA системы. Если узел содержит более 64 процессоров, узел NUMA охватывает несколько групп. В этом случае система назначает основную группу для каждого узла NUMA. Основной группой всегда является группа, содержащая больше всего процессоров. Чтобы определить количество активных процессоров в данном узле NUMA (во всех группах), вызовите KeQueryNodeActiveProcessorCount. Дополнительные сведения об этом изменении в поведении см. в разделе Поддержка NUMA.

Чтобы повторно включить устаревшее поведение разделения узлов, внесите следующие изменения в реестр и перезагрузите систему:

reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\NUMA" /v SplitLargeNodes /t REG_DWORD /d 1

Если драйвер сопоставляет процессоры с узлами NUMA путем вызова KeQueryNodeActiveAffinity, а код выполняется в системах с более чем 64 процессорами на узел NUMA, используйте один из следующих обходных путей:

  1. Перейдите на API сопоставления узлов с несколькими группами (режим пользователя и режим ядра), например KeQueryNodeActiveAffinity2.

  2. Вызовите KeQueryLogicalProcessorRelationship с RelationNumaNode , чтобы напрямую запросить узел NUMA, связанный с заданным номером процессора.

В следующем примере показан код, который был бы проблематичным в Windows Server 2022 и более поздних версиях, а затем показаны оба обходных решения.

//
// Problematic implementation using KeQueryNodeActiveAffinity.
//

    USHORT CurrentNode;
    USHORT HighestNodeNumber;
    GROUP_AFFINITY NodeAffinity;
    ULONG ProcessorIndex;
    PROCESSOR_NUMBER ProcessorNumber;

    HighestNodeNumber = KeQueryHighestNodeNumber();
    for (CurrentNode = 0; CurrentNode <= HighestNodeNumber; CurrentNode += 1) {

        KeQueryNodeActiveAffinity(CurrentNode, &NodeAffinity, NULL);
        while (NodeAffinity.Mask != 0) {

            ProcessorNumber.Group = NodeAffinity.Group;
            BitScanForward(&ProcessorNumber.Number, NodeAffinity.Mask);

            ProcessorIndex = KeGetProcessorIndexFromNumber(&ProcessorNumber);

            ProcessorNodeContexts[ProcessorIndex] = NodeContexts[CurrentNode;]

            NodeAffinity.Mask &= ~((KAFFINITY)1 << ProcessorNumber.Number);
        }
    }

//
// Resolution using KeQueryNodeActiveAffinity2.
//

    USHORT CurrentIndex;
    USHORT CurrentNode;
    USHORT CurrentNodeAffinityCount;
    USHORT HighestNodeNumber;
    ULONG MaximumGroupCount;
    PGROUP_AFFINITY NodeAffinityMasks;
    ULONG ProcessorIndex;
    PROCESSOR_NUMBER ProcessorNumber;
    NTSTATUS Status;

    MaximumGroupCount = KeQueryMaximumGroupCount();
    NodeAffinityMasks = ExAllocatePool2(POOL_FLAG_PAGED,
                                        sizeof(GROUP_AFFINITY) * MaximumGroupCount,
                                        'tseT');

    if (NodeAffinityMasks == NULL) {
        return STATUS_NO_MEMORY;
    }

    HighestNodeNumber = KeQueryHighestNodeNumber();
    for (CurrentNode = 0; CurrentNode <= HighestNodeNumber; CurrentNode += 1) {

        Status = KeQueryNodeActiveAffinity2(CurrentNode,
                                            NodeAffinityMasks,
                                            MaximumGroupCount,
                                            &CurrentNodeAffinityCount);
        NT_ASSERT(NT_SUCCESS(Status));

        for (CurrentIndex = 0; CurrentIndex < CurrentNodeAffinityCount; CurrentIndex += 1) {

            CurrentAffinity = &NodeAffinityMasks[CurrentIndex];

            while (CurrentAffinity->Mask != 0) {

                ProcessorNumber.Group = CurrentAffinity.Group;
                BitScanForward(&ProcessorNumber.Number, CurrentAffinity->Mask);

                ProcessorIndex = KeGetProcessorIndexFromNumber(&ProcessorNumber);

                ProcessorNodeContexts[ProcessorIndex] = NodeContexts[CurrentNode];

                CurrentAffinity->Mask &= ~((KAFFINITY)1 << ProcessorNumber.Number);
            }
        }
    }

//
// Resolution using KeQueryLogicalProcessorRelationship.
//

    ULONG ProcessorCount;
    ULONG ProcessorIndex;
    SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX ProcessorInformation;
    ULONG ProcessorInformationSize;
    PROCESSOR_NUMBER ProcessorNumber;
    NTSTATUS Status;

    ProcessorCount = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);

    for (ProcessorIndex = 0; ProcessorIndex < ProcessorCount; ProcessorIndex += 1) {

        Status = KeGetProcessorNumberFromIndex(ProcessorIndex, &ProcessorNumber);
        NT_ASSERT(NT_SUCCESS(Status));

        ProcessorInformationSize = sizeof(ProcessorInformation);
        Status = KeQueryLogicalProcessorRelationship(&ProcessorNumber,
                                                     RelationNumaNode,
                                                     &ProcessorInformation,
                                                     &ProcessorInformationSize);
        NT_ASSERT(NT_SUCCESS(Status));

        NodeNumber = ProcessorInformation.NumaNode.NodeNumber;

        ProcessorNodeContexts[ProcessorIndex] = NodeContexts[NodeNumber];
    }

Требования

Требование Значение
Минимальная версия сервера Windows Server 2022
Верхняя часть wdm.h
IRQL Любой уровень

См. также раздел

KeQueryNodeActiveAffinity

KeQueryNodeActiveProcessorCount

Поддержка NUMA