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 (ユーザー モードとカーネル モード) に移行します。
RelationNumaNodeKeQueryLogicalProcessorRelationship を呼び出して、指定されたプロセッサ番号に関連付けられている 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 | 任意のレベル |
KeQueryNodeActiveAffinity の