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 노드의 경우 0이 반환됩니다.
반환 값
노드 선호도를 성공적으로 쿼리했는지 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개를 초과하는 시스템에서 코드가 실행되는 경우 다음 해결 방법 중 하나를 사용합니다.
KeQueryNodeActiveAffinity2와 같은 다중 그룹 노드 선호도 API(사용자 모드 및 커널 모드)로 마이그레이션합니다.
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 | 모든 수준 |