From: "Christian König" <ckoenig.leichtzumerken@gmail.com>
To: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>,
igt-dev@lists.freedesktop.org
Cc: Rob Clark <robdclark@chromium.org>,
Intel-gfx@lists.freedesktop.org,
Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Subject: Re: [igt-dev] [PATCH i-g-t 8/8] gputop: Basic vendor agnostic GPU top tool
Date: Fri, 17 Jun 2022 13:33:25 +0200 [thread overview]
Message-ID: <64127964-4c0a-f486-42da-4b110405833e@gmail.com> (raw)
In-Reply-To: <af41c69f-c79c-e7e0-43a1-053dd08faaa8@linux.intel.com>
Am 17.06.22 um 12:09 schrieb Tvrtko Ursulin:
>
> On 17/06/2022 08:20, Christian König wrote:
>> Am 16.06.22 um 16:06 schrieb Tvrtko Ursulin:
>>> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>>>
>>> Rudimentary vendor agnostic example of how lib_igt_drm_clients can
>>> be used
>>> to display a sorted by card and usage list of processes using GPUs.
>>>
>>> Borrows a bit of code from intel_gpu_top but for now omits the fancy
>>> features like interactive functionality, card selection, client
>>> aggregation, sort modes, JSON output and pretty engine names. Also no
>>> support for global GPU or system metrics.
>>>
>>> On the other hand it shows clients from all DRM cards which
>>> intel_gpu_top does not do.
>>>
>>> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>>> Cc: Rob Clark <robdclark@chromium.org>
>>> Cc: Christian König <ckoenig.leichtzumerken@gmail.com>
>>
>> LGTM, Acked-by: Christian König <christian.koenig@amd.com>
>
> Thanks Christian,
>
> It is a very rudimentary tool, more a reference really. I keep hoping
> some UI/desktop folks actually pick up the idea and implement
> something nicer elsewhere. Or maybe it ends up me spending a little
> bit more time on it, to carry over some more functionality from
> intel_gpu_top.
>
> I see amdgpu patches are in - presumably that means gputop parses it
> and understands fine?
At least the last time I tested it the tool worked like a charm.
And yes, it's indeed rather useful.
Regards,
Christian.
>
> Regards,
>
> Tvrtko
>
>>> ---
>>> tools/gputop.c | 260
>>> ++++++++++++++++++++++++++++++++++++++++++++++
>>> tools/meson.build | 5 +
>>> 2 files changed, 265 insertions(+)
>>> create mode 100644 tools/gputop.c
>>>
>>> diff --git a/tools/gputop.c b/tools/gputop.c
>>> new file mode 100644
>>> index 000000000000..d259cac1ab17
>>> --- /dev/null
>>> +++ b/tools/gputop.c
>>> @@ -0,0 +1,260 @@
>>> +// SPDX-License-Identifier: MIT
>>> +/*
>>> + * Copyright © 2022 Intel Corporation
>>> + */
>>> +
>>> +#include <assert.h>
>>> +#include <ctype.h>
>>> +#include <dirent.h>
>>> +#include <errno.h>
>>> +#include <fcntl.h>
>>> +#include <inttypes.h>
>>> +#include <limits.h>
>>> +#include <locale.h>
>>> +#include <math.h>
>>> +#include <poll.h>
>>> +#include <signal.h>
>>> +#include <stdint.h>
>>> +#include <stdio.h>
>>> +#include <stdlib.h>
>>> +#include <string.h>
>>> +#include <sys/ioctl.h>
>>> +#include <sys/stat.h>
>>> +#include <sys/types.h>
>>> +#include <unistd.h>
>>> +#include <termios.h>
>>> +#include <sys/sysmacros.h>
>>> +#include <stdbool.h>
>>> +
>>> +#include "igt_drm_clients.h"
>>> +#include "igt_drm_fdinfo.h"
>>> +
>>> +static const char *bars[] = { " ", "▏", "▎", "▍", "▌", "▋", "▊",
>>> "▉", "█" };
>>> +
>>> +static void n_spaces(const unsigned int n)
>>> +{
>>> + unsigned int i;
>>> +
>>> + for (i = 0; i < n; i++)
>>> + putchar(' ');
>>> +}
>>> +
>>> +static void print_percentage_bar(double percent, int max_len)
>>> +{
>>> + int bar_len, i, len = max_len - 2;
>>> + const int w = 8;
>>> +
>>> + assert(max_len > 0);
>>> +
>>> + bar_len = ceil(w * percent * len / 100.0);
>>> + if (bar_len > w * len)
>>> + bar_len = w * len;
>>> +
>>> + putchar('|');
>>> +
>>> + for (i = bar_len; i >= w; i -= w)
>>> + printf("%s", bars[w]);
>>> + if (i)
>>> + printf("%s", bars[i]);
>>> +
>>> + len -= (bar_len + (w - 1)) / w;
>>> + n_spaces(len);
>>> +
>>> + putchar('|');
>>> +}
>>> +
>>> +static int
>>> +print_client_header(struct igt_drm_client *c, int lines, int con_w,
>>> int con_h,
>>> + int *engine_w)
>>> +{
>>> + const char *pidname = " PID NAME ";
>>> + int ret, len = strlen(pidname);
>>> +
>>> + if (lines++ >= con_h || len >= con_w)
>>> + return lines;
>>> + printf("\033[7m");
>>> + ret = printf("DRM minor %u", c->drm_minor);
>>> + n_spaces(con_w - ret);
>>> +
>>> + if (lines++ >= con_h)
>>> + return lines;
>>> + printf("\n%s", pidname);
>>> +
>>> + if (c->engines->num_engines) {
>>> + unsigned int i;
>>> + int width;
>>> +
>>> + *engine_w = width = (con_w - len) / c->engines->num_engines;
>>> +
>>> + for (i = 0; i <= c->engines->max_engine_id; i++) {
>>> + const char *name = c->engines->names[i];
>>> + int name_len = strlen(name);
>>> + int pad = (width - name_len) / 2;
>>> + int spaces = width - pad - name_len;
>>> +
>>> + if (!name)
>>> + continue;
>>> +
>>> + if (pad < 0 || spaces < 0)
>>> + continue;
>>> +
>>> + n_spaces(pad);
>>> + printf("%s", name);
>>> + n_spaces(spaces);
>>> + len += pad + name_len + spaces;
>>> + }
>>> + }
>>> +
>>> + n_spaces(con_w - len);
>>> + printf("\033[0m\n");
>>> +
>>> + return lines;
>>> +}
>>> +
>>> +
>>> +static bool
>>> +newheader(const struct igt_drm_client *c, const struct
>>> igt_drm_client *pc)
>>> +{
>>> + return !pc || c->drm_minor != pc->drm_minor;
>>> +}
>>> +
>>> +static int
>>> +print_client(struct igt_drm_client *c, struct igt_drm_client **prevc,
>>> + double t, int lines, int con_w, int con_h,
>>> + unsigned int period_us, int *engine_w)
>>> +{
>>> + unsigned int i;
>>> +
>>> + /* Filter out idle clients. */
>>> + if (!c->total_runtime || c->samples < 2)
>>> + return lines;
>>> +
>>> + /* Print header when moving to a different DRM card. */
>>> + if (newheader(c, *prevc)) {
>>> + lines = print_client_header(c, lines, con_w, con_h, engine_w);
>>> + if (lines >= con_h)
>>> + return lines;
>>> + }
>>> +
>>> + *prevc = c;
>>> +
>>> + printf("%8u %17s ", c->pid, c->print_name);
>>> + lines++;
>>> +
>>> + for (i = 0; c->samples > 1 && i <= c->engines->max_engine_id;
>>> i++) {
>>> + double pct;
>>> +
>>> + if (!c->engines->capacity[i])
>>> + continue;
>>> +
>>> + pct = (double)c->val[i] / period_us / 1e3 * 100 /
>>> + c->engines->capacity[i];
>>> +
>>> + /*
>>> + * Guard against fluctuations between our scanning period and
>>> + * GPU times as exported by the kernel in fdinfo.
>>> + */
>>> + if (pct > 100.0)
>>> + pct = 100.0;
>>> +
>>> + print_percentage_bar(pct, *engine_w);
>>> + }
>>> +
>>> + putchar('\n');
>>> +
>>> + return lines;
>>> +}
>>> +
>>> +static int
>>> +__client_id_cmp(const struct igt_drm_client *a,
>>> + const struct igt_drm_client *b)
>>> +{
>>> + if (a->id > b->id)
>>> + return 1;
>>> + else if (a->id < b->id)
>>> + return -1;
>>> + else
>>> + return 0;
>>> +}
>>> +
>>> +static int client_cmp(const void *_a, const void *_b, void *unused)
>>> +{
>>> + const struct igt_drm_client *a = _a;
>>> + const struct igt_drm_client *b = _b;
>>> + long val_a, val_b;
>>> +
>>> + /* DRM cards into consecutive buckets first. */
>>> + val_a = a->drm_minor;
>>> + val_b = b->drm_minor;
>>> + if (val_a > val_b)
>>> + return 1;
>>> + else if (val_b > val_a)
>>> + return -1;
>>> +
>>> + /*
>>> + * Within buckets sort by last sampling period aggregated
>>> runtime, with
>>> + * client id as a tie-breaker.
>>> + */
>>> + val_a = a->last_runtime;
>>> + val_b = b->last_runtime;
>>> + if (val_a == val_b)
>>> + return __client_id_cmp(a, b);
>>> + else if (val_b > val_a)
>>> + return 1;
>>> + else
>>> + return -1;
>>> +
>>> +}
>>> +
>>> +int main(int argc, char **argv)
>>> +{
>>> + unsigned int period_us = 2e6;
>>> + struct igt_drm_clients *clients = NULL;
>>> + int con_w = -1, con_h = -1;
>>> +
>>> + clients = igt_drm_clients_init(NULL);
>>> + if (!clients)
>>> + exit(1);
>>> +
>>> + igt_drm_clients_scan(clients, NULL, NULL, 0);
>>> +
>>> + for (;;) {
>>> + struct igt_drm_client *c, *prevc = NULL;
>>> + int i, engine_w = 0, lines = 0;
>>> + struct winsize ws;
>>> +
>>> + if (ioctl(0, TIOCGWINSZ, &ws) != -1) {
>>> + con_w = ws.ws_col;
>>> + con_h = ws.ws_row;
>>> + if (con_w == 0 && con_h == 0) {
>>> + /* Serial console. */
>>> + con_w = 80;
>>> + con_h = 24;
>>> + }
>>> + }
>>> +
>>> + igt_drm_clients_scan(clients, NULL, NULL, 0);
>>> + igt_drm_clients_sort(clients, client_cmp);
>>> +
>>> + printf("\033[H\033[J");
>>> +
>>> + igt_for_each_drm_client(clients, c, i) {
>>> + assert(c->status != IGT_DRM_CLIENT_PROBE);
>>> + if (c->status != IGT_DRM_CLIENT_ALIVE)
>>> + break; /* Active clients are first in the array. */
>>> +
>>> + lines = print_client(c, &prevc, (double)period_us / 1e6,
>>> + lines, con_w, con_h, period_us,
>>> + &engine_w);
>>> + if (lines >= con_h)
>>> + break;
>>> + }
>>> +
>>> + if (lines++ < con_h)
>>> + printf("\n");
>>> +
>>> + usleep(period_us);
>>> + }
>>> +
>>> + return 0;
>>> +}
>>> diff --git a/tools/meson.build b/tools/meson.build
>>> index ade00ee4df61..d5cb459b619d 100644
>>> --- a/tools/meson.build
>>> +++ b/tools/meson.build
>>> @@ -70,6 +70,11 @@ if libudev.found()
>>> install : true)
>>> endif
>>> +executable('gputop', 'gputop.c',
>>> + install : true,
>>> + install_rpath : bindir_rpathdir,
>>> + dependencies :
>>> [lib_igt_drm_clients,lib_igt_drm_fdinfo,math])
>>> +
>>> intel_l3_parity_src = [ 'intel_l3_parity.c',
>>> 'intel_l3_udev_listener.c' ]
>>> executable('intel_l3_parity', sources : intel_l3_parity_src,
>>> dependencies : tool_deps,
>>
next prev parent reply other threads:[~2022-06-17 11:33 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-16 14:06 [igt-dev] [PATCH i-g-t 0/8] Vendor agnostic gputop Tvrtko Ursulin
2022-06-16 14:06 ` [igt-dev] [PATCH i-g-t 1/8] lib: Extract igt_drm_clients from intel_gpu_top Tvrtko Ursulin
2022-06-16 14:06 ` [igt-dev] [PATCH i-g-t 2/8] libdrmfdinfo: Allow specifying custom engine map Tvrtko Ursulin
2022-06-16 14:06 ` [igt-dev] [PATCH i-g-t 3/8] libdrmclients: Record client drm minor Tvrtko Ursulin
2022-06-16 14:06 ` [igt-dev] [PATCH i-g-t 4/8] libdrmclient: Support multiple DRM cards Tvrtko Ursulin
2022-06-16 14:06 ` [igt-dev] [PATCH i-g-t 5/8] libdrmfdinfo: Track largest engine index Tvrtko Ursulin
2022-06-16 14:06 ` [igt-dev] [PATCH i-g-t 6/8] libdrmclient/intel_gpu_top: Decouple hardcoded engine assumptions Tvrtko Ursulin
2022-06-16 14:06 ` [igt-dev] [PATCH i-g-t 7/8] libdrmclient: Enforce client status sort order in the library Tvrtko Ursulin
2022-06-16 14:06 ` [igt-dev] [PATCH i-g-t 8/8] gputop: Basic vendor agnostic GPU top tool Tvrtko Ursulin
2022-06-17 7:20 ` Christian König
2022-06-17 10:09 ` Tvrtko Ursulin
2022-06-17 11:33 ` Christian König [this message]
2022-06-16 15:57 ` [igt-dev] ✓ Fi.CI.BAT: success for Vendor agnostic gputop (rev3) Patchwork
2022-06-16 22:41 ` [igt-dev] ✗ Fi.CI.IGT: failure " Patchwork
-- strict thread matches above, loose matches on Subject: below --
2023-04-17 10:57 [igt-dev] [PATCH i-g-t v5 0/8] Vendor agnostic gputop Tvrtko Ursulin
2023-04-17 10:57 ` [igt-dev] [PATCH i-g-t 8/8] gputop: Basic vendor agnostic GPU top tool Tvrtko Ursulin
2023-04-06 14:15 [igt-dev] [PATCH i-g-t v4 0/8] Vendor agnostic gputop Tvrtko Ursulin
2023-04-06 14:15 ` [igt-dev] [PATCH i-g-t 8/8] gputop: Basic vendor agnostic GPU top tool Tvrtko Ursulin
2023-01-31 11:32 [igt-dev] [PATCH i-g-t v3 0/8] Vendor agnostic gputop Tvrtko Ursulin
2023-01-31 11:32 ` [igt-dev] [PATCH i-g-t 8/8] gputop: Basic vendor agnostic GPU top tool Tvrtko Ursulin
2023-02-03 16:42 ` Kamil Konieczny
2023-02-06 9:19 ` Tvrtko Ursulin
2023-02-06 14:04 ` Kamil Konieczny
2023-04-05 17:57 ` Rob Clark
2023-04-06 11:08 ` Tvrtko Ursulin
2023-04-06 14:21 ` Rob Clark
2023-04-06 14:31 ` Tvrtko Ursulin
2023-05-12 14:18 ` Rob Clark
2023-05-15 11:10 ` Tvrtko Ursulin
2022-11-11 15:58 [igt-dev] [PATCH i-g-t 0/8] Vendor agnostic gputop Tvrtko Ursulin
2022-11-11 15:58 ` [igt-dev] [PATCH i-g-t 8/8] gputop: Basic vendor agnostic GPU top tool Tvrtko Ursulin
2022-11-16 13:43 ` Philipp Zabel
2022-05-11 12:18 [igt-dev] [PATCH i-g-t 0/8] Vendor agnostic gputop Tvrtko Ursulin
2022-05-11 12:18 ` [igt-dev] [PATCH i-g-t 8/8] gputop: Basic vendor agnostic GPU top tool Tvrtko Ursulin
2022-05-11 14:42 ` Christian König
2022-05-11 15:07 ` Tvrtko Ursulin
2022-04-05 8:41 [igt-dev] [PATCH i-g-t 0/8] Vendor agnostic gputop Tvrtko Ursulin
2022-04-05 8:41 ` [igt-dev] [PATCH i-g-t 8/8] gputop: Basic vendor agnostic GPU top tool Tvrtko Ursulin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=64127964-4c0a-f486-42da-4b110405833e@gmail.com \
--to=ckoenig.leichtzumerken@gmail.com \
--cc=Intel-gfx@lists.freedesktop.org \
--cc=igt-dev@lists.freedesktop.org \
--cc=robdclark@chromium.org \
--cc=tvrtko.ursulin@intel.com \
--cc=tvrtko.ursulin@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox