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

如果您的驅動程式藉由呼叫 KeQueryNodeActiveAffinity 將處理器對應至 NUMA 節點,而且您的程式代碼會在每個 NUMA 節點超過 64 個處理器的系統上執行,請使用下列其中一個因應措施:

  1. 移轉至多群組節點親和性 API, (使用者模式和內核模式) ,例如 KeQueryNodeActiveAffinity2

  2. 使用 RelationNumaNode 呼叫 KeQueryLogicalProcessorRelationship,以直接查詢與指定處理器編號相關聯的 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 支援