Freigeben über


KeQueryNodeActiveAffinity2-Funktion (wdm.h)

Diese Routine gibt die aktuelle Prozessoraffinität mit mehreren Gruppen des angegebenen NUMA-Knotens zurück.

Syntax

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

Parameter

[in] NodeNumber

Gibt die Knotennummer des abzufragenden Knotens an.

[out] GroupAffinities

Stellt einen Zeiger auf ein Array von GROUP_AFFINITY Strukturen bereit, die bei Erfolg eine Gruppennummer und die Affinitätsmaske der identifizierten Gruppe erhalten.

[in] GroupAffinitiesCount

Ein Wert vom Typ USHORT, der die Anzahl der Elemente im Gruppenaffinitätsarray angibt. Wenn das Array zu klein ist, um die Knotenaffinität zu halten, wird STATUS_BUFFER_TOO_SMALL zurückgegeben, und die anzahl der erforderlichen Elemente wird in GroupAffinitiesRequired zurückgegeben.

[out] GroupAffinitiesRequired

Ein Zeiger auf einen Wert vom Typ USHORT, der die Anzahl der Gruppenaffinitäten empfängt, die zur Darstellung der Knotenaffinität erforderlich sind. Bei einem NUMA-Knoten, der nur arbeitsspeicheret, wird 0 zurückgegeben.

Rückgabewert

STATUS_SUCCESS , wenn die Knotenaffinität erfolgreich abgefragt wurde.

STATUS_INVALID_PARAMETER , wenn eine ungültige Knotennummer angegeben wurde.

STATUS_BUFFER_TOO_SMALL , wenn das angegebene Array zu klein ist.

Hinweise

Ab Windows Server 2022 teilt das Betriebssystem keine großen NUMA-Knoten mehr auf. Stattdessen meldet Windows die echte NUMA-Topologie des Systems. Wenn ein Knoten mehr als 64 Prozessoren enthält, erstreckt sich ein NUMA-Knoten über mehr als eine einzelne Gruppe. In diesem Fall weist das System jedem NUMA-Knoten eine primäre Gruppe zu. Die primäre Gruppe ist immer die Gruppe, die die meisten Prozessoren enthält. Um die Anzahl der aktiven Prozessoren in einem bestimmten NUMA-Knoten (über alle Gruppen hinweg) zu bestimmen, rufen Sie KeQueryNodeActiveProcessorCount auf. Weitere Informationen zu dieser Verhaltensänderung finden Sie unter NUMA-Unterstützung.

Um das Legacy-Knotenteilungsverhalten erneut zu aktivieren, nehmen Sie die folgende Änderung an der Registrierung vor, und starten Sie das System neu:

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

Wenn Ihr Treiber Prozessoren NUMA-Knoten durch Aufrufen von KeQueryNodeActiveAffinity zuordnet und Ihr Code auf Systemen mit mehr als 64 Prozessoren pro NUMA-Knoten ausgeführt wird, verwenden Sie eine der folgenden Problemumgehungen:

  1. Migrieren Sie zu den Affinitäts-APIs für knotenübergreifende Gruppen (Benutzermodus und Kernelmodus), z. B. KeQueryNodeActiveAffinity2.

  2. Rufen Sie KeQueryLogicalProcessorRelationship mit RelationNumaNode auf, um den NUMA-Knoten, der einer bestimmten Prozessornummer zugeordnet ist, direkt abzufragen.

Das folgende Beispiel zeigt Code, der unter Windows Server 2022 und höher problematisch wäre, und zeigt dann beide Problemumgehungen an.

//
// 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];
    }

Anforderungen

Anforderung Wert
Unterstützte Mindestversion (Server) Windows Server 2022
Kopfzeile wdm.h
IRQL Beliebige Ebene

Weitere Informationen

KeQueryNodeActiveAffinity

KeQueryNodeActiveProcessorCount

NUMA-Unterstützung