8

So I've been experimenting with the performance counter class in C# and have had great success probing the CPU counters and almost everything I can find in the windows performance monitor. HOWEVER, I cannot gain access to the "NVIDIA GPU" category...

So for example, the following line of code is how it usually works.

PerformanceCounter cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");

That code works fine, but the GPU category that appeared in the performance monitor, just as the processor category did, is not accessible by C#. The following line of code attempts to access it.

PerformanceCounter gpuCounter = new PerformanceCounter("NVIDIA GPU", "% GPU Usage","#0 Quadro K1100M(id=1, NVAPI ID=256)");

Instead it throws a "Category does not exist" exception...

Here is what it looks like from within the Performance Monitor

enter image description here

The category clearly exists, so my question is... how do I access this counter?

Alex E
  • 269
  • 1
  • 2
  • 8
  • I've already looked into Nvidia PerfKit, the documentation is not very helpful , so it might work but there is too much information there and not enough run-time examples. – Alex E Apr 03 '16 at 19:17
  • Not sure if this matters or not, but I noticed the category name you provided DOES NOT match the string as shown in your screen shot. Your code has no space between K1100M and the open parenthesis. Again, might not matter, but something I noticed. – Michael A. Allen Aug 31 '21 at 22:06

2 Answers2

17

After spending six hours on this, I am ready to share my results. There were several testing methods used to search for this missing performance counter.

1) The first was a very simple search for keywords. This included PerformaceCounterCategory's as well as every single instance of performance counter running on my system (around 12,000 of them). This method did not find anything GPU or NVIDIA related, but worked flawlessly for the CPU.

2) The next test was performed by running the GPU at a very specific % usage and a search was performed that evaluated every percentage performance counter running within a narrow range of values. This method also did not return anything GPU related, but again worked flawlessly for the CPU.

This lead to one conclusion. There truly is no performance counter for the GPU, not even under a false alias.


Solution:

Nowhere does it state that the performance monitor must explicitly use performance counters, and a small hint to this was staring us in the face this entire time. The instance variable in the performance monitor was labeled "NVAPI ID=256". The NVIDIA API was designed to allow performance monitoring capabilities to NVIDIA hardware. Although it can perform actions similar to performance counters, it does not use the same data types to perform its task. We now have evidence that the Performance Monitor was using the NVAPI to gather information instead of using a performance counter. This was very misleading because every other entry corresponds to a counter. So we can conclude that the only proper way to access these variables is through the NVAPI.

I was able to do this successfully by first downloading the NVAPI from the NVIDIA website here.

Next I used some sample code found here from a blogger that is using Open Hardware Monitor source code, and here from another post on this site.

The code is written in C++, but after moving some libraries around and making a few .dll's everything ports nicely to C#.

Here is a picture of the result. Thank you everyone for your help and support!

enter image description here

Community
  • 1
  • 1
Alex E
  • 269
  • 1
  • 2
  • 8
2

Doing a PerformanceCounterCategory.GetCategories() will get you a list of all categories on your system, once you find the correct catagory you can use PerformanceCounterCategory.GetCounters() will list all counters in that catagory so you can get the correct name.

var cat = new PerformanceCounterCategory("Whatever the correct category name is");
var counters = cat.GetCounters();

Update:

Try this to search for it

static void Main(string[] args)
{
    var counters = PerformanceCounterCategory.GetCategories()
        .SelectMany(x=>x.GetCounters("")).Where(x => x.CounterName.Contains("GPU"));

    foreach (var counter in counters)
    {
        Console.WriteLine("{0} - {1}", counter.CategoryName, counter.CounterName);
    }
    Console.ReadLine();
}
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
  • 1
    I checked my performance counters and I don't have that category on my machine, otherwise I would have also included what the actual name is too – Scott Chamberlain Apr 04 '16 at 00:25
  • 1
    Likewise, as stated above, the category does not exist. PerformanceCounterCategory.GetCategories() does not return anything GPU or NVIDIA related. So the question still remains, how do I access this category that is found in the PerfMon but not publicly visible. – Alex E Apr 04 '16 at 12:28
  • This just does not make sense, there is no way to do a private counter, it must be there but under a name you are not expecting. Perhaps some kind of cryptic abbreviation? I really wish I could help more but as I said I did not have "NVIDIA GPU" in my Add Counters menu like you did so I am flying a little blind. – Scott Chamberlain Apr 04 '16 at 13:38
  • @AlexE try the search code in my update, do you get anything useful there? – Scott Chamberlain Apr 04 '16 at 13:55
  • @AlexE another thing you can try, from the command line do `typeperf -q -o "C:\Temp\counters.txt"` then in the txt file it generates search for `GPU`. – Scott Chamberlain Apr 04 '16 at 14:05
  • Thank you so much for your help. I used similar tactics to track down the problem and posted my results below. – Alex E Apr 05 '16 at 13:54