From: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
To: Intel-gfx@lists.freedesktop.org
Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org,
"Tejun Heo" <tj@kernel.org>,
"Johannes Weiner" <hannes@cmpxchg.org>,
"Zefan Li" <lizefan.x@bytedance.com>,
"Dave Airlie" <airlied@redhat.com>,
"Daniel Vetter" <daniel.vetter@ffwll.ch>,
"Rob Clark" <robdclark@chromium.org>,
"Stéphane Marchesin" <marcheu@chromium.org>,
"T . J . Mercier" <tjmercier@google.com>,
Kenny.Ho@amd.com, "Christian König" <christian.koenig@amd.com>,
"Brian Welty" <brian.welty@intel.com>,
"Tvrtko Ursulin" <tvrtko.ursulin@intel.com>
Subject: [RFC 13/13] drm/i915: Implement cgroup controller over budget throttling
Date: Wed, 9 Nov 2022 16:11:41 +0000 [thread overview]
Message-ID: <20221109161141.2987173-14-tvrtko.ursulin@linux.intel.com> (raw)
In-Reply-To: <20221109161141.2987173-1-tvrtko.ursulin@linux.intel.com>
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
When notified by the drm core we are over our allotted time budget, i915
instance will check if any of the GPU engines it is reponsible for is
fully saturated. If it is, and the client in question is using that
engine, it will throttle it.
For now throttling is done simplistically by lowering the scheduling
priority while client is throttled.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
.../gpu/drm/i915/gem/i915_gem_execbuffer.c | 37 +++++++-
drivers/gpu/drm/i915/i915_driver.c | 1 +
drivers/gpu/drm/i915/i915_drm_client.c | 93 +++++++++++++++++++
drivers/gpu/drm/i915/i915_drm_client.h | 11 +++
4 files changed, 141 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 1160723c9d2d..280ed90d5001 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -6,6 +6,7 @@
#include <linux/dma-resv.h>
#include <linux/highmem.h>
+#include <linux/prandom.h>
#include <linux/sync_file.h>
#include <linux/uaccess.h>
@@ -3015,6 +3016,40 @@ static void retire_requests(struct intel_timeline *tl, struct i915_request *end)
break;
}
+#ifdef CONFIG_CGROUP_DRM
+static unsigned int
+__get_class(struct drm_i915_file_private *fpriv, const struct i915_request *rq)
+{
+ unsigned int class;
+
+ class = rq->context->engine->uabi_class;
+
+ if (WARN_ON_ONCE(class >= ARRAY_SIZE(fpriv->client->throttle)))
+ class = 0;
+
+ return class;
+}
+
+static void copy_priority(struct i915_sched_attr *attr,
+ const struct i915_execbuffer *eb,
+ const struct i915_request *rq)
+{
+ struct drm_i915_file_private *file_priv = eb->file->driver_priv;
+
+ *attr = eb->gem_context->sched;
+ if (file_priv->client->throttle[__get_class(file_priv, rq)])
+ attr->priority -=
+ 1 + prandom_u32_max(-I915_CONTEXT_MIN_USER_PRIORITY / 2);
+}
+#else
+static void copy_priority(struct i915_sched_attr *attr,
+ const struct i915_execbuffer *eb,
+ const struct i915_request *rq)
+{
+ *attr = eb->gem_context->sched;
+}
+#endif
+
static int eb_request_add(struct i915_execbuffer *eb, struct i915_request *rq,
int err, bool last_parallel)
{
@@ -3031,7 +3066,7 @@ static int eb_request_add(struct i915_execbuffer *eb, struct i915_request *rq,
/* Check that the context wasn't destroyed before submission */
if (likely(!intel_context_is_closed(eb->context))) {
- attr = eb->gem_context->sched;
+ copy_priority(&attr, eb, rq);
} else {
/* Serialise with context_close via the add_to_timeline */
i915_request_set_error_once(rq, -ENOENT);
diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c
index 96a7da5258c4..d6c0501af3f4 100644
--- a/drivers/gpu/drm/i915/i915_driver.c
+++ b/drivers/gpu/drm/i915/i915_driver.c
@@ -1897,6 +1897,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = {
#ifdef CONFIG_CGROUP_DRM
static const struct drm_cgroup_ops i915_drm_cgroup_ops = {
.active_time_us = i915_drm_cgroup_get_active_time_us,
+ .signal_budget = i915_drm_cgroup_signal_budget,
};
#endif
diff --git a/drivers/gpu/drm/i915/i915_drm_client.c b/drivers/gpu/drm/i915/i915_drm_client.c
index c9754cb0277f..81144c8e8d05 100644
--- a/drivers/gpu/drm/i915/i915_drm_client.c
+++ b/drivers/gpu/drm/i915/i915_drm_client.c
@@ -4,6 +4,7 @@
*/
#include <linux/kernel.h>
+#include <linux/ktime.h>
#include <linux/slab.h>
#include <linux/types.h>
@@ -159,6 +160,98 @@ u64 i915_drm_cgroup_get_active_time_us(struct drm_file *file)
return busy;
}
+
+int i915_drm_cgroup_signal_budget(struct drm_file *file, u64 usage, u64 budget)
+{
+ struct drm_i915_file_private *fpriv = file->driver_priv;
+ u64 class_usage[I915_LAST_UABI_ENGINE_CLASS + 1];
+ u64 class_last[I915_LAST_UABI_ENGINE_CLASS + 1];
+ struct drm_i915_private *i915 = fpriv->dev_priv;
+ struct i915_drm_client *client = fpriv->client;
+ struct intel_engine_cs *engine;
+ bool over = usage > budget;
+ unsigned int i;
+ ktime_t unused;
+ int ret = 0;
+ u64 t;
+
+ if (!supports_stats(i915))
+ return -EINVAL;
+
+ if (usage == 0 && budget == 0)
+ return 0;
+
+printk("i915_drm_cgroup_signal_budget client-id=%u over=%u (%llu/%llu) <%u>\n",
+ client->id, over, usage, budget, client->over_budget);
+
+ if (over) {
+ client->over_budget++;
+ if (!client->over_budget)
+ client->over_budget = 2;
+ } else {
+ client->over_budget = 0;
+ memset(client->class_last, 0, sizeof(client->class_last));
+ memset(client->throttle, 0, sizeof(client->throttle));
+ return 0;
+ }
+
+ memset(class_usage, 0, sizeof(class_usage));
+ for_each_uabi_engine(engine, i915)
+ class_usage[engine->uabi_class] +=
+ ktime_to_ns(intel_engine_get_busy_time(engine, &unused));
+
+ memcpy(class_last, client->class_last, sizeof(class_last));
+ memcpy(client->class_last, class_usage, sizeof(class_last));
+
+ for (i = 0; i < ARRAY_SIZE(uabi_class_names); i++)
+ class_usage[i] -= class_last[i];
+
+ t = client->last;
+ client->last = ktime_get_raw_ns();
+ t = client->last - t;
+
+ if (client->over_budget == 1)
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(uabi_class_names); i++) {
+ u64 client_class_usage[I915_LAST_UABI_ENGINE_CLASS + 1];
+ unsigned int capacity;
+
+ if (!i915->engine_uabi_class_count[i])
+ continue;
+
+ t = DIV_ROUND_UP_ULL(t, 1000);
+ class_usage[i] = DIV_ROUND_CLOSEST_ULL(class_usage[i], 1000);
+ usage = DIV_ROUND_CLOSEST_ULL(class_usage[i] * 100ULL,
+ t *
+ i915->engine_uabi_class_count[i]);
+ if (usage <= 95) {
+ /* class not oversubsribed */
+ if (client->throttle[i]) {
+ client->throttle[i] = false;
+printk(" UN-throttling class%u (phys=%lld%%)\n",
+ i, usage);
+ }
+ continue;
+ }
+
+ client_class_usage[i] =
+ get_class_active_ns(client, i, &capacity);
+
+ if (client_class_usage[i] && !client->throttle[i]) {
+ ret |= 1;
+ client->throttle[i] = true;
+ /*
+ * QQQ maybe apply "strength" of throttling based on
+ * usage/budget?
+ */
+printk(" THROTTLING class%u (phys=%lld%% client=%lluus)\n",
+ i, usage, client_class_usage[i] / 1000);
+ }
+ }
+
+ return ret;
+}
#endif
#ifdef CONFIG_PROC_FS
diff --git a/drivers/gpu/drm/i915/i915_drm_client.h b/drivers/gpu/drm/i915/i915_drm_client.h
index c8439eaa89be..1331cab7ad5e 100644
--- a/drivers/gpu/drm/i915/i915_drm_client.h
+++ b/drivers/gpu/drm/i915/i915_drm_client.h
@@ -15,6 +15,8 @@
#define I915_LAST_UABI_ENGINE_CLASS I915_ENGINE_CLASS_COMPUTE
+struct drm_file;
+
struct drm_i915_private;
struct i915_drm_clients {
@@ -38,6 +40,13 @@ struct i915_drm_client {
* @past_runtime: Accumulation of pphwsp runtimes from closed contexts.
*/
atomic64_t past_runtime[I915_LAST_UABI_ENGINE_CLASS + 1];
+
+#ifdef CONFIG_CGROUP_DRM
+ bool throttle[I915_LAST_UABI_ENGINE_CLASS + 1];
+ unsigned int over_budget;
+ u64 last;
+ u64 class_last[I915_LAST_UABI_ENGINE_CLASS + 1];
+#endif
};
void i915_drm_clients_init(struct i915_drm_clients *clients,
@@ -66,5 +75,7 @@ void i915_drm_client_fdinfo(struct seq_file *m, struct file *f);
void i915_drm_clients_fini(struct i915_drm_clients *clients);
u64 i915_drm_cgroup_get_active_time_us(struct drm_file *file);
+int i915_drm_cgroup_signal_budget(struct drm_file *file,
+ u64 usage, u64 budget);
#endif /* !__I915_DRM_CLIENT_H__ */
--
2.34.1
prev parent reply other threads:[~2022-11-09 16:13 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-09 16:11 [RFC v2 00/13] DRM scheduling cgroup controller Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 01/13] drm: Replace DRM_DEBUG with drm_dbg_core in file and ioctl handling Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 02/13] drm: Track clients by tgid and not tid Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 03/13] drm: Update file owner during use Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 04/13] cgroup: Add the DRM cgroup controller Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 05/13] drm/cgroup: Track clients per owning process Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 06/13] drm/cgroup: Allow safe external access to file_priv Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 07/13] drm/cgroup: Add ability to query drm cgroup GPU time Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 08/13] drm/cgroup: Add over budget signalling callback Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 09/13] drm/cgroup: Only track clients which are providing drm_cgroup_ops Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 10/13] cgroup/drm: Client exit hook Tvrtko Ursulin
2022-11-09 16:11 ` [RFC 11/13] cgroup/drm: Introduce weight based drm cgroup control Tvrtko Ursulin
2022-11-22 21:29 ` Tejun Heo
2022-11-24 14:32 ` Tvrtko Ursulin
2022-11-28 19:50 ` Tejun Heo
2022-11-09 16:11 ` [RFC 12/13] drm/i915: Wire up with drm controller GPU time query Tvrtko Ursulin
2022-11-09 16:11 ` Tvrtko Ursulin [this message]
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=20221109161141.2987173-14-tvrtko.ursulin@linux.intel.com \
--to=tvrtko.ursulin@linux.intel.com \
--cc=Intel-gfx@lists.freedesktop.org \
--cc=Kenny.Ho@amd.com \
--cc=airlied@redhat.com \
--cc=brian.welty@intel.com \
--cc=cgroups@vger.kernel.org \
--cc=christian.koenig@amd.com \
--cc=daniel.vetter@ffwll.ch \
--cc=hannes@cmpxchg.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lizefan.x@bytedance.com \
--cc=marcheu@chromium.org \
--cc=robdclark@chromium.org \
--cc=tj@kernel.org \
--cc=tjmercier@google.com \
--cc=tvrtko.ursulin@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
all inboxes | Powered by JetHome®