Función KeQueryNodeActiveAffinity2 (wdm.h)

Esta rutina devuelve la afinidad actual del procesador multigrupo del nodo NUMA especificado.

Sintaxis

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

Parámetros

[in] NodeNumber

Proporciona el número de nodo del nodo que se va a consultar.

[out] GroupAffinities

Proporciona un puntero a una matriz de estructuras de GROUP_AFFINITY que, tras el éxito, reciben un número de grupo y la máscara de afinidad del grupo identificado.

[in] GroupAffinitiesCount

Valor de tipo USHORT que especifica el número de elementos de la matriz de afinidades de grupo. Si la matriz es demasiado pequeña para contener la afinidad de nodo, se devuelve STATUS_BUFFER_TOO_SMALL y se devuelve el número de elementos necesarios en GroupAffinitiesRequired.

[out] GroupAffinitiesRequired

Puntero a un valor de tipo USHORT que recibe el número de afinidades de grupo necesarias para representar la afinidad de nodo. En el caso de un nodo NUMA de solo memoria, se devuelve cero.

Valor devuelto

STATUS_SUCCESS si la afinidad de nodo se ha consultado correctamente.

STATUS_INVALID_PARAMETER si se especificó un número de nodo no válido.

STATUS_BUFFER_TOO_SMALL si la matriz proporcionada es demasiado pequeña.

Comentarios

A partir de Windows Server 2022, el sistema operativo ya no divide nodos NUMA grandes; en su lugar, Windows notifica la topología NUMA verdadera del sistema. Cuando un nodo contiene más de 64 procesadores, un nodo NUMA abarca más de un único grupo. En este caso, el sistema asigna un grupo principal para cada nodo NUMA. El grupo principal es siempre el que contiene la mayoría de los procesadores. Para determinar el número de procesadores activos en un nodo NUMA determinado (en todos los grupos), llame a KeQueryNodeActiveProcessorCount. Para obtener más información sobre este cambio en el comportamiento, consulte Compatibilidad con NUMA.

Para volver a habilitar el comportamiento de división de nodos heredados, realice el siguiente cambio en el registro y reinicie el sistema:

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

Si el controlador asigna procesadores a nodos NUMA mediante una llamada a KeQueryNodeActiveAffinity y el código se ejecuta en sistemas con más de 64 procesadores por nodo NUMA, use una de las siguientes soluciones alternativas:

  1. Migre a las API de afinidad de nodo de varios grupos (modo de usuario y modo kernel), como KeQueryNodeActiveAffinity2.

  2. Llame a KeQueryLogicalProcessorRelationship con RelationNumaNode para consultar directamente el nodo NUMA asociado a un número de procesador determinado.

En el ejemplo siguiente se muestra el código que sería problemático en Windows Server 2022 y versiones posteriores y, a continuación, se muestran ambas soluciones alternativas.

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

Requisitos

Requisito Value
Servidor mínimo compatible Windows Server 2022
Encabezado wdm.h
IRQL Cualquier nivel

Consulte también

KeQueryNodeActiveAffinity

KeQueryNodeActiveProcessorCount

Compatibilidad NUMA