Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GPU monitoring (percentage and time) in Darwin/macOS #1597

Open
Explorer09 opened this issue Jan 30, 2025 · 7 comments
Open

GPU monitoring (percentage and time) in Darwin/macOS #1597

Explorer09 opened this issue Jan 30, 2025 · 7 comments
Labels
enhancement Extension or improvement to existing feature MacOS 🍏 MacOS / Darwin related issues
Milestone

Comments

@Explorer09
Copy link
Contributor

This is a feature ticket, for people who are more familiar with Darwin/macOS to try and implement.

The Activity Monitor app in macOS has GPU Percentage and GPU Time columns for process monitoring. There is also a "GPU History" feature that shows the GPU usage as a graph.

This webpage (from a third party, not Apple) has brief descriptions and screenshots about the GPU monitoring in macOS: https://www.alphr.com/view-gpu-usage-mac/

It might be possible for such feature to be implemented in htop, too.

After #1288, we have GPU monitoring in Linux now. The GPU meter and columns shouldn't be limited to Linux.

@BenBE BenBE added enhancement Extension or improvement to existing feature MacOS 🍏 MacOS / Darwin related issues labels Jan 31, 2025
@aestriplex
Copy link
Contributor

@BenBE cc @Explorer09
It would be great to have that feature in htop. If it's ok for you, I'd like to start thinking about a possible implementation.
I would start by separating two aspects of the problem.

  1. GPU model and its overall usage;
  2. GPU utilization by process.

I attach below a sample program that prints the overall GPU usage, which could be a first step to solve the first point, once properly adapted to the htop context.
Unfortunately, as far as I know, there is no direct way to solve the second problem, as there is no API to trace this information. I would therefore start with the first point, adding a section (similar to the CPU or RAM usage section) that contains:

  • The model and version of the GPU;
  • The number of cores;
  • Their total GPU core utilization.
#include <stdio.h>
#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CoreFoundation.h>

int main() {
    io_service_t service = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching("IOGPU"));

    if (!service) {
        printf("GPU not found\n");
        return 1;
    }

    CFMutableDictionaryRef properties = NULL;
    if (IORegistryEntryCreateCFProperties(service, &properties, kCFAllocatorDefault, kNilOptions) != KERN_SUCCESS) {
        fprintf(stderr, "Failed to get GPU properties\n");
        IOObjectRelease(service);
        return 1;
    }

    CFDictionaryRef perfStats = CFDictionaryGetValue(properties, CFSTR("PerformanceStatistics"));

    if (perfStats && CFGetTypeID(perfStats) == CFDictionaryGetTypeID()) {
        CFNumberRef rendererUtil, tilerUtil;
        
        rendererUtil = CFDictionaryGetValue(perfStats, CFSTR("Renderer Utilization %"));
        tilerUtil = CFDictionaryGetValue(perfStats, CFSTR("Tiler Utilization %"));

        int renderer, tiler;
        
        if (rendererUtil) CFNumberGetValue(rendererUtil, kCFNumberIntType, &renderer);
        if (tilerUtil) CFNumberGetValue(tilerUtil, kCFNumberIntType, &tiler);

        printf("Renderer Utilization: %d%%\n", renderer);
        printf("Tiler Utilization: %d%%\n", tiler);
    } else {
        printf("PerformanceStatistics not found\n");
    }

    CFRelease(properties);
    IOObjectRelease(service);
}

aestriplex added a commit to aestriplex/htop that referenced this issue Feb 5, 2025
@aestriplex
Copy link
Contributor

I added a commit with a draft of the GPU usage meter for macOS. At this point I just replicated the linux/GPUMeter.c and linux/GPUMeter.h. It uses a static service variable that is allocated in the GPUMeter_init and deallocated in GPUMeter_done.
If the GPU is not available (e.g. on the old intel Macs), it prints N/A instead of the percentage in the default style view. If you choose another style, it prints 0.0.

@BenBE Do you have any suggestion?

@Explorer09
Copy link
Contributor Author

Explorer09 commented Feb 5, 2025

@aestriplex Thank you for your effort.

  1. You can start a pull request so that htop contributors and I can comment on the code easily. GitHub allows reviewing code with comments by code line, but that requires you to start a PR first (you can mark the PR as a draft).

(By the way, you seem to be the first time contributing to htop. Hello and welcome.)

  1. My initial thoughts about your commit: First, I wish the GPUMeter.c and .h files be shared across platforms. Ideally we would move GPUMeter.c and .h from the linux/ sub-directory to the top source directory, and platform specific codes would be called from either <platform>/Platform.c or <platform>/<platform>Machine.c (or maybe <platform>/GPU.c). Do you think you can structure the code like that?

@BenBE
Copy link
Member

BenBE commented Feb 5, 2025

Unless the GPU stuff isn't too much code, putting things in <platform>/<Platform>Machine.c should be fine.

The BlankMeter should be the last in the list of meters.

IIRC there's a open PR re the time unit display in #1583, thus avoid to touch that code if possible.

When refactoring the GPU meter to the platform-independent code, split the refactoring and the new Darwin implementation to a separate commit.

@aestriplex
Copy link
Contributor

Thank you all for your comments, and sorry it took me a while to respond. @Explorer09 Thank you for the welcome message. Ok, I'll move GPUMeter.c and GPUMeter.h from the linux/ sub-directory to the top source directory. And yes, @BenBE I'll extract the logic I introduced into a function and I put it in darwin/DarwinMachine.c.

For what concerns the time unit display code that I moved, I'll bring it back in linux/GPUMeter.c.

@BenBE Ok, I'll split those changes in two separate commit. Once I have the two commits (hopefully tomorrow) I'll open the pull request.

@Explorer09
Copy link
Contributor Author

The humanTimeUnit() function is currently used only in the GPU meter, and it's too early to move the function to XUtils.c. Keep it in the GPUMeter.c, please. As for #1583, I can rebase it easily, so there's no need to worry about it right now.

@aestriplex
Copy link
Contributor

I further investigated the point 2. made above, that is, the issue of GPU utilization by process. As I mentioned, Apple has not released any public API for this purpose. The question was whether a way could be found to get a good approximation of this value in some other way. After a bit of research and some testing, I came to the conclusion that no, there is no way that is reliable and stable (over time) to get this kind of metric. The best thing in my opinion is simply not to implement it. After all, more open systems offer more information, and this is nothing new (think of metrics regarding systems on Linux; you couldn't do anything similar with launchd on Mac). On the other hand, even tools such as nvtop simply make an estimate of the processes using the GPU and their relative consumption, but if you compare it with Activity Monitor (the only tool that officially supports this feature), the values are very approximate, not to say simply wrong.
For my part, I think we could focus on other metrics that macOS makes available to us, some of which are already present in the libraries we are using. I will open an issue with a more detailed list tonight

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Extension or improvement to existing feature MacOS 🍏 MacOS / Darwin related issues
Projects
None yet
Development

No branches or pull requests

3 participants