I would like to know if there is a way to determine CPU cache size in managed code?
I am writing a Strassen\'s algorithm for matrix multiplication in C# and would li
Try this code
using System.Management;
uint32 cachsize;
public void CPUSpeed()
{
using(ManagementObject Mo = new ManagementObject("Win32_Processor.DeviceID='CPU0'"))
{
cachsize = (uint)(Mo["L2CacheSize"]);
}
}
I get it from Here
is this what you are looking for? The Win32_Processor class features L2CacheSize and L3CacheSize members.
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;
}
}
}
Handy helper function:
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;
}
}
And call it:
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();
}
Output:
Single-core memory cache: L1=64 KB, L2=256 KB, L3=6144 KB
You can use WMI to retrieve cache information.
You will first need to add a reference to System.Management.dll
to your project, then you can use the following code:
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;
}
}
}
Full details of the Win32_CacheMemory
WMI class is available at:
http://msdn.microsoft.com/en-us/library/aa394080(v=vs.85).aspx