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 的系统上运行,请使用以下解决方法之一:
迁移到多组节点相关性 API (用户模式和内核模式) ,例如 KeQueryNodeActiveAffinity2。
使用 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 | 任何级别 |