2014-10-15 6 views
19

मैं एक टूल पर काम कर रहा हूं ताकि विद्यार्थियों को उनके प्रोग्रामिंग असाइनमेंट के प्रदर्शन का आत्म-मूल्यांकन करने की अनुमति मिल सके। विशेष रूप से, वे जो प्रोग्राम लिख रहे हैं वह बहु-थ्रेडेड है और मेरे पास बनाए गए धागे की संख्या को प्रभावित करने का कोई सीधा तरीका नहीं है। मैं अपने कार्यक्रमों के प्रदर्शन की तुलना अलग-अलग कोरों के साथ तुलना करना चाहता हूं (और आदर्श रूप से, उनके कार्यक्रमों को लगभग आनुपातिक रूप से तेजी से बढ़ाना चाहिए कि इसे कितने कोर उपयोग करने की अनुमति है)।यह निर्धारित करने के लिए कि कौन से लॉजिकल कोर एक ही भौतिक कोर साझा करते हैं?

हम प्रक्रिया के लिए बिटमैस्क पास कर सकते हैं। प्रोग्राम को नियंत्रित करने के लिए कौन सा कोर नियंत्रित करता है।

यह i5 और i7 मशीनों पर समस्याग्रस्त है जो हाइपर-थ्रेडिंग का उपयोग करते हैं और प्रत्येक भौतिक कोर को दो लॉजिकल में विभाजित करते हैं। मैं चाहता हूं कि कार्यक्रम दो/चार अलग-अलग भौतिक कोरों पर चलें। मेरी आई 7 मशीन पर, एफ़िनिटी के साथ एक प्रक्रिया 3 सेट (कोर1) लगभग एक कोर पर प्रोग्राम जितनी तेजी से चलती है (इन तार्किक कोरों को इंगित करना एक ही भौतिक कोर साझा करता है), लेकिन एफ़िनिटी के साथ सेट 5 (कोर 0 & 3) यह बहुत तेजी से चलाएगा (यह इंगित करता है कि ये कोर विभिन्न भौतिक कोर का उपयोग कर रहे हैं)। हालांकि, मुझे यह निर्धारित करने के लिए एक विश्वसनीय तरीका नहीं मिला है (परीक्षण और त्रुटि के अलावा)।

मैं (प्रयोग के बिना) कैसे निर्धारित कर सकता हूं कि कौन से लॉजिकल कोर एक ही भौतिक कोर साझा करते हैं?

(/ proc/cpuinfo जानकारी की आवश्यकता है, लेकिन है कि Windows मशीनों पर उपलब्ध नहीं है।)

+1

जानकारी के माध्यम से शायद उपलब्ध [WMI (विंडोज प्रबंधन इंस्ट्रूमेंटेशन)] (http://en.wikipedia.org/wiki/Windows_Management_Instrumentation) - या शारीरिक/आभासी कोर के कम से कम गिनती है, जो यह * हो सकता है * एक interleaved bitmask में extrapolate करने के लिए मान्य हो। – user2864740

+1

ऐसा लगता है कि मैं उल्लेख करना भूल गया था कि मैं विशेष रूप से सी # समाधान की तलाश में हूं। मैंने सी # टैग जोड़ा लेकिन मैंने इसे कहीं भी उल्लेख नहीं किया। मैंने अब शीर्षक में सी # जोड़ा है, जिसे मैं थोड़ा सा स्पष्ट कर दूंगा जो मैं ढूंढ रहा हूं। –

+0

@TomvanderZanden आपको शीर्षक में 'C#' जोड़ना नहीं चाहिए। टैग पर्याप्त होना चाहिए। यदि ऐसा नहीं है, तो इसे अपने प्रश्न में स्पष्ट करें। – MarcinJuraszek

उत्तर

4

अपने प्रश्न के लिए टिप्पणी के आधार पर (धन्यवाद सभी, विशेष रूप से @RLH करने के लिए) मैं इस वर्ग आपके लिए बनाया गया :

/// <summary> 
/// Provides CPU information 
/// </summary> 
public static class Processor 
{ 
    private static IHardwareCore[] cores; 
    private static int[] logicalCores; 

    /// <summary> 
    /// Hardware core 
    /// </summary> 
    public interface IHardwareCore 
    { 
     /// <summary> 
     /// Logical core IDs 
     /// </summary> 
     int[] LogicalCores { get; } 
    } 

    /// <summary> 
    /// Hardware cores 
    /// </summary> 
    public static IHardwareCore[] HardwareCores 
    { 
     get 
     { 
      return cores ?? (cores = GetLogicalProcessorInformation() 
       .Where(x => x.Relationship == LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore) 
       .Select(x => new HardwareCore((UInt64)x.ProcessorMask)) 
       .ToArray<IHardwareCore>()); 
     } 
    } 

    /// <summary> 
    /// All logical core IDs 
    /// </summary> 
    public static int[] LogicalCores 
    { 
     get 
     { 
      return logicalCores ?? (logicalCores = HardwareCores 
       .SelectMany(x => x.LogicalCores) 
       .ToArray()); 
     } 
    } 

    /// <summary> 
    /// Current logical core ID 
    /// </summary> 
    public static int CurrentLogicalCore 
    { 
     get { return GetCurrentProcessorNumber(); } 
    } 

    private class HardwareCore : IHardwareCore 
    { 
     public HardwareCore(UInt64 logicalCoresMask) 
     { 
      var logicalCores = new List<int>(); 

      for (var i = 0; i < 64; ++i) 
      { 
       if (((logicalCoresMask >> i) & 0x1) == 0) continue; 
       logicalCores.Add(i); 
      } 

      LogicalCores = logicalCores.ToArray(); 
     } 

     public int[] LogicalCores { get; private set; } 
    } 

    #region Exports 

    [StructLayout(LayoutKind.Sequential)] 
    private struct PROCESSORCORE 
    { 
     public byte Flags; 
    }; 

    [StructLayout(LayoutKind.Sequential)] 
    private struct NUMANODE 
    { 
     public uint NodeNumber; 
    } 

    private enum PROCESSOR_CACHE_TYPE 
    { 
     CacheUnified, 
     CacheInstruction, 
     CacheData, 
     CacheTrace 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    private struct CACHE_DESCRIPTOR 
    { 
     public byte Level; 
     public byte Associativity; 
     public ushort LineSize; 
     public uint Size; 
     public PROCESSOR_CACHE_TYPE Type; 
    } 

    [StructLayout(LayoutKind.Explicit)] 
    private struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION_UNION 
    { 
     [FieldOffset(0)] 
     public PROCESSORCORE ProcessorCore; 
     [FieldOffset(0)] 
     public NUMANODE NumaNode; 
     [FieldOffset(0)] 
     public CACHE_DESCRIPTOR Cache; 
     [FieldOffset(0)] 
     private UInt64 Reserved1; 
     [FieldOffset(8)] 
     private UInt64 Reserved2; 
    } 

    private enum LOGICAL_PROCESSOR_RELATIONSHIP 
    { 
     RelationProcessorCore, 
     RelationNumaNode, 
     RelationCache, 
     RelationProcessorPackage, 
     RelationGroup, 
     RelationAll = 0xffff 
    } 

    private struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION 
    { 
     public UIntPtr ProcessorMask; 
     public LOGICAL_PROCESSOR_RELATIONSHIP Relationship; 
     public SYSTEM_LOGICAL_PROCESSOR_INFORMATION_UNION ProcessorInformation; 
    } 

    [DllImport(@"kernel32.dll", SetLastError = true)] 
    private static extern bool GetLogicalProcessorInformation(
     IntPtr Buffer, 
     ref uint ReturnLength 
    ); 

    private const int ERROR_INSUFFICIENT_BUFFER = 122; 

    private static SYSTEM_LOGICAL_PROCESSOR_INFORMATION[] GetLogicalProcessorInformation() 
    { 
     uint ReturnLength = 0; 
     GetLogicalProcessorInformation(IntPtr.Zero, ref ReturnLength); 
     if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER) 
     { 
      IntPtr Ptr = Marshal.AllocHGlobal((int)ReturnLength); 
      try 
      { 
       if (GetLogicalProcessorInformation(Ptr, ref ReturnLength)) 
       { 
        int size = Marshal.SizeOf(typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); 
        int len = (int)ReturnLength/size; 
        SYSTEM_LOGICAL_PROCESSOR_INFORMATION[] Buffer = new SYSTEM_LOGICAL_PROCESSOR_INFORMATION[len]; 
        IntPtr Item = Ptr; 
        for (int i = 0; i < len; i++) 
        { 
         Buffer[i] = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION)Marshal.PtrToStructure(Item, typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); 
         Item += size; 
        } 
        return Buffer; 
       } 
      } 
      finally 
      { 
       Marshal.FreeHGlobal(Ptr); 
      } 
     } 
     return null; 
    } 

    [DllImport(@"kernel32.dll", SetLastError = true)] 
    private static extern int GetCurrentProcessorNumber(); 

    #endregion 
} 

प्रयोग उदाहरण: इंटेल कोर i5 के लिए

for (var i = 0; i < Processor.HardwareCores.Length; ++i) 
{ 
    Console.WriteLine("Hardware Core {0} has logical cores {1}", i, 
     string.Join(", ", Processor.HardwareCores[i].LogicalCores)); 
} 
Console.WriteLine("All logical cores: " + string.Join(", ", Processor.LogicalCores)); 
Console.WriteLine("Current Logical Core is " + Processor.CurrentLogicalCore); 

उदाहरण आउटपुट:

Hardware Core 0 has logical cores 0, 1 
Hardware Core 1 has logical cores 2, 3 
All logical cores: 0, 1, 2, 3 
Current Logical Core is 2 
संबंधित मुद्दे