KeQueryNodeActiveAffinity2, fonction (wdm.h)

Cette routine retourne l’affinité processeur multi-groupe actuelle du nœud NUMA donné.

Syntaxe

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

Paramètres

[in] NodeNumber

Fournit le numéro de nœud du nœud à interroger.

[out] GroupAffinities

Fournit un pointeur vers un tableau de structures GROUP_AFFINITY qui, en cas de succès, reçoivent un numéro de groupe et le masque d’affinité du groupe identifié.

[in] GroupAffinitiesCount

Valeur de type USHORT qui spécifie le nombre d’éléments dans le tableau d’affinités de groupe. Si le tableau est trop petit pour contenir l’affinité de nœud , STATUS_BUFFER_TOO_SMALL est retourné et le nombre d’éléments requis est retourné dans GroupAffinitiesRequired.

[out] GroupAffinitiesRequired

Pointeur vers une valeur de type USHORT qui reçoit le nombre d’affinités de groupe requises pour représenter l’affinité de nœud. Dans le cas d’un nœud NUMA en mémoire uniquement, zéro est retourné.

Valeur retournée

STATUS_SUCCESS si l’affinité de nœud a été correctement interrogée.

STATUS_INVALID_PARAMETER si un numéro de nœud non valide a été spécifié.

STATUS_BUFFER_TOO_SMALL si le tableau fourni est trop petit.

Remarques

À compter de Windows Server 2022, le système d’exploitation ne fractionne plus les nœuds NUMA volumineux ; au lieu de cela, Windows signale la véritable topologie NUMA du système. Lorsqu’un nœud contient plus de 64 processeurs, un nœud NUMA s’étend sur plusieurs groupes. Dans ce cas, le système affecte un groupe principal pour chaque nœud NUMA. Le groupe principal est toujours celui qui contient le plus de processeurs. Pour déterminer le nombre de processeurs actifs dans un nœud NUMA donné (dans tous les groupes), appelez KeQueryNodeActiveProcessorCount. Pour plus d’informations sur ce changement de comportement, consultez Prise en charge de NUMA.

Pour réactiver le comportement de fractionnement des nœuds hérités, apportez la modification suivante au Registre et redémarrez le système :

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

Si votre pilote mappe les processeurs aux nœuds NUMA en appelant KeQueryNodeActiveAffinity et que votre code s’exécute sur des systèmes avec plus de 64 processeurs par nœud NUMA, utilisez l’une des solutions de contournement suivantes :

  1. Migrez vers les API d’affinité de nœud multi-groupes (mode utilisateur et mode noyau), telles que KeQueryNodeActiveAffinity2.

  2. Appelez KeQueryLogicalProcessorRelationship avec RelationNumaNode pour interroger directement le nœud NUMA associé à un numéro de processeur donné.

L’exemple suivant montre du code qui serait problématique sur Windows Server 2022 et versions ultérieures, puis montre les deux solutions de contournement.

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

Configuration requise

Condition requise Valeur
Serveur minimal pris en charge Windows Server 2022
En-tête wdm.h
IRQL N’importe quel niveau

Voir aussi

KeQueryNodeActiveAffinity

KeQueryNodeActiveProcessorCount

Prise en charge de NUMA