Функция 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, используйте один из следующих обходных путей:
Перейдите на API сопоставления узлов с несколькими группами (режим пользователя и режим ядра), например KeQueryNodeActiveAffinity2.
Вызовите 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 | Любой уровень |