6

Is there a standard way of getting GPU percent usage in Cocoa/Objective-C on OS X (10.6 and 10.7)?

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
houbysoft
  • 32,532
  • 24
  • 103
  • 156

1 Answers1

8

Enjoy it, GPU and RAM usage , doesn't work on the discreet GPU btw because it does not expose the performances monitoring dictionary. My MBP has an NVIDIA gpu, should work on ATI too but I'm not sure 100%

#include <CoreFoundation/CoreFoundation.h>
#include <Cocoa/Cocoa.h>
#include <IOKit/IOKitLib.h>

int main(int argc, const char * argv[])
{

while (1) {

    // Get dictionary of all the PCI Devicces
    CFMutableDictionaryRef matchDict = IOServiceMatching(kIOAcceleratorClassName);

    // Create an iterator
    io_iterator_t iterator;

    if (IOServiceGetMatchingServices(kIOMasterPortDefault,matchDict,
                                     &iterator) == kIOReturnSuccess)
    {
        // Iterator for devices found
        io_registry_entry_t regEntry;

        while ((regEntry = IOIteratorNext(iterator))) {
            // Put this services object into a dictionary object.
            CFMutableDictionaryRef serviceDictionary;
            if (IORegistryEntryCreateCFProperties(regEntry,
                                                  &serviceDictionary,
                                                  kCFAllocatorDefault,
                                                  kNilOptions) != kIOReturnSuccess)
            {
                // Service dictionary creation failed.
                IOObjectRelease(regEntry);
                continue;
            }

            CFMutableDictionaryRef perf_properties = (CFMutableDictionaryRef) CFDictionaryGetValue( serviceDictionary, CFSTR("PerformanceStatistics") );
            if (perf_properties) {

                static ssize_t gpuCoreUse=0;
                static ssize_t freeVramCount=0;
                static ssize_t usedVramCount=0;

                const void* gpuCoreUtilization = CFDictionaryGetValue(perf_properties, CFSTR("GPU Core Utilization"));
                const void* freeVram = CFDictionaryGetValue(perf_properties, CFSTR("vramFreeBytes"));
                const void* usedVram = CFDictionaryGetValue(perf_properties, CFSTR("vramUsedBytes"));
                if (gpuCoreUtilization && freeVram && usedVram)
                {
                    CFNumberGetValue( (CFNumberRef) gpuCoreUtilization, kCFNumberSInt64Type, &gpuCoreUse);
                    CFNumberGetValue( (CFNumberRef) freeVram, kCFNumberSInt64Type, &freeVramCount);
                    CFNumberGetValue( (CFNumberRef) usedVram, kCFNumberSInt64Type, &usedVramCount);
                    NSLog(@"GPU: %.3f%% VRAM: %.3f%%",gpuCoreUse/(double)10000000,usedVramCount/(double)(freeVramCount+usedVramCount)*100.0);

                }

            }

            CFRelease(serviceDictionary);
            IOObjectRelease(regEntry);
        }
        IOObjectRelease(iterator);
    }

   sleep(1);
}
return 0;
}
Leonardo Bernardini
  • 1,076
  • 13
  • 23
  • So there is no way to get both dedicated and discreet gpu data? – Coldsteel48 Mar 24 '14 at 00:51
  • nope, the discreet GPU does not expose performances data, I've also discovered that neither ATI exposes it, just the VRAM usage, but nothing for the GPU usage :/ – Leonardo Bernardini Mar 27 '14 at 16:47
  • Hello again, How can I modify the code so it will support 2 or more GPUs? I don't have such Hardware though I don't have an Idea where to start could you please help ? – Coldsteel48 Jun 14 '15 at 15:27
  • 1
    @Leonardo Bernardini, The code example doesn't work for me. Although "perf_properties" seems to get a good value, its members: "gpuCoreUtilization", "freeVram", and "usedVram" are all NULL. I realize that the code was provided about 3 years ago. I am using Xcode 8.2.1. – Kaydell Feb 01 '17 at 23:21
  • 1
    don't think the Xcode version or SDK is a problem but rather the GPU driver. As I said from my test some cpus fills the dictionary while others no, so there should be another way maybe – Leonardo Bernardini Mar 05 '17 at 13:50
  • 6
    `vramUsedBytes` and `GPU Core Utilization` do not exist (anymore). The solution is to pick `"VRAM,totalMB"` from either `IOAccelerator` or `IOPCIDevice`. The VRAM of the Intel GPU for example is in `IOAccelerator`, and the VRAM of AMD is in `IOPCIDevice`. In `PerformanceStatistics` of `IOAccelerator` you'll find only `vramFreeBytes` for the active GPU. `GPU Core Utilization ` has also been renamed to `Device Utilization %` or `GPU Activity(%)`. – Marc J. Schmidt Mar 05 '20 at 01:57
  • Although @MarcJ.Schmidt is correct, it's important to check for all three as no device driver is guaranteed to expose the same names as the other. Furthermore, it's wise to check ahead of time which one your driver references by typing `ioreg -r -d 1 -w 0 -c "IOAccelerator"` to see for yourself. You will also find other values that you can query, such as GPU video engine, renderer engine, tiler engine and even "Device Unit n Utilization" if needed. – blueshogun96 Mar 30 '20 at 11:37