Link to home
Start Free TrialLog in
Avatar of Joel Miller
Joel MillerFlag for United States of America

asked on

Determine physical CPU count for a computer using C#

I am writing a simple asset management application to collect information about remote computers and store the information in a database for reporting. I am mostly using WMI to collect the information.

The issue I am having is that no matter how I try to collect the CPU count, I get back incorrect information. Because of the introduction of Hyperthreading and Dual Core CPUs, the CPU counts show double or even quadruple CPU counts. For example, if a computer has 2 physical CPUs and have hyperthreading enabled, the CPU count will show as 4 CPUs. If the same computer is using Dual Core CPUs with Hyperthreading enabled, the CPU count will be 8. This is the number shown anywhere you look in the operating system is also skewed by dual core and hyperthreaded CPUs.

Does anyone have any idea of a way I can determine the real physical CPU count?

Thanks in adavance!
Avatar of Nightman
Nightman
Flag of Australia image

Avatar of Joel Miller

ASKER

It appears that this is a C# client applications that calls a C++ coded compiled DLL. In this case, it would be C++ that is determining the CPU counts. Do you how this might convert to C# or another way?  I would rather not reference any external DLLs and only use the built -in .NET framework.

Thanks!
I'll be honest, you got me intrigued, so I have been doing some googling since I posted this. This is the best sample I could find that uses C#. The C++ is managed C++, so is native .NET anyway, but I suspect that this is not properly exposed in .NET.

It is also possible that the sample in that article does not accurately count the cores, but I don't have a DC machine with me right now to test it.

If I find more, I will post here.
Avatar of ostdp
ostdp

You can use

            ManagementClass mc = new ManagementClass("Win32_Processor");
            ManagementObjectCollection moc = mc.GetInstances();

to get the WMI information on the processors.


Have a look in the System.Management documnetation.
Thanks ostdp,
However, that returns the logical, not the physical processor count. I am very familiar on the WMI object model, however, it appears that you cannot return the physical count, only the logical count. If there is a way to convert that C++ code to C#, that would defnitely suffice.

Thanks
ASKER CERTIFIED SOLUTION
Avatar of Expert1701
Expert1701

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Expert1701 ,
It appears that this code only reads the ProcessorID using WMI and counts all the unique instances. However, on a PowerEdge 6650, Xeon, Quad Proc server, this only returned 1 processor. When looking over the Processor ID in WMI (Win32_Processor), I can find 8 instances of processors, all of them have the same ProcessorID. This is why when I ran the utility, it only returned 1 processor.
It also appears that if I were to use the C++ compiled dll, I would not be able to check the CPU count remotely, as it does not have an interface for that. I need to be able to connect to hundreds of servers and remotely determine the physical CPU count.

I hope that helps.

Thanks!
Can you examine the other properties for something that is unique?
That is the problem. I have looked at all of the Win32_Processor WMI properties and not found anything that is unique to physical processors. I am looking for any other possibilities.

Thanks!
What operating system is that PowerEdge 6650 running?
Windows 2003 SP1
OK, Thanks everyone. I finally got this working. In the spirit of sharing, this is what I have. So far, it appears to work. I will be running a test tonight against all servers and comparing that data with the purchase orders (they are on paper and they specify the real processor count, I wanted something automated though...)

I found that the SocketDesignation property from the Win32_Processor class has which physical socket the CPU is located in. If there are more than one logical CPUs using a single socket, I can ignore that duplicate (it is a virtual CPU). I used the same code that Expert1701 provided exchanging ProcessorID with SocketDesignation.

I will keep the Q open until tomorrow until I can verify this works on all servers. If this does work, i will award the points to Expert1702

Thanks everyone!


--------- Begin code snippet here -------------------------------------------------------
using System;
  using System.Collections;
  using System.Management;
  using System.Runtime.InteropServices;

  class Program
  {
    static void Main()
    {
      Console.WriteLine("Logical CPUs:  " + Environment.ProcessorCount);
      Console.WriteLine("Physical CPUs: " + PhysicalProcessorCount());
      Console.ReadLine();
    }

    static int PhysicalProcessorCount()
    {
      ArrayList processors = new ArrayList();

      foreach (ManagementObject mo in new ManagementClass("Win32_Processor").GetInstances())
      {
        string id = (string)mo.Properties["SocketDesignation"].Value;

        if (!processors.Contains(id))
          processors.Add(id);
      }

      return processors.Count;
    }
  }
--------- End code snippet here -------------------------------------------------------
I tested and verified this. this works as planned.

Thank you everyone!
Just out of curiosity, what types of values does SocketDesignation have on a multi-processor system?
Here is a sample:
-----------------------------------
Win32_Processor instance
-----------------------------------
SocketDesignation: PROC_1
-----------------------------------
Win32_Processor instance
-----------------------------------
SocketDesignation: PROC_2
-----------------------------------
Win32_Processor instance
-----------------------------------
SocketDesignation: PROC_3
-----------------------------------
Win32_Processor instance
-----------------------------------
SocketDesignation: PROC_4
-----------------------------------
Win32_Processor instance
-----------------------------------
SocketDesignation: PROC_1
-----------------------------------
Win32_Processor instance
-----------------------------------
SocketDesignation: PROC_1
-----------------------------------
Win32_Processor instance
-----------------------------------
SocketDesignation: PROC_1
-----------------------------------
Win32_Processor instance
-----------------------------------
SocketDesignation: PROC_1
FYI - That shows 8 logical instances but only 4 unique socket designations. This means that out of the 8 logical processors in the system, they are only using 4 physical sockets. That means that 4 processors are physically installed.
Thanks for the great response, jmiller47!