如何在.net中确定CPU缓存大小

本文关键字:CPU 缓存 net | 更新日期: 2023-09-27 18:05:02

我想知道是否有办法确定托管代码中的CPU缓存大小?

我正在用c#编写矩阵乘法的Strassen算法,我想知道我可以将多少个矩阵元素放入缓存中以提高计算速度。

如何在.net中确定CPU缓存大小

可以使用WMI检索缓存信息

您首先需要在项目中添加对System.Management.dll的引用,然后可以使用以下代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
namespace Scratch
{
    public enum CacheLevel : ushort 
    {
        Level1 = 3,
        Level2 = 4,
        Level3 = 5,
    }
    public static class CPUInfo
    {
        public static List<uint> GetCacheSizes(CacheLevel level)
        {
            ManagementClass mc = new ManagementClass("Win32_CacheMemory");
            ManagementObjectCollection moc = mc.GetInstances();
            List<uint> cacheSizes = new List<uint>(moc.Count);
            cacheSizes.AddRange(moc
              .Cast<ManagementObject>()
              .Where(p => (ushort)(p.Properties["Level"].Value) == (ushort)level)
              .Select(p => (uint)(p.Properties["MaxCacheSize"].Value)));
            return cacheSizes;
        }
    }
}

Win32_CacheMemory WMI类的全部详细信息可在:

http://msdn.microsoft.com/en-us/library/aa394080 (v = vs.85) . aspx

这是你要找的吗?Win32_Processor类具有L2CacheSize和L3CacheSize成员。

    using System;
    using System.Runtime.InteropServices;
    class Processor
    {
        [DllImport("kernel32.dll")]
        public static extern int GetCurrentThreadId();
        //[DllImport("kernel32.dll")]
        //public static extern int GetCurrentProcessorNumber();
        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        private struct GROUP_AFFINITY
        {
            public UIntPtr Mask;
            [MarshalAs(UnmanagedType.U2)]
            public ushort Group;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U2)]
            public ushort[] Reserved;
        }
        [DllImport("kernel32", SetLastError = true)]
        private static extern Boolean SetThreadGroupAffinity(IntPtr hThread, ref GROUP_AFFINITY GroupAffinity, ref GROUP_AFFINITY PreviousGroupAffinity);
        [StructLayout(LayoutKind.Sequential)]
        public struct PROCESSORCORE
        {
            public byte Flags;
        };
        [StructLayout(LayoutKind.Sequential)]
        public struct NUMANODE
        {
            public uint NodeNumber;
        }
        public enum PROCESSOR_CACHE_TYPE
        {
            CacheUnified,
            CacheInstruction,
            CacheData,
            CacheTrace
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct CACHE_DESCRIPTOR
        {
            public byte Level;
            public byte Associativity;
            public ushort LineSize;
            public uint Size;
            public PROCESSOR_CACHE_TYPE Type;
        }
        [StructLayout(LayoutKind.Explicit)]
        public 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;
        }
        public enum LOGICAL_PROCESSOR_RELATIONSHIP
        {
            RelationProcessorCore,
            RelationNumaNode,
            RelationCache,
            RelationProcessorPackage,
            RelationGroup,
            RelationAll = 0xffff
        }
        public struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION
        {
#pragma warning disable 0649
            public UIntPtr ProcessorMask;
            public LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
            public SYSTEM_LOGICAL_PROCESSOR_INFORMATION_UNION ProcessorInformation;
#pragma warning restore 0649
        }
        [DllImport(@"kernel32.dll", SetLastError = true)]
        public static extern bool GetLogicalProcessorInformation(IntPtr Buffer, ref uint ReturnLength);
        private const int ERROR_INSUFFICIENT_BUFFER = 122;
        private static SYSTEM_LOGICAL_PROCESSOR_INFORMATION[] _logicalProcessorInformation = null;
        public static SYSTEM_LOGICAL_PROCESSOR_INFORMATION[] LogicalProcessorInformation
        {
            get
            {
                if (_logicalProcessorInformation != null)
                    return _logicalProcessorInformation;
                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;
                            _logicalProcessorInformation = new SYSTEM_LOGICAL_PROCESSOR_INFORMATION[len];
                            IntPtr Item = Ptr;
                            for (int i = 0; i < len; i++)
                            {
                                _logicalProcessorInformation[i] = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION)Marshal.PtrToStructure(Item, typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
                                Item += size;
                            }
                            return _logicalProcessorInformation;
                        }
                    }
                    finally
                    {
                        Marshal.FreeHGlobal(Ptr);
                    }
                }
                return null;
            }
        }
    }

方便的辅助功能:

public static void GetPerCoreCacheSizes(out Int64  L1, out Int64 L2, out Int64 L3)
{
    L1 = 0;
    L2 = 0;
    L3 = 0;
    var info = Processor.LogicalProcessorInformation;
    foreach (var entry in info)
    {
        if (entry.Relationship != Processor.LOGICAL_PROCESSOR_RELATIONSHIP.RelationCache)
            continue;
        Int64 mask = (Int64)entry.ProcessorMask;
        if ((mask & (Int64)1) == 0)
            continue;
        var cache = entry.ProcessorInformation.Cache;
        switch (cache.Level)
        {
            case 1: L1 = L1 + cache.Size; break;
            case 2: L2 = L2 + cache.Size; break;
            case 3: L3 = L3 + cache.Size; break;
            default:
                break;
        }
    }

并命名为:

static void Main(string[] args)
{
    long l1, l2, l3;
    GetPerCoreCacheSizes(out l1, out l2, out l3);
    String s = String.Format("Single-core memory cache: L1={0} KB, L2={1} KB, L3={2} KB", l1 / 1024, l2 / 1024, l3 / 1024);
    Console.WriteLine(s);
    Console.ReadLine();
}

:

Single-core memory cache: L1=64 KB, L2=256 KB, L3=6144 KB

试试这个代码

using System.Management;
uint32 cachsize;
public void CPUSpeed()
{
  using(ManagementObject Mo = new ManagementObject("Win32_Processor.DeviceID='CPU0'"))
  {
    cachsize = (uint)(Mo["L2CacheSize"]);
  }
}

我从这里得到它