internal static void AffinitizeThreadNuma(uint threadIdx) { uint nrOfProcessors = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); ushort nrOfProcessorGroups = GetActiveProcessorGroupCount(); uint nrOfProcsPerGroup = nrOfProcessors / nrOfProcessorGroups; GROUP_AFFINITY groupAffinityThread = default; GROUP_AFFINITY oldAffinityThread = default; IntPtr thread = GetCurrentThread(); GetThreadGroupAffinity(thread, ref groupAffinityThread); groupAffinityThread.Mask = (ulong)1L << ((int)(threadIdx / nrOfProcessorGroups) % (int)nrOfProcsPerGroup); groupAffinityThread.Group = threadIdx % nrOfProcessorGroups; if (SetThreadGroupAffinity(thread, ref groupAffinityThread, ref oldAffinityThread) == 0) { Console.WriteLine("Unable to set group affinity"); } }
/// <summary> /// Accepts thread id = 0, 1, 2, ... and sprays them round-robin /// across all cores (viewed as a flat space). On NUMA machines, /// this gives us [socket, core] ordering of affinitization. That is, /// if there are N cores per socket, then thread indices of 0 to N-1 map /// to the range [socket 0, core 0] to [socket 0, core N-1]. /// </summary> /// <param name="threadIdx">Index of thread (from 0 onwards)</param> public static void AffinitizeThreadRoundRobin(uint threadIdx) { uint nrOfProcessors = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); ushort nrOfProcessorGroups = GetActiveProcessorGroupCount(); uint nrOfProcsPerGroup = nrOfProcessors / nrOfProcessorGroups; GROUP_AFFINITY groupAffinityThread = default(GROUP_AFFINITY); GROUP_AFFINITY oldAffinityThread = default(GROUP_AFFINITY); IntPtr thread = GetCurrentThread(); GetThreadGroupAffinity(thread, ref groupAffinityThread); threadIdx = threadIdx % nrOfProcessors; groupAffinityThread.Mask = (ulong)1L << ((int)(threadIdx % (int)nrOfProcsPerGroup)); groupAffinityThread.Group = (uint)(threadIdx / nrOfProcsPerGroup); if (SetThreadGroupAffinity(thread, ref groupAffinityThread, ref oldAffinityThread) == 0) { throw new FasterException("Unable to affinitize thread"); } }
public static extern bool GetNumaNodeProcessorMaskEx(ushort Node, out GROUP_AFFINITY ProcessorMask);
private static extern Boolean SetThreadGroupAffinity(IntPtr hThread, ref GROUP_AFFINITY GroupAffinity, ref GROUP_AFFINITY PreviousGroupAffinity);
// EO 2015-02-16, Function has been added by me. ~Copied from GetLogicalProcessorInformation() from David Heffernan public static List <T> GetLogicalProcessorInformationEx <T>() where T : struct { LOGICAL_PROCESSOR_RELATIONSHIP relationShip; if (typeof(T) == typeof(CACHE_RELATIONSHIP)) { relationShip = LOGICAL_PROCESSOR_RELATIONSHIP.RelationCache; } else if (typeof(T) == typeof(GROUP_RELATIONSHIP)) { relationShip = LOGICAL_PROCESSOR_RELATIONSHIP.RelationGroup; } else if (typeof(T) == typeof(PROCESSOR_RELATIONSHIP)) { relationShip = LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore; } else if (typeof(T) == typeof(NUMA_NODE_RELATIONSHIP)) { relationShip = LOGICAL_PROCESSOR_RELATIONSHIP.RelationNumaNode; } else { throw new NotSupportedException("This type of relation is currently unsuported"); } var listRelationShip = new List <T>(); SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX systemLogicalProcessorInformationEx; UInt32 ReturnLength = 0; bool isOk = GetLogicalProcessorInformationEx(relationShip, IntPtr.Zero, ref ReturnLength); int error = Marshal.GetLastWin32Error(); if (error == ERROR_INSUFFICIENT_BUFFER) { IntPtr Ptr = Marshal.AllocHGlobal((int)ReturnLength); try { int size = 0; if (GetLogicalProcessorInformationEx(relationShip, Ptr, ref ReturnLength)) { var sizeLeftToRead = (Int32)ReturnLength; IntPtr nextItem = IntPtr.Zero; while (sizeLeftToRead > 0) { var structInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX_ROOT_INFO) Marshal.PtrToStructure(Ptr, typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX_ROOT_INFO)); nextItem = Ptr + Marshal.SizeOf(typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX_ROOT_INFO)); switch (structInfo.Relationship) { case LOGICAL_PROCESSOR_RELATIONSHIP.RelationAll: { throw new NotSupportedException("LOGICAL_PROCESSOR_RELATIONSHIP.RelationAll is not supported"); } case LOGICAL_PROCESSOR_RELATIONSHIP.RelationCache: // Checked, ok { var relationship = (T)Marshal.PtrToStructure(nextItem, typeof(T)); listRelationShip.Add(relationship); break; } case LOGICAL_PROCESSOR_RELATIONSHIP.RelationNumaNode: // Cheked, unsure { var relationship = (T)Marshal.PtrToStructure(nextItem, typeof(T)); listRelationShip.Add(relationship); break; } case LOGICAL_PROCESSOR_RELATIONSHIP.RelationGroup: { var relationship = (GROUP_RELATIONSHIP_INTERNAL)Marshal.PtrToStructure(nextItem, typeof(GROUP_RELATIONSHIP_INTERNAL)); IntPtr processorGroupInfoPtr = nextItem + Marshal.SizeOf(typeof(GROUP_RELATIONSHIP_INTERNAL)); int groupCount = ((GROUP_RELATIONSHIP_INTERNAL)(object)relationship).ActiveGroupCount; int sizeProcessorGroupInfo = Marshal.SizeOf(typeof(PROCESSOR_GROUP_INFO)); var processorGroupInfos = new PROCESSOR_GROUP_INFO[groupCount]; for (int groupIndex = 0; groupIndex < groupCount; groupIndex++) { var processorGroupInfo = Marshal.PtrToStructure <PROCESSOR_GROUP_INFO>(processorGroupInfoPtr); processorGroupInfos[groupIndex] = processorGroupInfo; processorGroupInfoPtr += sizeProcessorGroupInfo; } var groupRelationship = new GROUP_RELATIONSHIP(); groupRelationship.ActiveGroupCount = relationship.ActiveGroupCount; groupRelationship.MaximumGroupCount = relationship.MaximumGroupCount; groupRelationship.GroupInfo = processorGroupInfos; listRelationShip.Add((T)(object)groupRelationship); break; } case LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore: { var relationship = (PROCESSOR_RELATIONSHIP_INTERNAL)Marshal.PtrToStructure(nextItem, typeof(PROCESSOR_RELATIONSHIP_INTERNAL)); IntPtr groupAffinityPtr = nextItem + Marshal.SizeOf(typeof(PROCESSOR_RELATIONSHIP_INTERNAL)); int groupCount = ((PROCESSOR_RELATIONSHIP_INTERNAL)(object)relationship).GroupCount; int sizeGroupAffinity = Marshal.SizeOf(typeof(GROUP_AFFINITY)); var processorGroupAffinitys = new GROUP_AFFINITY[groupCount]; for (int groupMaskIndex = 0; groupMaskIndex < groupCount; groupMaskIndex++) { var groupAffinity = Marshal.PtrToStructure <GROUP_AFFINITY>(groupAffinityPtr); processorGroupAffinitys[groupMaskIndex] = groupAffinity; groupAffinityPtr += sizeGroupAffinity; } var processorRelationship = new PROCESSOR_RELATIONSHIP(); processorRelationship.Flags = relationship.Flags; processorRelationship.GroupCount = relationship.GroupCount; processorRelationship.GroupAffinity = processorGroupAffinitys; listRelationShip.Add((T)(object)processorRelationship); break; } } nextItem += (int)structInfo.Size; sizeLeftToRead -= (int)structInfo.Size; } } } catch (Exception ex) { Debug.Print(ex.ToString()); } finally { Marshal.FreeHGlobal(Ptr); } } Debug.Print("Cache"); foreach (T rel in listRelationShip) { Debug.Print(rel.ToString()); } return(listRelationShip); }
public static extern int GetThreadGroupAffinity(IntPtr hThread, ref GROUP_AFFINITY PreviousGroupAffinity);
public static extern bool SetThreadGroupAffinity( IntPtr thread, ref GROUP_AFFINITY groupAffinity, out GROUP_AFFINITY previousGroupAffinity);
public static extern bool GetThreadGroupAffinity(IntPtr hThread, out GROUP_AFFINITY GroupAffinity);
internal static extern int SetThreadGroupAffinity(IntPtr hThread, ref GROUP_AFFINITY GroupAffinity, ref GROUP_AFFINITY PreviousGroupAffinity);
public static extern bool GetThreadGroupAffinity(HTHREAD hThread, out GROUP_AFFINITY GroupAffinity);
public static extern bool SetInformationJobObject(IntPtr hJob, JOBOBJECTINFOCLASS JobObjectInfoClass, ref GROUP_AFFINITY lpJobObjectInfo, uint cbJobObjectInfoLength);