* [RFC 01/14] drm/sched: Delete unused update_job_credits
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
@ 2024-12-30 16:52 ` Tvrtko Ursulin
2025-01-08 8:34 ` Danilo Krummrich
2024-12-30 16:52 ` [RFC 02/14] drm/sched: Remove idle entity from tree Tvrtko Ursulin
` (16 subsequent siblings)
17 siblings, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2024-12-30 16:52 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
No driver is using the update_job_credits() schduler vfunc
so lets remove it.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <pstanner@redhat.com>
---
drivers/gpu/drm/scheduler/sched_main.c | 13 -------------
include/drm/gpu_scheduler.h | 13 -------------
2 files changed, 26 deletions(-)
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index 7ce25281c74c..1734c17aeea5 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -64,12 +64,6 @@
* credit limit, the job won't be executed. Instead, the scheduler will wait
* until the credit count has decreased enough to not overflow its credit limit.
* This implies waiting for previously executed jobs.
- *
- * Optionally, drivers may register a callback (update_job_credits) provided by
- * struct drm_sched_backend_ops to update the job's credits dynamically. The
- * scheduler executes this callback every time the scheduler considers a job for
- * execution and subsequently checks whether the job fits the scheduler's credit
- * limit.
*/
#include <linux/wait.h>
@@ -133,13 +127,6 @@ static bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
if (!s_job)
return false;
- if (sched->ops->update_job_credits) {
- s_job->credits = sched->ops->update_job_credits(s_job);
-
- drm_WARN(sched, !s_job->credits,
- "Jobs with zero credits bypass job-flow control.\n");
- }
-
/* If a job exceeds the credit limit, truncate it to the credit limit
* itself to guarantee forward progress.
*/
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index 95e17504e46a..e2e6af8849c6 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -476,19 +476,6 @@ struct drm_sched_backend_ops {
* and it's time to clean it up.
*/
void (*free_job)(struct drm_sched_job *sched_job);
-
- /**
- * @update_job_credits: Called when the scheduler is considering this
- * job for execution.
- *
- * This callback returns the number of credits the job would take if
- * pushed to the hardware. Drivers may use this to dynamically update
- * the job's credit count. For instance, deduct the number of credits
- * for already signalled native fences.
- *
- * This callback is optional.
- */
- u32 (*update_job_credits)(struct drm_sched_job *sched_job);
};
/**
--
2.47.1
^ permalink raw reply related [flat|nested] 61+ messages in thread* Re: [RFC 01/14] drm/sched: Delete unused update_job_credits
2024-12-30 16:52 ` [RFC 01/14] drm/sched: Delete unused update_job_credits Tvrtko Ursulin
@ 2025-01-08 8:34 ` Danilo Krummrich
2025-01-08 12:27 ` Boris Brezillon
0 siblings, 1 reply; 61+ messages in thread
From: Danilo Krummrich @ 2025-01-08 8:34 UTC (permalink / raw)
To: Tvrtko Ursulin
Cc: dri-devel, kernel-dev, Tvrtko Ursulin, Christian König,
Matthew Brost, Philipp Stanner, Boris Brezillon
On Mon, Dec 30, 2024 at 04:52:46PM +0000, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>
> No driver is using the update_job_credits() schduler vfunc
> so lets remove it.
>
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
(+ Boris)
AFAIR the panthor folks asked for this. I assume they never actually ended up
using it? Unless they plan to use it,
Acked-by: Danilo Krummrich <dakr@kernel.org>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: Danilo Krummrich <dakr@redhat.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Philipp Stanner <pstanner@redhat.com>
> ---
> drivers/gpu/drm/scheduler/sched_main.c | 13 -------------
> include/drm/gpu_scheduler.h | 13 -------------
> 2 files changed, 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
> index 7ce25281c74c..1734c17aeea5 100644
> --- a/drivers/gpu/drm/scheduler/sched_main.c
> +++ b/drivers/gpu/drm/scheduler/sched_main.c
> @@ -64,12 +64,6 @@
> * credit limit, the job won't be executed. Instead, the scheduler will wait
> * until the credit count has decreased enough to not overflow its credit limit.
> * This implies waiting for previously executed jobs.
> - *
> - * Optionally, drivers may register a callback (update_job_credits) provided by
> - * struct drm_sched_backend_ops to update the job's credits dynamically. The
> - * scheduler executes this callback every time the scheduler considers a job for
> - * execution and subsequently checks whether the job fits the scheduler's credit
> - * limit.
> */
>
> #include <linux/wait.h>
> @@ -133,13 +127,6 @@ static bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
> if (!s_job)
> return false;
>
> - if (sched->ops->update_job_credits) {
> - s_job->credits = sched->ops->update_job_credits(s_job);
> -
> - drm_WARN(sched, !s_job->credits,
> - "Jobs with zero credits bypass job-flow control.\n");
> - }
> -
> /* If a job exceeds the credit limit, truncate it to the credit limit
> * itself to guarantee forward progress.
> */
> diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
> index 95e17504e46a..e2e6af8849c6 100644
> --- a/include/drm/gpu_scheduler.h
> +++ b/include/drm/gpu_scheduler.h
> @@ -476,19 +476,6 @@ struct drm_sched_backend_ops {
> * and it's time to clean it up.
> */
> void (*free_job)(struct drm_sched_job *sched_job);
> -
> - /**
> - * @update_job_credits: Called when the scheduler is considering this
> - * job for execution.
> - *
> - * This callback returns the number of credits the job would take if
> - * pushed to the hardware. Drivers may use this to dynamically update
> - * the job's credit count. For instance, deduct the number of credits
> - * for already signalled native fences.
> - *
> - * This callback is optional.
> - */
> - u32 (*update_job_credits)(struct drm_sched_job *sched_job);
> };
>
> /**
> --
> 2.47.1
>
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 01/14] drm/sched: Delete unused update_job_credits
2025-01-08 8:34 ` Danilo Krummrich
@ 2025-01-08 12:27 ` Boris Brezillon
2025-01-08 14:08 ` Matt Coster
0 siblings, 1 reply; 61+ messages in thread
From: Boris Brezillon @ 2025-01-08 12:27 UTC (permalink / raw)
To: Danilo Krummrich
Cc: Tvrtko Ursulin, dri-devel, kernel-dev, Tvrtko Ursulin,
Christian König, Matthew Brost, Philipp Stanner, Frank Binns
On Wed, 8 Jan 2025 09:34:11 +0100
Danilo Krummrich <dakr@redhat.com> wrote:
> On Mon, Dec 30, 2024 at 04:52:46PM +0000, Tvrtko Ursulin wrote:
> > From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> >
> > No driver is using the update_job_credits() schduler vfunc
> > so lets remove it.
> >
> > Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>
> (+ Boris)
>
> AFAIR the panthor folks asked for this. I assume they never actually ended up
> using it? Unless they plan to use it,
+Frank
That was for the PowerVR driver, and it doesn't seem it's been hooked
up there. I don't think we'll ever need it in panthor, so
Acked-by: Boris Brezillon <boris.brezillon@collabora.com>
>
> Acked-by: Danilo Krummrich <dakr@kernel.org>
>
> > Cc: Christian König <christian.koenig@amd.com>
> > Cc: Danilo Krummrich <dakr@redhat.com>
> > Cc: Matthew Brost <matthew.brost@intel.com>
> > Cc: Philipp Stanner <pstanner@redhat.com>
> > ---
> > drivers/gpu/drm/scheduler/sched_main.c | 13 -------------
> > include/drm/gpu_scheduler.h | 13 -------------
> > 2 files changed, 26 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
> > index 7ce25281c74c..1734c17aeea5 100644
> > --- a/drivers/gpu/drm/scheduler/sched_main.c
> > +++ b/drivers/gpu/drm/scheduler/sched_main.c
> > @@ -64,12 +64,6 @@
> > * credit limit, the job won't be executed. Instead, the scheduler will wait
> > * until the credit count has decreased enough to not overflow its credit limit.
> > * This implies waiting for previously executed jobs.
> > - *
> > - * Optionally, drivers may register a callback (update_job_credits) provided by
> > - * struct drm_sched_backend_ops to update the job's credits dynamically. The
> > - * scheduler executes this callback every time the scheduler considers a job for
> > - * execution and subsequently checks whether the job fits the scheduler's credit
> > - * limit.
> > */
> >
> > #include <linux/wait.h>
> > @@ -133,13 +127,6 @@ static bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
> > if (!s_job)
> > return false;
> >
> > - if (sched->ops->update_job_credits) {
> > - s_job->credits = sched->ops->update_job_credits(s_job);
> > -
> > - drm_WARN(sched, !s_job->credits,
> > - "Jobs with zero credits bypass job-flow control.\n");
> > - }
> > -
> > /* If a job exceeds the credit limit, truncate it to the credit limit
> > * itself to guarantee forward progress.
> > */
> > diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
> > index 95e17504e46a..e2e6af8849c6 100644
> > --- a/include/drm/gpu_scheduler.h
> > +++ b/include/drm/gpu_scheduler.h
> > @@ -476,19 +476,6 @@ struct drm_sched_backend_ops {
> > * and it's time to clean it up.
> > */
> > void (*free_job)(struct drm_sched_job *sched_job);
> > -
> > - /**
> > - * @update_job_credits: Called when the scheduler is considering this
> > - * job for execution.
> > - *
> > - * This callback returns the number of credits the job would take if
> > - * pushed to the hardware. Drivers may use this to dynamically update
> > - * the job's credit count. For instance, deduct the number of credits
> > - * for already signalled native fences.
> > - *
> > - * This callback is optional.
> > - */
> > - u32 (*update_job_credits)(struct drm_sched_job *sched_job);
> > };
> >
> > /**
> > --
> > 2.47.1
> >
>
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 01/14] drm/sched: Delete unused update_job_credits
2025-01-08 12:27 ` Boris Brezillon
@ 2025-01-08 14:08 ` Matt Coster
0 siblings, 0 replies; 61+ messages in thread
From: Matt Coster @ 2025-01-08 14:08 UTC (permalink / raw)
To: Boris Brezillon, Danilo Krummrich
Cc: Tvrtko Ursulin, dri-devel@lists.freedesktop.org,
kernel-dev@igalia.com, Tvrtko Ursulin, Christian König,
Matthew Brost, Philipp Stanner, Frank Binns
[-- Attachment #1.1: Type: text/plain, Size: 3746 bytes --]
On 08/01/2025 12:27, Boris Brezillon wrote:
> On Wed, 8 Jan 2025 09:34:11 +0100
> Danilo Krummrich <dakr@redhat.com> wrote:
>
>> On Mon, Dec 30, 2024 at 04:52:46PM +0000, Tvrtko Ursulin wrote:
>>> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>>>
>>> No driver is using the update_job_credits() schduler vfunc
>>> so lets remove it.
>>>
>>> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>>
>> (+ Boris)
>>
>> AFAIR the panthor folks asked for this. I assume they never actually ended up
>> using it? Unless they plan to use it,
>
> +Frank
>
> That was for the PowerVR driver, and it doesn't seem it's been hooked
> up there. I don't think we'll ever need it in panthor, so
Looks good to us, thanks for checking!
Acked-by: Matt Coster <matt.coster@imgtec.com>
--
Matt Coster
E: matt.coster@imgtec.com
> Acked-by: Boris Brezillon <boris.brezillon@collabora.com>
>
>>
>> Acked-by: Danilo Krummrich <dakr@kernel.org>
>>
>>> Cc: Christian König <christian.koenig@amd.com>
>>> Cc: Danilo Krummrich <dakr@redhat.com>
>>> Cc: Matthew Brost <matthew.brost@intel.com>
>>> Cc: Philipp Stanner <pstanner@redhat.com>
>>> ---
>>> drivers/gpu/drm/scheduler/sched_main.c | 13 -------------
>>> include/drm/gpu_scheduler.h | 13 -------------
>>> 2 files changed, 26 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
>>> index 7ce25281c74c..1734c17aeea5 100644
>>> --- a/drivers/gpu/drm/scheduler/sched_main.c
>>> +++ b/drivers/gpu/drm/scheduler/sched_main.c
>>> @@ -64,12 +64,6 @@
>>> * credit limit, the job won't be executed. Instead, the scheduler will wait
>>> * until the credit count has decreased enough to not overflow its credit limit.
>>> * This implies waiting for previously executed jobs.
>>> - *
>>> - * Optionally, drivers may register a callback (update_job_credits) provided by
>>> - * struct drm_sched_backend_ops to update the job's credits dynamically. The
>>> - * scheduler executes this callback every time the scheduler considers a job for
>>> - * execution and subsequently checks whether the job fits the scheduler's credit
>>> - * limit.
>>> */
>>>
>>> #include <linux/wait.h>
>>> @@ -133,13 +127,6 @@ static bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
>>> if (!s_job)
>>> return false;
>>>
>>> - if (sched->ops->update_job_credits) {
>>> - s_job->credits = sched->ops->update_job_credits(s_job);
>>> -
>>> - drm_WARN(sched, !s_job->credits,
>>> - "Jobs with zero credits bypass job-flow control.\n");
>>> - }
>>> -
>>> /* If a job exceeds the credit limit, truncate it to the credit limit
>>> * itself to guarantee forward progress.
>>> */
>>> diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
>>> index 95e17504e46a..e2e6af8849c6 100644
>>> --- a/include/drm/gpu_scheduler.h
>>> +++ b/include/drm/gpu_scheduler.h
>>> @@ -476,19 +476,6 @@ struct drm_sched_backend_ops {
>>> * and it's time to clean it up.
>>> */
>>> void (*free_job)(struct drm_sched_job *sched_job);
>>> -
>>> - /**
>>> - * @update_job_credits: Called when the scheduler is considering this
>>> - * job for execution.
>>> - *
>>> - * This callback returns the number of credits the job would take if
>>> - * pushed to the hardware. Drivers may use this to dynamically update
>>> - * the job's credit count. For instance, deduct the number of credits
>>> - * for already signalled native fences.
>>> - *
>>> - * This callback is optional.
>>> - */
>>> - u32 (*update_job_credits)(struct drm_sched_job *sched_job);
>>> };
>>>
>>> /**
>>> --
>>> 2.47.1
>>>
>>
>
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 236 bytes --]
^ permalink raw reply [flat|nested] 61+ messages in thread
* [RFC 02/14] drm/sched: Remove idle entity from tree
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
2024-12-30 16:52 ` [RFC 01/14] drm/sched: Delete unused update_job_credits Tvrtko Ursulin
@ 2024-12-30 16:52 ` Tvrtko Ursulin
2024-12-30 16:52 ` [RFC 03/14] drm/sched: Implement RR via FIFO Tvrtko Ursulin
` (15 subsequent siblings)
17 siblings, 0 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2024-12-30 16:52 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
There is no need to keep entities with no jobs in the tree so lets remove
it once the last job is consumed. This keeps the tree smaller which is
nicer and more efficient.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <pstanner@redhat.com>
---
drivers/gpu/drm/scheduler/sched_entity.c | 15 ++++++++-------
drivers/gpu/drm/scheduler/sched_main.c | 4 ++--
include/drm/gpu_scheduler.h | 2 ++
3 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index 69bcf0e99d57..8e910586979e 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -512,19 +512,20 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
*/
if (drm_sched_policy == DRM_SCHED_POLICY_FIFO) {
struct drm_sched_job *next;
+ struct drm_sched_rq *rq;
+ spin_lock(&entity->lock);
+ rq = entity->rq;
+ spin_lock(&rq->lock);
next = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
if (next) {
- struct drm_sched_rq *rq;
-
- spin_lock(&entity->lock);
- rq = entity->rq;
- spin_lock(&rq->lock);
drm_sched_rq_update_fifo_locked(entity, rq,
next->submit_ts);
- spin_unlock(&rq->lock);
- spin_unlock(&entity->lock);
+ } else {
+ drm_sched_rq_remove_fifo_locked(entity, rq);
}
+ spin_unlock(&rq->lock);
+ spin_unlock(&entity->lock);
}
/* Jobs and entities might have different lifecycles. Since we're
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index 1734c17aeea5..9beb4c611988 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -146,8 +146,8 @@ static __always_inline bool drm_sched_entity_compare_before(struct rb_node *a,
return ktime_before(ent_a->oldest_job_waiting, ent_b->oldest_job_waiting);
}
-static void drm_sched_rq_remove_fifo_locked(struct drm_sched_entity *entity,
- struct drm_sched_rq *rq)
+void drm_sched_rq_remove_fifo_locked(struct drm_sched_entity *entity,
+ struct drm_sched_rq *rq)
{
if (!RB_EMPTY_NODE(&entity->rb_tree_node)) {
rb_erase_cached(&entity->rb_tree_node, &rq->rb_tree_root);
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index e2e6af8849c6..978ca621cc13 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -591,6 +591,8 @@ void drm_sched_rq_add_entity(struct drm_sched_rq *rq,
void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
struct drm_sched_entity *entity);
+void drm_sched_rq_remove_fifo_locked(struct drm_sched_entity *entity,
+ struct drm_sched_rq *rq);
void drm_sched_rq_update_fifo_locked(struct drm_sched_entity *entity,
struct drm_sched_rq *rq, ktime_t ts);
--
2.47.1
^ permalink raw reply related [flat|nested] 61+ messages in thread* [RFC 03/14] drm/sched: Implement RR via FIFO
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
2024-12-30 16:52 ` [RFC 01/14] drm/sched: Delete unused update_job_credits Tvrtko Ursulin
2024-12-30 16:52 ` [RFC 02/14] drm/sched: Remove idle entity from tree Tvrtko Ursulin
@ 2024-12-30 16:52 ` Tvrtko Ursulin
2025-01-08 9:42 ` Danilo Krummrich
2024-12-30 16:52 ` [RFC 04/14] drm/sched: Consolidate entity run queue management Tvrtko Ursulin
` (14 subsequent siblings)
17 siblings, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2024-12-30 16:52 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Round-robin being the non-default policy and unclear how much it is used,
we can notice that it can be implemented using the FIFO data structures if
we only invent a fake submit timestamp which is monotonically increasing
inside drm_sched_rq instances.
So instead of remembering which was the last entity the scheduler worker
picked, we can bump the picked one to the bottom of the tree, achieving
the same round-robin behaviour.
Advantage is that we can consolidate to a single code path and remove a
bunch of code. Downside is round-robin mode now needs to lock on the job
pop path but that should not be visible.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <pstanner@redhat.com>
---
drivers/gpu/drm/scheduler/sched_entity.c | 53 ++++++++-----
drivers/gpu/drm/scheduler/sched_main.c | 99 +++---------------------
include/drm/gpu_scheduler.h | 5 +-
3 files changed, 48 insertions(+), 109 deletions(-)
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index 8e910586979e..cb5f596b48b7 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -473,9 +473,20 @@ drm_sched_job_dependency(struct drm_sched_job *job,
return NULL;
}
+static ktime_t
+drm_sched_rq_get_rr_deadline(struct drm_sched_rq *rq)
+{
+ lockdep_assert_held(&rq->lock);
+
+ rq->rr_deadline = ktime_add_ns(rq->rr_deadline, 1);
+
+ return rq->rr_deadline;
+}
+
struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
{
- struct drm_sched_job *sched_job;
+ struct drm_sched_job *sched_job, *next_job;
+ struct drm_sched_rq *rq;
sched_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
if (!sched_job)
@@ -510,24 +521,28 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
* Update the entity's location in the min heap according to
* the timestamp of the next job, if any.
*/
- if (drm_sched_policy == DRM_SCHED_POLICY_FIFO) {
- struct drm_sched_job *next;
- struct drm_sched_rq *rq;
+ next_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
- spin_lock(&entity->lock);
- rq = entity->rq;
- spin_lock(&rq->lock);
- next = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
- if (next) {
- drm_sched_rq_update_fifo_locked(entity, rq,
- next->submit_ts);
- } else {
- drm_sched_rq_remove_fifo_locked(entity, rq);
- }
- spin_unlock(&rq->lock);
- spin_unlock(&entity->lock);
+ spin_lock(&entity->lock);
+ rq = entity->rq;
+ spin_lock(&rq->lock);
+
+ if (next_job) {
+ ktime_t ts;
+
+ if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
+ ts = next_job->submit_ts;
+ else
+ ts = drm_sched_rq_get_rr_deadline(rq);
+
+ drm_sched_rq_update_fifo_locked(entity, rq, ts);
+ } else {
+ drm_sched_rq_remove_fifo_locked(entity, rq);
}
+ spin_unlock(&rq->lock);
+ spin_unlock(&entity->lock);
+
/* Jobs and entities might have different lifecycles. Since we're
* removing the job from the entities queue, set the jobs entity pointer
* to NULL to prevent any future access of the entity through this job.
@@ -624,9 +639,9 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
spin_lock(&rq->lock);
drm_sched_rq_add_entity(rq, entity);
-
- if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
- drm_sched_rq_update_fifo_locked(entity, rq, submit_ts);
+ if (drm_sched_policy == DRM_SCHED_POLICY_RR)
+ submit_ts = drm_sched_rq_get_rr_deadline(rq);
+ drm_sched_rq_update_fifo_locked(entity, rq, submit_ts);
spin_unlock(&rq->lock);
spin_unlock(&entity->lock);
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index 9beb4c611988..eb22b1b7de36 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -189,7 +189,6 @@ static void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
spin_lock_init(&rq->lock);
INIT_LIST_HEAD(&rq->entities);
rq->rb_tree_root = RB_ROOT_CACHED;
- rq->current_entity = NULL;
rq->sched = sched;
}
@@ -235,82 +234,13 @@ void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
atomic_dec(rq->sched->score);
list_del_init(&entity->list);
- if (rq->current_entity == entity)
- rq->current_entity = NULL;
-
- if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
- drm_sched_rq_remove_fifo_locked(entity, rq);
+ drm_sched_rq_remove_fifo_locked(entity, rq);
spin_unlock(&rq->lock);
}
/**
- * drm_sched_rq_select_entity_rr - Select an entity which could provide a job to run
- *
- * @sched: the gpu scheduler
- * @rq: scheduler run queue to check.
- *
- * Try to find the next ready entity.
- *
- * Return an entity if one is found; return an error-pointer (!NULL) if an
- * entity was ready, but the scheduler had insufficient credits to accommodate
- * its job; return NULL, if no ready entity was found.
- */
-static struct drm_sched_entity *
-drm_sched_rq_select_entity_rr(struct drm_gpu_scheduler *sched,
- struct drm_sched_rq *rq)
-{
- struct drm_sched_entity *entity;
-
- spin_lock(&rq->lock);
-
- entity = rq->current_entity;
- if (entity) {
- list_for_each_entry_continue(entity, &rq->entities, list) {
- if (drm_sched_entity_is_ready(entity)) {
- /* If we can't queue yet, preserve the current
- * entity in terms of fairness.
- */
- if (!drm_sched_can_queue(sched, entity)) {
- spin_unlock(&rq->lock);
- return ERR_PTR(-ENOSPC);
- }
-
- rq->current_entity = entity;
- reinit_completion(&entity->entity_idle);
- spin_unlock(&rq->lock);
- return entity;
- }
- }
- }
-
- list_for_each_entry(entity, &rq->entities, list) {
- if (drm_sched_entity_is_ready(entity)) {
- /* If we can't queue yet, preserve the current entity in
- * terms of fairness.
- */
- if (!drm_sched_can_queue(sched, entity)) {
- spin_unlock(&rq->lock);
- return ERR_PTR(-ENOSPC);
- }
-
- rq->current_entity = entity;
- reinit_completion(&entity->entity_idle);
- spin_unlock(&rq->lock);
- return entity;
- }
-
- if (entity == rq->current_entity)
- break;
- }
-
- spin_unlock(&rq->lock);
-
- return NULL;
-}
-
-/**
- * drm_sched_rq_select_entity_fifo - Select an entity which provides a job to run
+ * drm_sched_rq_select_entity - Select an entity which provides a job to run
*
* @sched: the gpu scheduler
* @rq: scheduler run queue to check.
@@ -322,32 +252,29 @@ drm_sched_rq_select_entity_rr(struct drm_gpu_scheduler *sched,
* its job; return NULL, if no ready entity was found.
*/
static struct drm_sched_entity *
-drm_sched_rq_select_entity_fifo(struct drm_gpu_scheduler *sched,
- struct drm_sched_rq *rq)
+drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched,
+ struct drm_sched_rq *rq)
{
+ struct drm_sched_entity *entity = NULL;
struct rb_node *rb;
spin_lock(&rq->lock);
for (rb = rb_first_cached(&rq->rb_tree_root); rb; rb = rb_next(rb)) {
- struct drm_sched_entity *entity;
-
entity = rb_entry(rb, struct drm_sched_entity, rb_tree_node);
if (drm_sched_entity_is_ready(entity)) {
- /* If we can't queue yet, preserve the current entity in
- * terms of fairness.
- */
if (!drm_sched_can_queue(sched, entity)) {
- spin_unlock(&rq->lock);
- return ERR_PTR(-ENOSPC);
+ entity = ERR_PTR(-ENOSPC);
+ break;
}
reinit_completion(&entity->entity_idle);
break;
}
+ entity = NULL;
}
spin_unlock(&rq->lock);
- return rb ? rb_entry(rb, struct drm_sched_entity, rb_tree_node) : NULL;
+ return entity;
}
/**
@@ -1045,20 +972,18 @@ void drm_sched_wakeup(struct drm_gpu_scheduler *sched)
static struct drm_sched_entity *
drm_sched_select_entity(struct drm_gpu_scheduler *sched)
{
- struct drm_sched_entity *entity;
+ struct drm_sched_entity *entity = NULL;
int i;
/* Start with the highest priority.
*/
for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) {
- entity = drm_sched_policy == DRM_SCHED_POLICY_FIFO ?
- drm_sched_rq_select_entity_fifo(sched, sched->sched_rq[i]) :
- drm_sched_rq_select_entity_rr(sched, sched->sched_rq[i]);
+ entity = drm_sched_rq_select_entity(sched, sched->sched_rq[i]);
if (entity)
break;
}
- return IS_ERR(entity) ? NULL : entity;
+ return IS_ERR(entity) ? NULL : entity;;
}
/**
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index 978ca621cc13..db65600732b9 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -245,8 +245,7 @@ struct drm_sched_entity {
* struct drm_sched_rq - queue of entities to be scheduled.
*
* @sched: the scheduler to which this rq belongs to.
- * @lock: protects @entities, @rb_tree_root and @current_entity.
- * @current_entity: the entity which is to be scheduled.
+ * @lock: protects @entities, @rb_tree_root and @rr_deadline.
* @entities: list of the entities to be scheduled.
* @rb_tree_root: root of time based priority queue of entities for FIFO scheduling
*
@@ -259,7 +258,7 @@ struct drm_sched_rq {
spinlock_t lock;
/* Following members are protected by the @lock: */
- struct drm_sched_entity *current_entity;
+ ktime_t rr_deadline;
struct list_head entities;
struct rb_root_cached rb_tree_root;
};
--
2.47.1
^ permalink raw reply related [flat|nested] 61+ messages in thread* Re: [RFC 03/14] drm/sched: Implement RR via FIFO
2024-12-30 16:52 ` [RFC 03/14] drm/sched: Implement RR via FIFO Tvrtko Ursulin
@ 2025-01-08 9:42 ` Danilo Krummrich
2025-01-08 15:04 ` Tvrtko Ursulin
0 siblings, 1 reply; 61+ messages in thread
From: Danilo Krummrich @ 2025-01-08 9:42 UTC (permalink / raw)
To: Tvrtko Ursulin
Cc: dri-devel, kernel-dev, Tvrtko Ursulin, Christian König,
Matthew Brost, Philipp Stanner
On Mon, Dec 30, 2024 at 04:52:48PM +0000, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>
> Round-robin being the non-default policy and unclear how much it is used,
I don't know either, but would be nice if we could instead remove it.
> we can notice that it can be implemented using the FIFO data structures if
> we only invent a fake submit timestamp which is monotonically increasing
> inside drm_sched_rq instances.
>
> So instead of remembering which was the last entity the scheduler worker
> picked, we can bump the picked one to the bottom of the tree, achieving
> the same round-robin behaviour.
>
> Advantage is that we can consolidate to a single code path and remove a
> bunch of code. Downside is round-robin mode now needs to lock on the job
> pop path but that should not be visible.
I guess you did you test both scheduler strategies with this change?
>
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: Danilo Krummrich <dakr@redhat.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Philipp Stanner <pstanner@redhat.com>
> ---
> drivers/gpu/drm/scheduler/sched_entity.c | 53 ++++++++-----
> drivers/gpu/drm/scheduler/sched_main.c | 99 +++---------------------
> include/drm/gpu_scheduler.h | 5 +-
> 3 files changed, 48 insertions(+), 109 deletions(-)
>
> diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
> index 8e910586979e..cb5f596b48b7 100644
> --- a/drivers/gpu/drm/scheduler/sched_entity.c
> +++ b/drivers/gpu/drm/scheduler/sched_entity.c
> @@ -473,9 +473,20 @@ drm_sched_job_dependency(struct drm_sched_job *job,
> return NULL;
> }
>
> +static ktime_t
> +drm_sched_rq_get_rr_deadline(struct drm_sched_rq *rq)
> +{
> + lockdep_assert_held(&rq->lock);
> +
> + rq->rr_deadline = ktime_add_ns(rq->rr_deadline, 1);
> +
> + return rq->rr_deadline;
> +}
> +
> struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
> {
> - struct drm_sched_job *sched_job;
> + struct drm_sched_job *sched_job, *next_job;
> + struct drm_sched_rq *rq;
>
> sched_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
> if (!sched_job)
> @@ -510,24 +521,28 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
> * Update the entity's location in the min heap according to
> * the timestamp of the next job, if any.
> */
> - if (drm_sched_policy == DRM_SCHED_POLICY_FIFO) {
> - struct drm_sched_job *next;
> - struct drm_sched_rq *rq;
> + next_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
>
> - spin_lock(&entity->lock);
> - rq = entity->rq;
> - spin_lock(&rq->lock);
> - next = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
> - if (next) {
> - drm_sched_rq_update_fifo_locked(entity, rq,
> - next->submit_ts);
> - } else {
> - drm_sched_rq_remove_fifo_locked(entity, rq);
> - }
> - spin_unlock(&rq->lock);
> - spin_unlock(&entity->lock);
> + spin_lock(&entity->lock);
> + rq = entity->rq;
> + spin_lock(&rq->lock);
> +
> + if (next_job) {
> + ktime_t ts;
> +
> + if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
> + ts = next_job->submit_ts;
> + else
> + ts = drm_sched_rq_get_rr_deadline(rq);
> +
> + drm_sched_rq_update_fifo_locked(entity, rq, ts);
> + } else {
> + drm_sched_rq_remove_fifo_locked(entity, rq);
> }
>
> + spin_unlock(&rq->lock);
> + spin_unlock(&entity->lock);
> +
> /* Jobs and entities might have different lifecycles. Since we're
> * removing the job from the entities queue, set the jobs entity pointer
> * to NULL to prevent any future access of the entity through this job.
> @@ -624,9 +639,9 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
>
> spin_lock(&rq->lock);
> drm_sched_rq_add_entity(rq, entity);
> -
> - if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
> - drm_sched_rq_update_fifo_locked(entity, rq, submit_ts);
> + if (drm_sched_policy == DRM_SCHED_POLICY_RR)
> + submit_ts = drm_sched_rq_get_rr_deadline(rq);
> + drm_sched_rq_update_fifo_locked(entity, rq, submit_ts);
>
> spin_unlock(&rq->lock);
> spin_unlock(&entity->lock);
> diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
> index 9beb4c611988..eb22b1b7de36 100644
> --- a/drivers/gpu/drm/scheduler/sched_main.c
> +++ b/drivers/gpu/drm/scheduler/sched_main.c
> @@ -189,7 +189,6 @@ static void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
> spin_lock_init(&rq->lock);
> INIT_LIST_HEAD(&rq->entities);
> rq->rb_tree_root = RB_ROOT_CACHED;
> - rq->current_entity = NULL;
> rq->sched = sched;
> }
>
> @@ -235,82 +234,13 @@ void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
> atomic_dec(rq->sched->score);
> list_del_init(&entity->list);
>
> - if (rq->current_entity == entity)
> - rq->current_entity = NULL;
> -
> - if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
> - drm_sched_rq_remove_fifo_locked(entity, rq);
> + drm_sched_rq_remove_fifo_locked(entity, rq);
>
> spin_unlock(&rq->lock);
> }
>
> /**
> - * drm_sched_rq_select_entity_rr - Select an entity which could provide a job to run
> - *
> - * @sched: the gpu scheduler
> - * @rq: scheduler run queue to check.
> - *
> - * Try to find the next ready entity.
> - *
> - * Return an entity if one is found; return an error-pointer (!NULL) if an
> - * entity was ready, but the scheduler had insufficient credits to accommodate
> - * its job; return NULL, if no ready entity was found.
> - */
> -static struct drm_sched_entity *
> -drm_sched_rq_select_entity_rr(struct drm_gpu_scheduler *sched,
> - struct drm_sched_rq *rq)
> -{
> - struct drm_sched_entity *entity;
> -
> - spin_lock(&rq->lock);
> -
> - entity = rq->current_entity;
> - if (entity) {
> - list_for_each_entry_continue(entity, &rq->entities, list) {
> - if (drm_sched_entity_is_ready(entity)) {
> - /* If we can't queue yet, preserve the current
> - * entity in terms of fairness.
> - */
> - if (!drm_sched_can_queue(sched, entity)) {
> - spin_unlock(&rq->lock);
> - return ERR_PTR(-ENOSPC);
> - }
> -
> - rq->current_entity = entity;
> - reinit_completion(&entity->entity_idle);
> - spin_unlock(&rq->lock);
> - return entity;
> - }
> - }
> - }
> -
> - list_for_each_entry(entity, &rq->entities, list) {
> - if (drm_sched_entity_is_ready(entity)) {
> - /* If we can't queue yet, preserve the current entity in
> - * terms of fairness.
> - */
> - if (!drm_sched_can_queue(sched, entity)) {
> - spin_unlock(&rq->lock);
> - return ERR_PTR(-ENOSPC);
> - }
> -
> - rq->current_entity = entity;
> - reinit_completion(&entity->entity_idle);
> - spin_unlock(&rq->lock);
> - return entity;
> - }
> -
> - if (entity == rq->current_entity)
> - break;
> - }
> -
> - spin_unlock(&rq->lock);
> -
> - return NULL;
> -}
> -
> -/**
> - * drm_sched_rq_select_entity_fifo - Select an entity which provides a job to run
> + * drm_sched_rq_select_entity - Select an entity which provides a job to run
> *
> * @sched: the gpu scheduler
> * @rq: scheduler run queue to check.
> @@ -322,32 +252,29 @@ drm_sched_rq_select_entity_rr(struct drm_gpu_scheduler *sched,
> * its job; return NULL, if no ready entity was found.
> */
> static struct drm_sched_entity *
> -drm_sched_rq_select_entity_fifo(struct drm_gpu_scheduler *sched,
> - struct drm_sched_rq *rq)
> +drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched,
> + struct drm_sched_rq *rq)
> {
> + struct drm_sched_entity *entity = NULL;
> struct rb_node *rb;
>
> spin_lock(&rq->lock);
> for (rb = rb_first_cached(&rq->rb_tree_root); rb; rb = rb_next(rb)) {
> - struct drm_sched_entity *entity;
> -
> entity = rb_entry(rb, struct drm_sched_entity, rb_tree_node);
> if (drm_sched_entity_is_ready(entity)) {
> - /* If we can't queue yet, preserve the current entity in
> - * terms of fairness.
> - */
> if (!drm_sched_can_queue(sched, entity)) {
> - spin_unlock(&rq->lock);
> - return ERR_PTR(-ENOSPC);
> + entity = ERR_PTR(-ENOSPC);
> + break;
> }
>
> reinit_completion(&entity->entity_idle);
> break;
> }
> + entity = NULL;
> }
> spin_unlock(&rq->lock);
>
> - return rb ? rb_entry(rb, struct drm_sched_entity, rb_tree_node) : NULL;
> + return entity;
> }
The whole diff of drm_sched_rq_select_entity_fifo() (except for the name) has
nothing to do with the patch, does it?
If you want refactor things, please do it in a separate patch.
>
> /**
> @@ -1045,20 +972,18 @@ void drm_sched_wakeup(struct drm_gpu_scheduler *sched)
> static struct drm_sched_entity *
> drm_sched_select_entity(struct drm_gpu_scheduler *sched)
> {
> - struct drm_sched_entity *entity;
> + struct drm_sched_entity *entity = NULL;
> int i;
>
> /* Start with the highest priority.
> */
> for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) {
> - entity = drm_sched_policy == DRM_SCHED_POLICY_FIFO ?
> - drm_sched_rq_select_entity_fifo(sched, sched->sched_rq[i]) :
> - drm_sched_rq_select_entity_rr(sched, sched->sched_rq[i]);
> + entity = drm_sched_rq_select_entity(sched, sched->sched_rq[i]);
> if (entity)
> break;
> }
>
> - return IS_ERR(entity) ? NULL : entity;
> + return IS_ERR(entity) ? NULL : entity;;
> }
>
> /**
> diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
> index 978ca621cc13..db65600732b9 100644
> --- a/include/drm/gpu_scheduler.h
> +++ b/include/drm/gpu_scheduler.h
> @@ -245,8 +245,7 @@ struct drm_sched_entity {
> * struct drm_sched_rq - queue of entities to be scheduled.
> *
> * @sched: the scheduler to which this rq belongs to.
> - * @lock: protects @entities, @rb_tree_root and @current_entity.
> - * @current_entity: the entity which is to be scheduled.
> + * @lock: protects @entities, @rb_tree_root and @rr_deadline.
> * @entities: list of the entities to be scheduled.
> * @rb_tree_root: root of time based priority queue of entities for FIFO scheduling
> *
> @@ -259,7 +258,7 @@ struct drm_sched_rq {
>
> spinlock_t lock;
> /* Following members are protected by the @lock: */
> - struct drm_sched_entity *current_entity;
> + ktime_t rr_deadline;
> struct list_head entities;
> struct rb_root_cached rb_tree_root;
> };
> --
> 2.47.1
>
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 03/14] drm/sched: Implement RR via FIFO
2025-01-08 9:42 ` Danilo Krummrich
@ 2025-01-08 15:04 ` Tvrtko Ursulin
0 siblings, 0 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-08 15:04 UTC (permalink / raw)
To: Danilo Krummrich, Tvrtko Ursulin
Cc: dri-devel, kernel-dev, Christian König, Matthew Brost,
Philipp Stanner
On 08/01/2025 09:42, Danilo Krummrich wrote:
> On Mon, Dec 30, 2024 at 04:52:48PM +0000, Tvrtko Ursulin wrote:
>> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>>
>> Round-robin being the non-default policy and unclear how much it is used,
>
> I don't know either, but would be nice if we could instead remove it.
>
>> we can notice that it can be implemented using the FIFO data structures if
>> we only invent a fake submit timestamp which is monotonically increasing
>> inside drm_sched_rq instances.
>>
>> So instead of remembering which was the last entity the scheduler worker
>> picked, we can bump the picked one to the bottom of the tree, achieving
>> the same round-robin behaviour.
>>
>> Advantage is that we can consolidate to a single code path and remove a
>> bunch of code. Downside is round-robin mode now needs to lock on the job
>> pop path but that should not be visible.
>
> I guess you did you test both scheduler strategies with this change?
Insofar it doesn't crash and burn, yes.
>> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>> Cc: Christian König <christian.koenig@amd.com>
>> Cc: Danilo Krummrich <dakr@redhat.com>
>> Cc: Matthew Brost <matthew.brost@intel.com>
>> Cc: Philipp Stanner <pstanner@redhat.com>
>> ---
>> drivers/gpu/drm/scheduler/sched_entity.c | 53 ++++++++-----
>> drivers/gpu/drm/scheduler/sched_main.c | 99 +++---------------------
>> include/drm/gpu_scheduler.h | 5 +-
>> 3 files changed, 48 insertions(+), 109 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
>> index 8e910586979e..cb5f596b48b7 100644
>> --- a/drivers/gpu/drm/scheduler/sched_entity.c
>> +++ b/drivers/gpu/drm/scheduler/sched_entity.c
>> @@ -473,9 +473,20 @@ drm_sched_job_dependency(struct drm_sched_job *job,
>> return NULL;
>> }
>>
>> +static ktime_t
>> +drm_sched_rq_get_rr_deadline(struct drm_sched_rq *rq)
>> +{
>> + lockdep_assert_held(&rq->lock);
>> +
>> + rq->rr_deadline = ktime_add_ns(rq->rr_deadline, 1);
>> +
>> + return rq->rr_deadline;
>> +}
>> +
>> struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
>> {
>> - struct drm_sched_job *sched_job;
>> + struct drm_sched_job *sched_job, *next_job;
>> + struct drm_sched_rq *rq;
>>
>> sched_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
>> if (!sched_job)
>> @@ -510,24 +521,28 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
>> * Update the entity's location in the min heap according to
>> * the timestamp of the next job, if any.
>> */
>> - if (drm_sched_policy == DRM_SCHED_POLICY_FIFO) {
>> - struct drm_sched_job *next;
>> - struct drm_sched_rq *rq;
>> + next_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
>>
>> - spin_lock(&entity->lock);
>> - rq = entity->rq;
>> - spin_lock(&rq->lock);
>> - next = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
>> - if (next) {
>> - drm_sched_rq_update_fifo_locked(entity, rq,
>> - next->submit_ts);
>> - } else {
>> - drm_sched_rq_remove_fifo_locked(entity, rq);
>> - }
>> - spin_unlock(&rq->lock);
>> - spin_unlock(&entity->lock);
>> + spin_lock(&entity->lock);
>> + rq = entity->rq;
>> + spin_lock(&rq->lock);
>> +
>> + if (next_job) {
>> + ktime_t ts;
>> +
>> + if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
>> + ts = next_job->submit_ts;
>> + else
>> + ts = drm_sched_rq_get_rr_deadline(rq);
>> +
>> + drm_sched_rq_update_fifo_locked(entity, rq, ts);
>> + } else {
>> + drm_sched_rq_remove_fifo_locked(entity, rq);
>> }
>>
>> + spin_unlock(&rq->lock);
>> + spin_unlock(&entity->lock);
>> +
>> /* Jobs and entities might have different lifecycles. Since we're
>> * removing the job from the entities queue, set the jobs entity pointer
>> * to NULL to prevent any future access of the entity through this job.
>> @@ -624,9 +639,9 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
>>
>> spin_lock(&rq->lock);
>> drm_sched_rq_add_entity(rq, entity);
>> -
>> - if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
>> - drm_sched_rq_update_fifo_locked(entity, rq, submit_ts);
>> + if (drm_sched_policy == DRM_SCHED_POLICY_RR)
>> + submit_ts = drm_sched_rq_get_rr_deadline(rq);
>> + drm_sched_rq_update_fifo_locked(entity, rq, submit_ts);
>>
>> spin_unlock(&rq->lock);
>> spin_unlock(&entity->lock);
>> diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
>> index 9beb4c611988..eb22b1b7de36 100644
>> --- a/drivers/gpu/drm/scheduler/sched_main.c
>> +++ b/drivers/gpu/drm/scheduler/sched_main.c
>> @@ -189,7 +189,6 @@ static void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
>> spin_lock_init(&rq->lock);
>> INIT_LIST_HEAD(&rq->entities);
>> rq->rb_tree_root = RB_ROOT_CACHED;
>> - rq->current_entity = NULL;
>> rq->sched = sched;
>> }
>>
>> @@ -235,82 +234,13 @@ void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
>> atomic_dec(rq->sched->score);
>> list_del_init(&entity->list);
>>
>> - if (rq->current_entity == entity)
>> - rq->current_entity = NULL;
>> -
>> - if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
>> - drm_sched_rq_remove_fifo_locked(entity, rq);
>> + drm_sched_rq_remove_fifo_locked(entity, rq);
>>
>> spin_unlock(&rq->lock);
>> }
>>
>> /**
>> - * drm_sched_rq_select_entity_rr - Select an entity which could provide a job to run
>> - *
>> - * @sched: the gpu scheduler
>> - * @rq: scheduler run queue to check.
>> - *
>> - * Try to find the next ready entity.
>> - *
>> - * Return an entity if one is found; return an error-pointer (!NULL) if an
>> - * entity was ready, but the scheduler had insufficient credits to accommodate
>> - * its job; return NULL, if no ready entity was found.
>> - */
>> -static struct drm_sched_entity *
>> -drm_sched_rq_select_entity_rr(struct drm_gpu_scheduler *sched,
>> - struct drm_sched_rq *rq)
>> -{
>> - struct drm_sched_entity *entity;
>> -
>> - spin_lock(&rq->lock);
>> -
>> - entity = rq->current_entity;
>> - if (entity) {
>> - list_for_each_entry_continue(entity, &rq->entities, list) {
>> - if (drm_sched_entity_is_ready(entity)) {
>> - /* If we can't queue yet, preserve the current
>> - * entity in terms of fairness.
>> - */
>> - if (!drm_sched_can_queue(sched, entity)) {
>> - spin_unlock(&rq->lock);
>> - return ERR_PTR(-ENOSPC);
>> - }
>> -
>> - rq->current_entity = entity;
>> - reinit_completion(&entity->entity_idle);
>> - spin_unlock(&rq->lock);
>> - return entity;
>> - }
>> - }
>> - }
>> -
>> - list_for_each_entry(entity, &rq->entities, list) {
>> - if (drm_sched_entity_is_ready(entity)) {
>> - /* If we can't queue yet, preserve the current entity in
>> - * terms of fairness.
>> - */
>> - if (!drm_sched_can_queue(sched, entity)) {
>> - spin_unlock(&rq->lock);
>> - return ERR_PTR(-ENOSPC);
>> - }
>> -
>> - rq->current_entity = entity;
>> - reinit_completion(&entity->entity_idle);
>> - spin_unlock(&rq->lock);
>> - return entity;
>> - }
>> -
>> - if (entity == rq->current_entity)
>> - break;
>> - }
>> -
>> - spin_unlock(&rq->lock);
>> -
>> - return NULL;
>> -}
>> -
>> -/**
>> - * drm_sched_rq_select_entity_fifo - Select an entity which provides a job to run
>> + * drm_sched_rq_select_entity - Select an entity which provides a job to run
>> *
>> * @sched: the gpu scheduler
>> * @rq: scheduler run queue to check.
>> @@ -322,32 +252,29 @@ drm_sched_rq_select_entity_rr(struct drm_gpu_scheduler *sched,
>> * its job; return NULL, if no ready entity was found.
>> */
>> static struct drm_sched_entity *
>> -drm_sched_rq_select_entity_fifo(struct drm_gpu_scheduler *sched,
>> - struct drm_sched_rq *rq)
>> +drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched,
>> + struct drm_sched_rq *rq)
>> {
>> + struct drm_sched_entity *entity = NULL;
>> struct rb_node *rb;
>>
>> spin_lock(&rq->lock);
>> for (rb = rb_first_cached(&rq->rb_tree_root); rb; rb = rb_next(rb)) {
>> - struct drm_sched_entity *entity;
>> -
>> entity = rb_entry(rb, struct drm_sched_entity, rb_tree_node);
>> if (drm_sched_entity_is_ready(entity)) {
>> - /* If we can't queue yet, preserve the current entity in
>> - * terms of fairness.
>> - */
>> if (!drm_sched_can_queue(sched, entity)) {
>> - spin_unlock(&rq->lock);
>> - return ERR_PTR(-ENOSPC);
>> + entity = ERR_PTR(-ENOSPC);
>> + break;
>> }
>>
>> reinit_completion(&entity->entity_idle);
>> break;
>> }
>> + entity = NULL;
>> }
>> spin_unlock(&rq->lock);
>>
>> - return rb ? rb_entry(rb, struct drm_sched_entity, rb_tree_node) : NULL;
>> + return entity;
>> }
>
> The whole diff of drm_sched_rq_select_entity_fifo() (except for the name) has
> nothing to do with the patch, does it?
>
> If you want refactor things, please do it in a separate patch.
Well spotted thanks. There was some re-ordering and cherry-picking
patches from some development branches and some mistakes crept in.
Regards,
Tvrtko
>>
>> /**
>> @@ -1045,20 +972,18 @@ void drm_sched_wakeup(struct drm_gpu_scheduler *sched)
>> static struct drm_sched_entity *
>> drm_sched_select_entity(struct drm_gpu_scheduler *sched)
>> {
>> - struct drm_sched_entity *entity;
>> + struct drm_sched_entity *entity = NULL;
>> int i;
>>
>> /* Start with the highest priority.
>> */
>> for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) {
>> - entity = drm_sched_policy == DRM_SCHED_POLICY_FIFO ?
>> - drm_sched_rq_select_entity_fifo(sched, sched->sched_rq[i]) :
>> - drm_sched_rq_select_entity_rr(sched, sched->sched_rq[i]);
>> + entity = drm_sched_rq_select_entity(sched, sched->sched_rq[i]);
>> if (entity)
>> break;
>> }
>>
>> - return IS_ERR(entity) ? NULL : entity;
>> + return IS_ERR(entity) ? NULL : entity;;
>> }
>>
>> /**
>> diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
>> index 978ca621cc13..db65600732b9 100644
>> --- a/include/drm/gpu_scheduler.h
>> +++ b/include/drm/gpu_scheduler.h
>> @@ -245,8 +245,7 @@ struct drm_sched_entity {
>> * struct drm_sched_rq - queue of entities to be scheduled.
>> *
>> * @sched: the scheduler to which this rq belongs to.
>> - * @lock: protects @entities, @rb_tree_root and @current_entity.
>> - * @current_entity: the entity which is to be scheduled.
>> + * @lock: protects @entities, @rb_tree_root and @rr_deadline.
>> * @entities: list of the entities to be scheduled.
>> * @rb_tree_root: root of time based priority queue of entities for FIFO scheduling
>> *
>> @@ -259,7 +258,7 @@ struct drm_sched_rq {
>>
>> spinlock_t lock;
>> /* Following members are protected by the @lock: */
>> - struct drm_sched_entity *current_entity;
>> + ktime_t rr_deadline;
>> struct list_head entities;
>> struct rb_root_cached rb_tree_root;
>> };
>> --
>> 2.47.1
>>
>
^ permalink raw reply [flat|nested] 61+ messages in thread
* [RFC 04/14] drm/sched: Consolidate entity run queue management
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
` (2 preceding siblings ...)
2024-12-30 16:52 ` [RFC 03/14] drm/sched: Implement RR via FIFO Tvrtko Ursulin
@ 2024-12-30 16:52 ` Tvrtko Ursulin
2024-12-30 16:52 ` [RFC 05/14] drm/sched: Move run queue related code into a separate file Tvrtko Ursulin
` (13 subsequent siblings)
17 siblings, 0 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2024-12-30 16:52 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Move the code dealing with entities entering and exiting run queues to
helpers to logically separate it from jobs entering and exiting entities.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <pstanner@redhat.com>
---
drivers/gpu/drm/scheduler/sched_entity.c | 66 ++--------------
drivers/gpu/drm/scheduler/sched_main.c | 98 +++++++++++++++++++-----
include/drm/gpu_scheduler.h | 12 +--
3 files changed, 90 insertions(+), 86 deletions(-)
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index cb5f596b48b7..b93da068585e 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -473,20 +473,9 @@ drm_sched_job_dependency(struct drm_sched_job *job,
return NULL;
}
-static ktime_t
-drm_sched_rq_get_rr_deadline(struct drm_sched_rq *rq)
-{
- lockdep_assert_held(&rq->lock);
-
- rq->rr_deadline = ktime_add_ns(rq->rr_deadline, 1);
-
- return rq->rr_deadline;
-}
-
struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
{
- struct drm_sched_job *sched_job, *next_job;
- struct drm_sched_rq *rq;
+ struct drm_sched_job *sched_job;
sched_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
if (!sched_job)
@@ -516,32 +505,7 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
smp_wmb();
spsc_queue_pop(&entity->job_queue);
-
- /*
- * Update the entity's location in the min heap according to
- * the timestamp of the next job, if any.
- */
- next_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
-
- spin_lock(&entity->lock);
- rq = entity->rq;
- spin_lock(&rq->lock);
-
- if (next_job) {
- ktime_t ts;
-
- if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
- ts = next_job->submit_ts;
- else
- ts = drm_sched_rq_get_rr_deadline(rq);
-
- drm_sched_rq_update_fifo_locked(entity, rq, ts);
- } else {
- drm_sched_rq_remove_fifo_locked(entity, rq);
- }
-
- spin_unlock(&rq->lock);
- spin_unlock(&entity->lock);
+ drm_sched_rq_pop_entity(entity->rq, entity);
/* Jobs and entities might have different lifecycles. Since we're
* removing the job from the entities queue, set the jobs entity pointer
@@ -623,30 +587,10 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
/* first job wakes up scheduler */
if (first) {
struct drm_gpu_scheduler *sched;
- struct drm_sched_rq *rq;
- /* Add the entity to the run queue */
- spin_lock(&entity->lock);
- if (entity->stopped) {
- spin_unlock(&entity->lock);
-
- DRM_ERROR("Trying to push to a killed entity\n");
- return;
- }
-
- rq = entity->rq;
- sched = rq->sched;
-
- spin_lock(&rq->lock);
- drm_sched_rq_add_entity(rq, entity);
- if (drm_sched_policy == DRM_SCHED_POLICY_RR)
- submit_ts = drm_sched_rq_get_rr_deadline(rq);
- drm_sched_rq_update_fifo_locked(entity, rq, submit_ts);
-
- spin_unlock(&rq->lock);
- spin_unlock(&entity->lock);
-
- drm_sched_wakeup(sched);
+ sched = drm_sched_rq_add_entity(entity->rq, entity, submit_ts);
+ if (sched)
+ drm_sched_wakeup(sched);
}
}
EXPORT_SYMBOL(drm_sched_entity_push_job);
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index eb22b1b7de36..52c1a71d48e1 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -146,18 +146,19 @@ static __always_inline bool drm_sched_entity_compare_before(struct rb_node *a,
return ktime_before(ent_a->oldest_job_waiting, ent_b->oldest_job_waiting);
}
-void drm_sched_rq_remove_fifo_locked(struct drm_sched_entity *entity,
- struct drm_sched_rq *rq)
+static void __drm_sched_rq_remove_fifo_locked(struct drm_sched_entity *entity,
+ struct drm_sched_rq *rq)
{
- if (!RB_EMPTY_NODE(&entity->rb_tree_node)) {
- rb_erase_cached(&entity->rb_tree_node, &rq->rb_tree_root);
- RB_CLEAR_NODE(&entity->rb_tree_node);
- }
+ lockdep_assert_held(&entity->lock);
+ lockdep_assert_held(&rq->lock);
+
+ rb_erase_cached(&entity->rb_tree_node, &rq->rb_tree_root);
+ RB_CLEAR_NODE(&entity->rb_tree_node);
}
-void drm_sched_rq_update_fifo_locked(struct drm_sched_entity *entity,
- struct drm_sched_rq *rq,
- ktime_t ts)
+static void __drm_sched_rq_add_fifo_locked(struct drm_sched_entity *entity,
+ struct drm_sched_rq *rq,
+ ktime_t ts)
{
/*
* Both locks need to be grabbed, one to protect from entity->rq change
@@ -167,8 +168,6 @@ void drm_sched_rq_update_fifo_locked(struct drm_sched_entity *entity,
lockdep_assert_held(&entity->lock);
lockdep_assert_held(&rq->lock);
- drm_sched_rq_remove_fifo_locked(entity, rq);
-
entity->oldest_job_waiting = ts;
rb_add_cached(&entity->rb_tree_node, &rq->rb_tree_root,
@@ -192,6 +191,16 @@ static void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
rq->sched = sched;
}
+static ktime_t
+drm_sched_rq_get_rr_deadline(struct drm_sched_rq *rq)
+{
+ lockdep_assert_held(&rq->lock);
+
+ rq->rr_deadline = ktime_add_ns(rq->rr_deadline, 1);
+
+ return rq->rr_deadline;
+}
+
/**
* drm_sched_rq_add_entity - add an entity
*
@@ -199,18 +208,41 @@ static void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
* @entity: scheduler entity
*
* Adds a scheduler entity to the run queue.
+ *
+ * Returns a DRM scheduler pre-selected to handle this entity.
*/
-void drm_sched_rq_add_entity(struct drm_sched_rq *rq,
- struct drm_sched_entity *entity)
+struct drm_gpu_scheduler *
+drm_sched_rq_add_entity(struct drm_sched_rq *rq,
+ struct drm_sched_entity *entity,
+ ktime_t ts)
{
- lockdep_assert_held(&entity->lock);
- lockdep_assert_held(&rq->lock);
+ struct drm_gpu_scheduler *sched;
+
+ if (entity->stopped) {
+ DRM_ERROR("Trying to push to a killed entity\n");
+ return NULL;
+ }
+
+ spin_lock(&entity->lock);
+ spin_lock(&rq->lock);
+
+ sched = rq->sched;
+ atomic_inc(sched->score);
if (!list_empty(&entity->list))
- return;
+ list_add_tail(&entity->list, &rq->entities);
- atomic_inc(rq->sched->score);
- list_add_tail(&entity->list, &rq->entities);
+ if (drm_sched_policy == DRM_SCHED_POLICY_RR)
+ ts = drm_sched_rq_get_rr_deadline(rq);
+
+ if (!RB_EMPTY_NODE(&entity->rb_tree_node))
+ __drm_sched_rq_remove_fifo_locked(entity, rq);
+ __drm_sched_rq_add_fifo_locked(entity, rq, ts);
+
+ spin_unlock(&rq->lock);
+ spin_unlock(&entity->lock);
+
+ return sched;
}
/**
@@ -234,11 +266,39 @@ void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
atomic_dec(rq->sched->score);
list_del_init(&entity->list);
- drm_sched_rq_remove_fifo_locked(entity, rq);
+ if (!RB_EMPTY_NODE(&entity->rb_tree_node))
+ __drm_sched_rq_remove_fifo_locked(entity, rq);
spin_unlock(&rq->lock);
}
+void drm_sched_rq_pop_entity(struct drm_sched_rq *rq,
+ struct drm_sched_entity *entity)
+{
+ struct drm_sched_job *next_job;
+
+ next_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
+
+ spin_lock(&entity->lock);
+ spin_lock(&rq->lock);
+
+ __drm_sched_rq_remove_fifo_locked(entity, rq);
+
+ if (next_job) {
+ ktime_t ts;
+
+ if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
+ ts = next_job->submit_ts;
+ else
+ ts = drm_sched_rq_get_rr_deadline(rq);
+
+ __drm_sched_rq_add_fifo_locked(entity, rq, ts);
+ }
+
+ spin_unlock(&rq->lock);
+ spin_unlock(&entity->lock);
+}
+
/**
* drm_sched_rq_select_entity - Select an entity which provides a job to run
*
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index db65600732b9..23d5b1b0b048 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -585,15 +585,15 @@ bool drm_sched_dependency_optimized(struct dma_fence* fence,
struct drm_sched_entity *entity);
void drm_sched_fault(struct drm_gpu_scheduler *sched);
-void drm_sched_rq_add_entity(struct drm_sched_rq *rq,
- struct drm_sched_entity *entity);
+struct drm_gpu_scheduler *
+drm_sched_rq_add_entity(struct drm_sched_rq *rq,
+ struct drm_sched_entity *entity,
+ ktime_t ts);
void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
struct drm_sched_entity *entity);
-void drm_sched_rq_remove_fifo_locked(struct drm_sched_entity *entity,
- struct drm_sched_rq *rq);
-void drm_sched_rq_update_fifo_locked(struct drm_sched_entity *entity,
- struct drm_sched_rq *rq, ktime_t ts);
+void drm_sched_rq_pop_entity(struct drm_sched_rq *rq,
+ struct drm_sched_entity *entity);
int drm_sched_entity_init(struct drm_sched_entity *entity,
enum drm_sched_priority priority,
--
2.47.1
^ permalink raw reply related [flat|nested] 61+ messages in thread* [RFC 05/14] drm/sched: Move run queue related code into a separate file
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
` (3 preceding siblings ...)
2024-12-30 16:52 ` [RFC 04/14] drm/sched: Consolidate entity run queue management Tvrtko Ursulin
@ 2024-12-30 16:52 ` Tvrtko Ursulin
2024-12-31 0:35 ` kernel test robot
2024-12-30 16:52 ` [RFC 06/14] drm/sched: Ignore own fence earlier Tvrtko Ursulin
` (12 subsequent siblings)
17 siblings, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2024-12-30 16:52 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Lets move all the code dealing with struct drm_sched_rq into a separate
compilation unit. Advantage being sched_main.c is left with a clearer set
of responsibilities.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <pstanner@redhat.com>
---
drivers/gpu/drm/scheduler/Makefile | 2 +-
drivers/gpu/drm/scheduler/sched_main.c | 207 +------------------------
drivers/gpu/drm/scheduler/sched_rq.c | 203 ++++++++++++++++++++++++
include/drm/gpu_scheduler.h | 13 ++
4 files changed, 219 insertions(+), 206 deletions(-)
create mode 100644 drivers/gpu/drm/scheduler/sched_rq.c
diff --git a/drivers/gpu/drm/scheduler/Makefile b/drivers/gpu/drm/scheduler/Makefile
index 53863621829f..d11d83e285e7 100644
--- a/drivers/gpu/drm/scheduler/Makefile
+++ b/drivers/gpu/drm/scheduler/Makefile
@@ -20,6 +20,6 @@
# OTHER DEALINGS IN THE SOFTWARE.
#
#
-gpu-sched-y := sched_main.o sched_fence.o sched_entity.o
+gpu-sched-y := sched_main.o sched_fence.o sched_entity.o sched_rq.o
obj-$(CONFIG_DRM_SCHED) += gpu-sched.o
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index 52c1a71d48e1..5c92784bb533 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -87,9 +87,6 @@ static struct lockdep_map drm_sched_lockdep_map = {
};
#endif
-#define to_drm_sched_job(sched_job) \
- container_of((sched_job), struct drm_sched_job, queue_node)
-
int drm_sched_policy = DRM_SCHED_POLICY_FIFO;
/**
@@ -118,8 +115,8 @@ static u32 drm_sched_available_credits(struct drm_gpu_scheduler *sched)
* Return true if we can push at least one more job from @entity, false
* otherwise.
*/
-static bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
- struct drm_sched_entity *entity)
+bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
+ struct drm_sched_entity *entity)
{
struct drm_sched_job *s_job;
@@ -137,206 +134,6 @@ static bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
return drm_sched_available_credits(sched) >= s_job->credits;
}
-static __always_inline bool drm_sched_entity_compare_before(struct rb_node *a,
- const struct rb_node *b)
-{
- struct drm_sched_entity *ent_a = rb_entry((a), struct drm_sched_entity, rb_tree_node);
- struct drm_sched_entity *ent_b = rb_entry((b), struct drm_sched_entity, rb_tree_node);
-
- return ktime_before(ent_a->oldest_job_waiting, ent_b->oldest_job_waiting);
-}
-
-static void __drm_sched_rq_remove_fifo_locked(struct drm_sched_entity *entity,
- struct drm_sched_rq *rq)
-{
- lockdep_assert_held(&entity->lock);
- lockdep_assert_held(&rq->lock);
-
- rb_erase_cached(&entity->rb_tree_node, &rq->rb_tree_root);
- RB_CLEAR_NODE(&entity->rb_tree_node);
-}
-
-static void __drm_sched_rq_add_fifo_locked(struct drm_sched_entity *entity,
- struct drm_sched_rq *rq,
- ktime_t ts)
-{
- /*
- * Both locks need to be grabbed, one to protect from entity->rq change
- * for entity from within concurrent drm_sched_entity_select_rq and the
- * other to update the rb tree structure.
- */
- lockdep_assert_held(&entity->lock);
- lockdep_assert_held(&rq->lock);
-
- entity->oldest_job_waiting = ts;
-
- rb_add_cached(&entity->rb_tree_node, &rq->rb_tree_root,
- drm_sched_entity_compare_before);
-}
-
-/**
- * drm_sched_rq_init - initialize a given run queue struct
- *
- * @sched: scheduler instance to associate with this run queue
- * @rq: scheduler run queue
- *
- * Initializes a scheduler runqueue.
- */
-static void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
- struct drm_sched_rq *rq)
-{
- spin_lock_init(&rq->lock);
- INIT_LIST_HEAD(&rq->entities);
- rq->rb_tree_root = RB_ROOT_CACHED;
- rq->sched = sched;
-}
-
-static ktime_t
-drm_sched_rq_get_rr_deadline(struct drm_sched_rq *rq)
-{
- lockdep_assert_held(&rq->lock);
-
- rq->rr_deadline = ktime_add_ns(rq->rr_deadline, 1);
-
- return rq->rr_deadline;
-}
-
-/**
- * drm_sched_rq_add_entity - add an entity
- *
- * @rq: scheduler run queue
- * @entity: scheduler entity
- *
- * Adds a scheduler entity to the run queue.
- *
- * Returns a DRM scheduler pre-selected to handle this entity.
- */
-struct drm_gpu_scheduler *
-drm_sched_rq_add_entity(struct drm_sched_rq *rq,
- struct drm_sched_entity *entity,
- ktime_t ts)
-{
- struct drm_gpu_scheduler *sched;
-
- if (entity->stopped) {
- DRM_ERROR("Trying to push to a killed entity\n");
- return NULL;
- }
-
- spin_lock(&entity->lock);
- spin_lock(&rq->lock);
-
- sched = rq->sched;
- atomic_inc(sched->score);
-
- if (!list_empty(&entity->list))
- list_add_tail(&entity->list, &rq->entities);
-
- if (drm_sched_policy == DRM_SCHED_POLICY_RR)
- ts = drm_sched_rq_get_rr_deadline(rq);
-
- if (!RB_EMPTY_NODE(&entity->rb_tree_node))
- __drm_sched_rq_remove_fifo_locked(entity, rq);
- __drm_sched_rq_add_fifo_locked(entity, rq, ts);
-
- spin_unlock(&rq->lock);
- spin_unlock(&entity->lock);
-
- return sched;
-}
-
-/**
- * drm_sched_rq_remove_entity - remove an entity
- *
- * @rq: scheduler run queue
- * @entity: scheduler entity
- *
- * Removes a scheduler entity from the run queue.
- */
-void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
- struct drm_sched_entity *entity)
-{
- lockdep_assert_held(&entity->lock);
-
- if (list_empty(&entity->list))
- return;
-
- spin_lock(&rq->lock);
-
- atomic_dec(rq->sched->score);
- list_del_init(&entity->list);
-
- if (!RB_EMPTY_NODE(&entity->rb_tree_node))
- __drm_sched_rq_remove_fifo_locked(entity, rq);
-
- spin_unlock(&rq->lock);
-}
-
-void drm_sched_rq_pop_entity(struct drm_sched_rq *rq,
- struct drm_sched_entity *entity)
-{
- struct drm_sched_job *next_job;
-
- next_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
-
- spin_lock(&entity->lock);
- spin_lock(&rq->lock);
-
- __drm_sched_rq_remove_fifo_locked(entity, rq);
-
- if (next_job) {
- ktime_t ts;
-
- if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
- ts = next_job->submit_ts;
- else
- ts = drm_sched_rq_get_rr_deadline(rq);
-
- __drm_sched_rq_add_fifo_locked(entity, rq, ts);
- }
-
- spin_unlock(&rq->lock);
- spin_unlock(&entity->lock);
-}
-
-/**
- * drm_sched_rq_select_entity - Select an entity which provides a job to run
- *
- * @sched: the gpu scheduler
- * @rq: scheduler run queue to check.
- *
- * Find oldest waiting ready entity.
- *
- * Return an entity if one is found; return an error-pointer (!NULL) if an
- * entity was ready, but the scheduler had insufficient credits to accommodate
- * its job; return NULL, if no ready entity was found.
- */
-static struct drm_sched_entity *
-drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched,
- struct drm_sched_rq *rq)
-{
- struct drm_sched_entity *entity = NULL;
- struct rb_node *rb;
-
- spin_lock(&rq->lock);
- for (rb = rb_first_cached(&rq->rb_tree_root); rb; rb = rb_next(rb)) {
- entity = rb_entry(rb, struct drm_sched_entity, rb_tree_node);
- if (drm_sched_entity_is_ready(entity)) {
- if (!drm_sched_can_queue(sched, entity)) {
- entity = ERR_PTR(-ENOSPC);
- break;
- }
-
- reinit_completion(&entity->entity_idle);
- break;
- }
- entity = NULL;
- }
- spin_unlock(&rq->lock);
-
- return entity;
-}
-
/**
* drm_sched_run_job_queue - enqueue run-job work
* @sched: scheduler instance
diff --git a/drivers/gpu/drm/scheduler/sched_rq.c b/drivers/gpu/drm/scheduler/sched_rq.c
new file mode 100644
index 000000000000..5b31e5434d12
--- /dev/null
+++ b/drivers/gpu/drm/scheduler/sched_rq.c
@@ -0,0 +1,203 @@
+#include <linux/rbtree.h>
+
+#include <drm/drm_print.h>
+#include <drm/gpu_scheduler.h>
+
+static __always_inline bool drm_sched_entity_compare_before(struct rb_node *a,
+ const struct rb_node *b)
+{
+ struct drm_sched_entity *ent_a = rb_entry((a), struct drm_sched_entity, rb_tree_node);
+ struct drm_sched_entity *ent_b = rb_entry((b), struct drm_sched_entity, rb_tree_node);
+
+ return ktime_before(ent_a->oldest_job_waiting, ent_b->oldest_job_waiting);
+}
+
+static void __drm_sched_rq_remove_fifo_locked(struct drm_sched_entity *entity,
+ struct drm_sched_rq *rq)
+{
+ lockdep_assert_held(&entity->lock);
+ lockdep_assert_held(&rq->lock);
+
+ rb_erase_cached(&entity->rb_tree_node, &rq->rb_tree_root);
+ RB_CLEAR_NODE(&entity->rb_tree_node);
+}
+
+static void __drm_sched_rq_add_fifo_locked(struct drm_sched_entity *entity,
+ struct drm_sched_rq *rq,
+ ktime_t ts)
+{
+ /*
+ * Both locks need to be grabbed, one to protect from entity->rq change
+ * for entity from within concurrent drm_sched_entity_select_rq and the
+ * other to update the rb tree structure.
+ */
+ lockdep_assert_held(&entity->lock);
+ lockdep_assert_held(&rq->lock);
+
+ entity->oldest_job_waiting = ts;
+ rb_add_cached(&entity->rb_tree_node, &rq->rb_tree_root,
+ drm_sched_entity_compare_before);
+}
+
+/**
+ * drm_sched_rq_init - initialize a given run queue struct
+ *
+ * @sched: scheduler instance to associate with this run queue
+ * @rq: scheduler run queue
+ *
+ * Initializes a scheduler runqueue.
+ */
+void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
+ struct drm_sched_rq *rq)
+{
+ spin_lock_init(&rq->lock);
+ INIT_LIST_HEAD(&rq->entities);
+ rq->rb_tree_root = RB_ROOT_CACHED;
+ rq->sched = sched;
+}
+
+static ktime_t
+drm_sched_rq_get_rr_deadline(struct drm_sched_rq *rq)
+{
+ lockdep_assert_held(&rq->lock);
+
+ rq->rr_deadline = ktime_add_ns(rq->rr_deadline, 1);
+
+ return rq->rr_deadline;
+}
+
+/**
+ * drm_sched_rq_add_entity - add an entity
+ *
+ * @rq: scheduler run queue
+ * @entity: scheduler entity
+ *
+ * Adds a scheduler entity to the run queue.
+ *
+ * Returns a DRM scheduler pre-selected to handle this entity.
+ */
+struct drm_gpu_scheduler *
+drm_sched_rq_add_entity(struct drm_sched_rq *rq,
+ struct drm_sched_entity *entity,
+ ktime_t ts)
+{
+ struct drm_gpu_scheduler *sched;
+
+ if (entity->stopped) {
+ DRM_ERROR("Trying to push to a killed entity\n");
+ return NULL;
+ }
+
+ spin_lock(&entity->lock);
+ spin_lock(&rq->lock);
+
+ sched = rq->sched;
+ atomic_inc(sched->score);
+
+ if (!list_empty(&entity->list))
+ list_add_tail(&entity->list, &rq->entities);
+
+ if (drm_sched_policy == DRM_SCHED_POLICY_RR)
+ ts = drm_sched_rq_get_rr_deadline(rq);
+
+ if (!RB_EMPTY_NODE(&entity->rb_tree_node))
+ __drm_sched_rq_remove_fifo_locked(entity, rq);
+ __drm_sched_rq_add_fifo_locked(entity, rq, ts);
+
+ spin_unlock(&rq->lock);
+ spin_unlock(&entity->lock);
+
+ return sched;
+}
+
+/**
+ * drm_sched_rq_remove_entity - remove an entity
+ *
+ * @rq: scheduler run queue
+ * @entity: scheduler entity
+ *
+ * Removes a scheduler entity from the run queue.
+ */
+void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
+ struct drm_sched_entity *entity)
+{
+ lockdep_assert_held(&entity->lock);
+
+ if (list_empty(&entity->list))
+ return;
+
+ spin_lock(&rq->lock);
+
+ atomic_dec(rq->sched->score);
+ list_del_init(&entity->list);
+
+ if (!RB_EMPTY_NODE(&entity->rb_tree_node))
+ __drm_sched_rq_remove_fifo_locked(entity, rq);
+
+ spin_unlock(&rq->lock);
+}
+
+void drm_sched_rq_pop_entity(struct drm_sched_rq *rq,
+ struct drm_sched_entity *entity)
+{
+ struct drm_sched_job *next_job;
+
+ next_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
+
+ spin_lock(&entity->lock);
+ spin_lock(&rq->lock);
+
+ __drm_sched_rq_remove_fifo_locked(entity, rq);
+
+ if (next_job) {
+ ktime_t ts;
+
+ if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
+ ts = next_job->submit_ts;
+ else
+ ts = drm_sched_rq_get_rr_deadline(rq);
+
+ __drm_sched_rq_add_fifo_locked(entity, rq, ts);
+ }
+
+ spin_unlock(&rq->lock);
+ spin_unlock(&entity->lock);
+}
+
+/**
+ * drm_sched_rq_select_entity - Select an entity which provides a job to run
+ *
+ * @sched: the gpu scheduler
+ * @rq: scheduler run queue to check.
+ *
+ * Find oldest waiting ready entity.
+ *
+ * Return an entity if one is found; return an error-pointer (!NULL) if an
+ * entity was ready, but the scheduler had insufficient credits to accommodate
+ * its job; return NULL, if no ready entity was found.
+ */
+struct drm_sched_entity *
+drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched,
+ struct drm_sched_rq *rq)
+{
+ struct drm_sched_entity *entity = NULL;
+ struct rb_node *rb;
+
+ spin_lock(&rq->lock);
+ for (rb = rb_first_cached(&rq->rb_tree_root); rb; rb = rb_next(rb)) {
+ entity = rb_entry(rb, struct drm_sched_entity, rb_tree_node);
+ if (drm_sched_entity_is_ready(entity)) {
+ if (!drm_sched_can_queue(sched, entity)) {
+ entity = ERR_PTR(-ENOSPC);
+ break;
+ }
+
+ reinit_completion(&entity->entity_idle);
+ break;
+ }
+ entity = NULL;
+ }
+ spin_unlock(&rq->lock);
+
+ return entity;
+}
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index 23d5b1b0b048..45879a755f34 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -386,6 +386,9 @@ struct drm_sched_job {
ktime_t submit_ts;
};
+#define to_drm_sched_job(sched_job) \
+ container_of((sched_job), struct drm_sched_job, queue_node)
+
static inline bool drm_sched_invalidate_job(struct drm_sched_job *s_job,
int threshold)
{
@@ -547,6 +550,10 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
atomic_t *score, const char *name, struct device *dev);
void drm_sched_fini(struct drm_gpu_scheduler *sched);
+
+bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
+ struct drm_sched_entity *entity);
+
int drm_sched_job_init(struct drm_sched_job *job,
struct drm_sched_entity *entity,
u32 credits, void *owner);
@@ -585,6 +592,9 @@ bool drm_sched_dependency_optimized(struct dma_fence* fence,
struct drm_sched_entity *entity);
void drm_sched_fault(struct drm_gpu_scheduler *sched);
+void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
+ struct drm_sched_rq *rq);
+
struct drm_gpu_scheduler *
drm_sched_rq_add_entity(struct drm_sched_rq *rq,
struct drm_sched_entity *entity,
@@ -594,6 +604,9 @@ void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
void drm_sched_rq_pop_entity(struct drm_sched_rq *rq,
struct drm_sched_entity *entity);
+struct drm_sched_entity *
+drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched,
+ struct drm_sched_rq *rq);
int drm_sched_entity_init(struct drm_sched_entity *entity,
enum drm_sched_priority priority,
--
2.47.1
^ permalink raw reply related [flat|nested] 61+ messages in thread* Re: [RFC 05/14] drm/sched: Move run queue related code into a separate file
2024-12-30 16:52 ` [RFC 05/14] drm/sched: Move run queue related code into a separate file Tvrtko Ursulin
@ 2024-12-31 0:35 ` kernel test robot
0 siblings, 0 replies; 61+ messages in thread
From: kernel test robot @ 2024-12-31 0:35 UTC (permalink / raw)
To: Tvrtko Ursulin; +Cc: oe-kbuild-all
Hi Tvrtko,
[This is a private test report for your RFC patch.]
kernel test robot noticed the following build warnings:
[auto build test WARNING on drm-exynos/exynos-drm-next]
[also build test WARNING on linus/master v6.13-rc5 next-20241220]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Tvrtko-Ursulin/drm-sched-Delete-unused-update_job_credits/20241231-011327
base: https://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git exynos-drm-next
patch link: https://lore.kernel.org/r/20241230165259.95855-6-tursulin%40igalia.com
patch subject: [RFC 05/14] drm/sched: Move run queue related code into a separate file
config: s390-randconfig-001-20241231 (https://download.01.org/0day-ci/archive/20241231/202412310801.fR4rGSTm-lkp@intel.com/config)
compiler: s390-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241231/202412310801.fR4rGSTm-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202412310801.fR4rGSTm-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/gpu/drm/scheduler/sched_rq.c:83: warning: Function parameter or struct member 'ts' not described in 'drm_sched_rq_add_entity'
vim +83 drivers/gpu/drm/scheduler/sched_rq.c
68
69 /**
70 * drm_sched_rq_add_entity - add an entity
71 *
72 * @rq: scheduler run queue
73 * @entity: scheduler entity
74 *
75 * Adds a scheduler entity to the run queue.
76 *
77 * Returns a DRM scheduler pre-selected to handle this entity.
78 */
79 struct drm_gpu_scheduler *
80 drm_sched_rq_add_entity(struct drm_sched_rq *rq,
81 struct drm_sched_entity *entity,
82 ktime_t ts)
> 83 {
84 struct drm_gpu_scheduler *sched;
85
86 if (entity->stopped) {
87 DRM_ERROR("Trying to push to a killed entity\n");
88 return NULL;
89 }
90
91 spin_lock(&entity->lock);
92 spin_lock(&rq->lock);
93
94 sched = rq->sched;
95 atomic_inc(sched->score);
96
97 if (!list_empty(&entity->list))
98 list_add_tail(&entity->list, &rq->entities);
99
100 if (drm_sched_policy == DRM_SCHED_POLICY_RR)
101 ts = drm_sched_rq_get_rr_deadline(rq);
102
103 if (!RB_EMPTY_NODE(&entity->rb_tree_node))
104 __drm_sched_rq_remove_fifo_locked(entity, rq);
105 __drm_sched_rq_add_fifo_locked(entity, rq, ts);
106
107 spin_unlock(&rq->lock);
108 spin_unlock(&entity->lock);
109
110 return sched;
111 }
112
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 61+ messages in thread
* [RFC 06/14] drm/sched: Ignore own fence earlier
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
` (4 preceding siblings ...)
2024-12-30 16:52 ` [RFC 05/14] drm/sched: Move run queue related code into a separate file Tvrtko Ursulin
@ 2024-12-30 16:52 ` Tvrtko Ursulin
2024-12-30 16:52 ` [RFC 07/14] drm/sched: Resolve same scheduler dependencies earlier Tvrtko Ursulin
` (11 subsequent siblings)
17 siblings, 0 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2024-12-30 16:52 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
If a job depends on another job from the same context it will be naturally
ordered by the submission queue. We can therefore ignore those before
adding them to the dependency tracking xarray.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <pstanner@redhat.com>
---
drivers/gpu/drm/scheduler/sched_entity.c | 11 -----------
drivers/gpu/drm/scheduler/sched_main.c | 12 ++++++++++++
2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index b93da068585e..2c342c7b9712 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -412,17 +412,6 @@ static bool drm_sched_entity_add_dependency_cb(struct drm_sched_entity *entity)
struct dma_fence *fence = entity->dependency;
struct drm_sched_fence *s_fence;
- if (fence->context == entity->fence_context ||
- fence->context == entity->fence_context + 1) {
- /*
- * Fence is a scheduled/finished fence from a job
- * which belongs to the same entity, we can ignore
- * fences from ourself
- */
- dma_fence_put(entity->dependency);
- return false;
- }
-
s_fence = to_drm_sched_fence(fence);
if (!fence->error && s_fence && s_fence->sched == sched &&
!test_bit(DRM_SCHED_FENCE_DONT_PIPELINE, &fence->flags)) {
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index 5c92784bb533..34ed22c6482e 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -648,6 +648,7 @@ EXPORT_SYMBOL(drm_sched_job_arm);
int drm_sched_job_add_dependency(struct drm_sched_job *job,
struct dma_fence *fence)
{
+ struct drm_sched_entity *entity = job->entity;
struct dma_fence *entry;
unsigned long index;
u32 id = 0;
@@ -656,6 +657,17 @@ int drm_sched_job_add_dependency(struct drm_sched_job *job,
if (!fence)
return 0;
+ if (fence->context == entity->fence_context ||
+ fence->context == entity->fence_context + 1) {
+ /*
+ * Fence is a scheduled/finished fence from a job
+ * which belongs to the same entity, we can ignore
+ * fences from ourself
+ */
+ dma_fence_put(fence);
+ return 0;
+ }
+
/* Deduplicate if we already depend on a fence from the same context.
* This lets the size of the array of deps scale with the number of
* engines involved, rather than the number of BOs.
--
2.47.1
^ permalink raw reply related [flat|nested] 61+ messages in thread* [RFC 07/14] drm/sched: Resolve same scheduler dependencies earlier
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
` (5 preceding siblings ...)
2024-12-30 16:52 ` [RFC 06/14] drm/sched: Ignore own fence earlier Tvrtko Ursulin
@ 2024-12-30 16:52 ` Tvrtko Ursulin
2024-12-30 16:52 ` [RFC 08/14] drm/sched: Add deadline policy Tvrtko Ursulin
` (10 subsequent siblings)
17 siblings, 0 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2024-12-30 16:52 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
When a job's dependency is on a same scheduler we pipeline the two
directly to the backend by replacing the dependency with the scheduled
instead of the finished fence. Ordering is handled by the backend.
Instead of doing this fence substitution at the time of popping the job
(entity selected by the worker), we can do it earlier when preparing the
job for submission.
We add a new helper drm_sched_job_prepare_dependecies() which is ran
before pushing the job but inside the arm+push block guaranteeing the
final scheduler instance has been assigned and is fixed.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <pstanner@redhat.com>
---
drivers/gpu/drm/scheduler/sched_entity.c | 72 +++++++-----------------
drivers/gpu/drm/scheduler/sched_main.c | 23 ++++++++
include/drm/gpu_scheduler.h | 2 +-
3 files changed, 45 insertions(+), 52 deletions(-)
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index 2c342c7b9712..608bc43ff256 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -360,31 +360,6 @@ void drm_sched_entity_destroy(struct drm_sched_entity *entity)
}
EXPORT_SYMBOL(drm_sched_entity_destroy);
-/* drm_sched_entity_clear_dep - callback to clear the entities dependency */
-static void drm_sched_entity_clear_dep(struct dma_fence *f,
- struct dma_fence_cb *cb)
-{
- struct drm_sched_entity *entity =
- container_of(cb, struct drm_sched_entity, cb);
-
- entity->dependency = NULL;
- dma_fence_put(f);
-}
-
-/*
- * drm_sched_entity_wakeup - callback to clear the entity's dependency and
- * wake up the scheduler
- */
-static void drm_sched_entity_wakeup(struct dma_fence *f,
- struct dma_fence_cb *cb)
-{
- struct drm_sched_entity *entity =
- container_of(cb, struct drm_sched_entity, cb);
-
- drm_sched_entity_clear_dep(f, cb);
- drm_sched_wakeup(entity->rq->sched);
-}
-
/**
* drm_sched_entity_set_priority - Sets priority of the entity
*
@@ -402,41 +377,34 @@ void drm_sched_entity_set_priority(struct drm_sched_entity *entity,
}
EXPORT_SYMBOL(drm_sched_entity_set_priority);
+/*
+ * drm_sched_entity_wakeup - callback to clear the entity's dependency and
+ * wake up the scheduler
+ */
+static void drm_sched_entity_wakeup(struct dma_fence *f,
+ struct dma_fence_cb *cb)
+{
+ struct drm_sched_entity *entity =
+ container_of(cb, struct drm_sched_entity, cb);
+
+ entity->dependency = NULL;
+ dma_fence_put(f);
+ drm_sched_wakeup(entity->rq->sched);
+}
+
/*
* Add a callback to the current dependency of the entity to wake up the
* scheduler when the entity becomes available.
*/
static bool drm_sched_entity_add_dependency_cb(struct drm_sched_entity *entity)
{
- struct drm_gpu_scheduler *sched = entity->rq->sched;
struct dma_fence *fence = entity->dependency;
- struct drm_sched_fence *s_fence;
- s_fence = to_drm_sched_fence(fence);
- if (!fence->error && s_fence && s_fence->sched == sched &&
- !test_bit(DRM_SCHED_FENCE_DONT_PIPELINE, &fence->flags)) {
-
- /*
- * Fence is from the same scheduler, only need to wait for
- * it to be scheduled
- */
- fence = dma_fence_get(&s_fence->scheduled);
- dma_fence_put(entity->dependency);
- entity->dependency = fence;
- if (!dma_fence_add_callback(fence, &entity->cb,
- drm_sched_entity_clear_dep))
- return true;
-
- /* Ignore it when it is already scheduled */
- dma_fence_put(fence);
- return false;
- }
-
- if (!dma_fence_add_callback(entity->dependency, &entity->cb,
+ if (!dma_fence_add_callback(fence, &entity->cb,
drm_sched_entity_wakeup))
return true;
- dma_fence_put(entity->dependency);
+ dma_fence_put(fence);
return false;
}
@@ -558,19 +526,21 @@ void drm_sched_entity_select_rq(struct drm_sched_entity *entity)
void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
{
struct drm_sched_entity *entity = sched_job->entity;
+ ktime_t submit_ts = ktime_get();
bool first;
- ktime_t submit_ts;
trace_drm_sched_job(sched_job, entity);
atomic_inc(entity->rq->sched->score);
WRITE_ONCE(entity->last_user, current->group_leader);
+ drm_sched_job_prepare_dependecies(sched_job);
+
/*
* After the sched_job is pushed into the entity queue, it may be
* completed and freed up at any time. We can no longer access it.
* Make sure to set the submit_ts first, to avoid a race.
*/
- sched_job->submit_ts = submit_ts = ktime_get();
+ sched_job->submit_ts = submit_ts;
first = spsc_queue_push(&entity->job_queue, &sched_job->queue_node);
/* first job wakes up scheduler */
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index 34ed22c6482e..ba9b0274b185 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -780,6 +780,29 @@ int drm_sched_job_add_implicit_dependencies(struct drm_sched_job *job,
}
EXPORT_SYMBOL(drm_sched_job_add_implicit_dependencies);
+void drm_sched_job_prepare_dependecies(struct drm_sched_job *job)
+{
+ struct drm_gpu_scheduler *sched = job->sched;
+ struct dma_fence *fence;
+ unsigned long index;
+
+ xa_for_each(&job->dependencies, index, fence) {
+ struct drm_sched_fence *s_fence = to_drm_sched_fence(fence);
+
+ if (fence->error || !s_fence || s_fence->sched != sched ||
+ test_bit(DRM_SCHED_FENCE_DONT_PIPELINE, &fence->flags))
+ continue;
+
+ /*
+ * Fence is from the same scheduler, only need to wait for
+ * it to be scheduled.
+ */
+ xa_store(&job->dependencies, index,
+ dma_fence_get(&s_fence->scheduled), GFP_KERNEL);
+ dma_fence_put(fence);
+ }
+}
+
/**
* drm_sched_job_cleanup - clean up scheduler job resources
* @job: scheduler job to clean up
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index 45879a755f34..6fee85e45d45 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -570,7 +570,7 @@ int drm_sched_job_add_resv_dependencies(struct drm_sched_job *job,
int drm_sched_job_add_implicit_dependencies(struct drm_sched_job *job,
struct drm_gem_object *obj,
bool write);
-
+void drm_sched_job_prepare_dependecies(struct drm_sched_job *job);
void drm_sched_entity_modify_sched(struct drm_sched_entity *entity,
struct drm_gpu_scheduler **sched_list,
--
2.47.1
^ permalink raw reply related [flat|nested] 61+ messages in thread* [RFC 08/14] drm/sched: Add deadline policy
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
` (6 preceding siblings ...)
2024-12-30 16:52 ` [RFC 07/14] drm/sched: Resolve same scheduler dependencies earlier Tvrtko Ursulin
@ 2024-12-30 16:52 ` Tvrtko Ursulin
2025-01-02 13:11 ` Philipp Stanner
2024-12-30 16:52 ` [RFC 09/14] drm/sched: Remove FIFO and RR and simplify to a single run queue Tvrtko Ursulin
` (9 subsequent siblings)
17 siblings, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2024-12-30 16:52 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Deadline scheduling policy should be a fairer flavour of FIFO with two
main advantages being that it can naturally connect with the dma-fence
deadlines, and secondly that it can get away with multiple run queues per
scheduler.
From the latter comes the fairness advantage. Where the current FIFO
policy will always starve low priority entities by normal, and normal
by high etc, deadline tracks all runnable entities in a single run queue
and assigns them deadlines based on priority. Instead of being ordered
strictly by priority, jobs and entities become ordered by deadlines.
This means that a later higher priority submission can still overtake an
earlier lower priority one, but eventually the lower priority will get its
turn even if high priority is constantly feeding new work.
Current mapping of priority to deadlines is somewhat arbitrary and looks
like this (submit timestamp plus constant offset in micro-seconds):
static const unsigned int d_us[] = {
[DRM_SCHED_PRIORITY_KERNEL] = 100,
[DRM_SCHED_PRIORITY_HIGH] = 1000,
[DRM_SCHED_PRIORITY_NORMAL] = 5000,
[DRM_SCHED_PRIORITY_LOW] = 100000,
};
Assuming simultaneous submission of one normal and one low prioriy job at
a time of "t", they will get respective deadlines of t+5ms and t+100ms.
Hence normal will run first and low will run after it, or at the latest
100ms after it was submitted in case other higher priority submissions
overtake it in the meantime.
Because deadline policy does not need run queues, if the FIFO and RR
polices are later removed, that would allow for a significant
simplification of the code base by reducing the 1:N to 1:1 scheduler
to run queue relationship.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <pstanner@redhat.com>
---
drivers/gpu/drm/scheduler/sched_entity.c | 53 +++++++++++++++++++-----
drivers/gpu/drm/scheduler/sched_main.c | 14 ++++---
drivers/gpu/drm/scheduler/sched_rq.c | 5 ++-
include/drm/gpu_scheduler.h | 10 ++++-
4 files changed, 64 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index 608bc43ff256..6928ec19ec23 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -71,6 +71,8 @@ int drm_sched_entity_init(struct drm_sched_entity *entity,
entity->guilty = guilty;
entity->num_sched_list = num_sched_list;
entity->priority = priority;
+ entity->rq_priority = drm_sched_policy == DRM_SCHED_POLICY_DEADLINE ?
+ DRM_SCHED_PRIORITY_KERNEL : priority;
/*
* It's perfectly valid to initialize an entity without having a valid
* scheduler attached. It's just not valid to use the scheduler before it
@@ -87,17 +89,23 @@ int drm_sched_entity_init(struct drm_sched_entity *entity,
*/
pr_warn("%s: called with uninitialized scheduler\n", __func__);
} else if (num_sched_list) {
- /* The "priority" of an entity cannot exceed the number of run-queues of a
- * scheduler. Protect against num_rqs being 0, by converting to signed. Choose
- * the lowest priority available.
+ enum drm_sched_priority p = entity->priority;
+
+ /*
+ * The "priority" of an entity cannot exceed the number of
+ * run-queues of a scheduler. Protect against num_rqs being 0,
+ * by converting to signed. Choose the lowest priority
+ * available.
*/
- if (entity->priority >= sched_list[0]->num_rqs) {
- drm_err(sched_list[0], "entity with out-of-bounds priority:%u num_rqs:%u\n",
- entity->priority, sched_list[0]->num_rqs);
- entity->priority = max_t(s32, (s32) sched_list[0]->num_rqs - 1,
- (s32) DRM_SCHED_PRIORITY_KERNEL);
+ if (p >= sched_list[0]->num_user_rqs) {
+ drm_err(sched_list[0], "entity with out-of-bounds priority:%u num_user_rqs:%u\n",
+ p, sched_list[0]->num_user_rqs);
+ p = max_t(s32,
+ (s32)sched_list[0]->num_user_rqs - 1,
+ (s32)DRM_SCHED_PRIORITY_KERNEL);
+ entity->priority = p;
}
- entity->rq = sched_list[0]->sched_rq[entity->priority];
+ entity->rq = sched_list[0]->sched_rq[entity->rq_priority];
}
init_completion(&entity->entity_idle);
@@ -377,6 +385,27 @@ void drm_sched_entity_set_priority(struct drm_sched_entity *entity,
}
EXPORT_SYMBOL(drm_sched_entity_set_priority);
+static ktime_t
+__drm_sched_entity_get_job_deadline(struct drm_sched_entity *entity,
+ ktime_t submit_ts)
+{
+ static const unsigned int d_us[] = {
+ [DRM_SCHED_PRIORITY_KERNEL] = 100,
+ [DRM_SCHED_PRIORITY_HIGH] = 1000,
+ [DRM_SCHED_PRIORITY_NORMAL] = 5000,
+ [DRM_SCHED_PRIORITY_LOW] = 100000,
+ };
+
+ return ktime_add_us(submit_ts, d_us[entity->priority]);
+}
+
+ktime_t
+drm_sched_entity_get_job_deadline(struct drm_sched_entity *entity,
+ struct drm_sched_job *job)
+{
+ return __drm_sched_entity_get_job_deadline(entity, job->submit_ts);
+}
+
/*
* drm_sched_entity_wakeup - callback to clear the entity's dependency and
* wake up the scheduler
@@ -503,7 +532,7 @@ void drm_sched_entity_select_rq(struct drm_sched_entity *entity)
spin_lock(&entity->lock);
sched = drm_sched_pick_best(entity->sched_list, entity->num_sched_list);
- rq = sched ? sched->sched_rq[entity->priority] : NULL;
+ rq = sched ? sched->sched_rq[entity->rq_priority] : NULL;
if (rq != entity->rq) {
drm_sched_rq_remove_entity(entity->rq, entity);
entity->rq = rq;
@@ -547,6 +576,10 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
if (first) {
struct drm_gpu_scheduler *sched;
+ if (drm_sched_policy == DRM_SCHED_POLICY_DEADLINE)
+ submit_ts = __drm_sched_entity_get_job_deadline(entity,
+ submit_ts);
+
sched = drm_sched_rq_add_entity(entity->rq, entity, submit_ts);
if (sched)
drm_sched_wakeup(sched);
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index ba9b0274b185..433bef85eeaf 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -87,13 +87,13 @@ static struct lockdep_map drm_sched_lockdep_map = {
};
#endif
-int drm_sched_policy = DRM_SCHED_POLICY_FIFO;
+int drm_sched_policy = DRM_SCHED_POLICY_DEADLINE;
/**
* DOC: sched_policy (int)
* Used to override default entities scheduling policy in a run queue.
*/
-MODULE_PARM_DESC(sched_policy, "Specify the scheduling policy for entities on a run-queue, " __stringify(DRM_SCHED_POLICY_RR) " = Round Robin, " __stringify(DRM_SCHED_POLICY_FIFO) " = FIFO (default).");
+MODULE_PARM_DESC(sched_policy, "Specify the scheduling policy for entities on a run-queue, " __stringify(DRM_SCHED_POLICY_RR) " = Round Robin, " __stringify(DRM_SCHED_POLICY_FIFO) " = FIFO, " __stringify(DRM_SCHED_POLICY_DEADLINE) " = Virtual deadline (default).");
module_param_named(sched_policy, drm_sched_policy, int, 0444);
static u32 drm_sched_available_credits(struct drm_gpu_scheduler *sched)
@@ -1109,11 +1109,15 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
sched->own_submit_wq = true;
}
- sched->sched_rq = kmalloc_array(num_rqs, sizeof(*sched->sched_rq),
+ sched->num_user_rqs = num_rqs;
+ sched->num_rqs = drm_sched_policy != DRM_SCHED_POLICY_DEADLINE ?
+ num_rqs : 1;
+ sched->sched_rq = kmalloc_array(sched->num_rqs,
+ sizeof(*sched->sched_rq),
GFP_KERNEL | __GFP_ZERO);
if (!sched->sched_rq)
goto Out_check_own;
- sched->num_rqs = num_rqs;
+
for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) {
sched->sched_rq[i] = kzalloc(sizeof(*sched->sched_rq[i]), GFP_KERNEL);
if (!sched->sched_rq[i])
@@ -1227,7 +1231,7 @@ void drm_sched_increase_karma(struct drm_sched_job *bad)
if (bad->s_priority != DRM_SCHED_PRIORITY_KERNEL) {
atomic_inc(&bad->karma);
- for (i = DRM_SCHED_PRIORITY_HIGH; i < sched->num_rqs; i++) {
+ for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) {
struct drm_sched_rq *rq = sched->sched_rq[i];
spin_lock(&rq->lock);
diff --git a/drivers/gpu/drm/scheduler/sched_rq.c b/drivers/gpu/drm/scheduler/sched_rq.c
index 5b31e5434d12..a6bb21250350 100644
--- a/drivers/gpu/drm/scheduler/sched_rq.c
+++ b/drivers/gpu/drm/scheduler/sched_rq.c
@@ -152,7 +152,10 @@ void drm_sched_rq_pop_entity(struct drm_sched_rq *rq,
if (next_job) {
ktime_t ts;
- if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
+ if (drm_sched_policy == DRM_SCHED_POLICY_DEADLINE)
+ ts = drm_sched_entity_get_job_deadline(entity,
+ next_job);
+ else if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
ts = next_job->submit_ts;
else
ts = drm_sched_rq_get_rr_deadline(rq);
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index 6fee85e45d45..7532071fbea8 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -74,8 +74,9 @@ enum drm_sched_priority {
/* Used to choose between FIFO and RR job-scheduling */
extern int drm_sched_policy;
-#define DRM_SCHED_POLICY_RR 0
-#define DRM_SCHED_POLICY_FIFO 1
+#define DRM_SCHED_POLICY_RR 0
+#define DRM_SCHED_POLICY_FIFO 1
+#define DRM_SCHED_POLICY_DEADLINE 2
/**
* struct drm_sched_entity - A wrapper around a job queue (typically
@@ -153,6 +154,8 @@ struct drm_sched_entity {
*/
struct spsc_queue job_queue;
+ enum drm_sched_priority rq_priority;
+
/**
* @fence_seq:
*
@@ -522,6 +525,7 @@ struct drm_gpu_scheduler {
long timeout;
const char *name;
u32 num_rqs;
+ u32 num_user_rqs;
struct drm_sched_rq **sched_rq;
wait_queue_head_t job_scheduled;
atomic64_t job_id_count;
@@ -623,6 +627,8 @@ void drm_sched_entity_set_priority(struct drm_sched_entity *entity,
enum drm_sched_priority priority);
bool drm_sched_entity_is_ready(struct drm_sched_entity *entity);
int drm_sched_entity_error(struct drm_sched_entity *entity);
+ktime_t drm_sched_entity_get_job_deadline(struct drm_sched_entity *entity,
+ struct drm_sched_job *job);
struct drm_sched_fence *drm_sched_fence_alloc(
struct drm_sched_entity *s_entity, void *owner);
--
2.47.1
^ permalink raw reply related [flat|nested] 61+ messages in thread* Re: [RFC 08/14] drm/sched: Add deadline policy
2024-12-30 16:52 ` [RFC 08/14] drm/sched: Add deadline policy Tvrtko Ursulin
@ 2025-01-02 13:11 ` Philipp Stanner
2025-01-03 12:40 ` Tvrtko Ursulin
0 siblings, 1 reply; 61+ messages in thread
From: Philipp Stanner @ 2025-01-02 13:11 UTC (permalink / raw)
To: Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost
On Mon, 2024-12-30 at 16:52 +0000, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>
> Deadline scheduling policy should be a fairer flavour of FIFO with
> two
> main advantages being that it can naturally connect with the dma-
> fence
> deadlines, and secondly that it can get away with multiple run queues
> per
> scheduler.
>
> From the latter comes the fairness advantage. Where the current FIFO
> policy will always starve low priority entities by normal, and normal
> by high etc, deadline tracks all runnable entities in a single run
> queue
> and assigns them deadlines based on priority. Instead of being
> ordered
> strictly by priority, jobs and entities become ordered by deadlines.
>
> This means that a later higher priority submission can still overtake
> an
> earlier lower priority one, but eventually the lower priority will
> get its
> turn even if high priority is constantly feeding new work.
So, as you're aware of, this is a major change in behavior. FIFO's
purpose actually is to be unfair, and my understanding has always been
that it is on purpose that the higher priority will with absolute
certainty take precedence.
Reason being that on the high priority things like configuring memory /
mappings are done, which you want to be prioritized.
IOW in which scenario would you want the low priorities to be able to
overtake the higher ones?
@Danilo, @Christian?
>
> Current mapping of priority to deadlines is somewhat arbitrary and
> looks
> like this (submit timestamp plus constant offset in micro-seconds):
>
> static const unsigned int d_us[] = {
> [DRM_SCHED_PRIORITY_KERNEL] = 100,
> [DRM_SCHED_PRIORITY_HIGH] = 1000,
> [DRM_SCHED_PRIORITY_NORMAL] = 5000,
> [DRM_SCHED_PRIORITY_LOW] = 100000,
> };
>
> Assuming simultaneous submission of one normal and one low prioriy
> job at
> a time of "t", they will get respective deadlines of t+5ms and
> t+100ms.
> Hence normal will run first and low will run after it, or at the
> latest
> 100ms after it was submitted in case other higher priority
> submissions
> overtake it in the meantime.
>
> Because deadline policy does not need run queues, if the FIFO and RR
> polices are later removed, that would allow for a significant
> simplification of the code base by reducing the 1:N to 1:1 scheduler
> to run queue relationship.
So the proposed upsides for the rework are that a) code can arguably be
simplified and that b) deadline is fairer than FIFO.
Focusing on b) right now: Have you seen it in the wild that high
priorities starve lower ones? Is that a problem already?
I assume you have been working on that for a reason – do you have a
usecase in amdgpu or similar where the deadline policy improves things
in a way?
P.
>
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: Danilo Krummrich <dakr@redhat.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Philipp Stanner <pstanner@redhat.com>
> ---
> drivers/gpu/drm/scheduler/sched_entity.c | 53 +++++++++++++++++++---
> --
> drivers/gpu/drm/scheduler/sched_main.c | 14 ++++---
> drivers/gpu/drm/scheduler/sched_rq.c | 5 ++-
> include/drm/gpu_scheduler.h | 10 ++++-
> 4 files changed, 64 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/gpu/drm/scheduler/sched_entity.c
> b/drivers/gpu/drm/scheduler/sched_entity.c
> index 608bc43ff256..6928ec19ec23 100644
> --- a/drivers/gpu/drm/scheduler/sched_entity.c
> +++ b/drivers/gpu/drm/scheduler/sched_entity.c
> @@ -71,6 +71,8 @@ int drm_sched_entity_init(struct drm_sched_entity
> *entity,
> entity->guilty = guilty;
> entity->num_sched_list = num_sched_list;
> entity->priority = priority;
> + entity->rq_priority = drm_sched_policy ==
> DRM_SCHED_POLICY_DEADLINE ?
> + DRM_SCHED_PRIORITY_KERNEL : priority;
> /*
> * It's perfectly valid to initialize an entity without
> having a valid
> * scheduler attached. It's just not valid to use the
> scheduler before it
> @@ -87,17 +89,23 @@ int drm_sched_entity_init(struct drm_sched_entity
> *entity,
> */
> pr_warn("%s: called with uninitialized scheduler\n",
> __func__);
> } else if (num_sched_list) {
> - /* The "priority" of an entity cannot exceed the
> number of run-queues of a
> - * scheduler. Protect against num_rqs being 0, by
> converting to signed. Choose
> - * the lowest priority available.
> + enum drm_sched_priority p = entity->priority;
> +
> + /*
> + * The "priority" of an entity cannot exceed the
> number of
> + * run-queues of a scheduler. Protect against
> num_rqs being 0,
> + * by converting to signed. Choose the lowest
> priority
> + * available.
> */
> - if (entity->priority >= sched_list[0]->num_rqs) {
> - drm_err(sched_list[0], "entity with out-of-
> bounds priority:%u num_rqs:%u\n",
> - entity->priority, sched_list[0]-
> >num_rqs);
> - entity->priority = max_t(s32, (s32)
> sched_list[0]->num_rqs - 1,
> - (s32)
> DRM_SCHED_PRIORITY_KERNEL);
> + if (p >= sched_list[0]->num_user_rqs) {
> + drm_err(sched_list[0], "entity with out-of-
> bounds priority:%u num_user_rqs:%u\n",
> + p, sched_list[0]->num_user_rqs);
> + p = max_t(s32,
> + (s32)sched_list[0]->num_user_rqs -
> 1,
> + (s32)DRM_SCHED_PRIORITY_KERNEL);
> + entity->priority = p;
> }
> - entity->rq = sched_list[0]->sched_rq[entity-
> >priority];
> + entity->rq = sched_list[0]->sched_rq[entity-
> >rq_priority];
> }
>
> init_completion(&entity->entity_idle);
> @@ -377,6 +385,27 @@ void drm_sched_entity_set_priority(struct
> drm_sched_entity *entity,
> }
> EXPORT_SYMBOL(drm_sched_entity_set_priority);
>
> +static ktime_t
> +__drm_sched_entity_get_job_deadline(struct drm_sched_entity *entity,
> + ktime_t submit_ts)
> +{
> + static const unsigned int d_us[] = {
> + [DRM_SCHED_PRIORITY_KERNEL] = 100,
> + [DRM_SCHED_PRIORITY_HIGH] = 1000,
> + [DRM_SCHED_PRIORITY_NORMAL] = 5000,
> + [DRM_SCHED_PRIORITY_LOW] = 100000,
> + };
> +
> + return ktime_add_us(submit_ts, d_us[entity->priority]);
> +}
> +
> +ktime_t
> +drm_sched_entity_get_job_deadline(struct drm_sched_entity *entity,
> + struct drm_sched_job *job)
> +{
> + return __drm_sched_entity_get_job_deadline(entity, job-
> >submit_ts);
> +}
> +
> /*
> * drm_sched_entity_wakeup - callback to clear the entity's
> dependency and
> * wake up the scheduler
> @@ -503,7 +532,7 @@ void drm_sched_entity_select_rq(struct
> drm_sched_entity *entity)
>
> spin_lock(&entity->lock);
> sched = drm_sched_pick_best(entity->sched_list, entity-
> >num_sched_list);
> - rq = sched ? sched->sched_rq[entity->priority] : NULL;
> + rq = sched ? sched->sched_rq[entity->rq_priority] : NULL;
> if (rq != entity->rq) {
> drm_sched_rq_remove_entity(entity->rq, entity);
> entity->rq = rq;
> @@ -547,6 +576,10 @@ void drm_sched_entity_push_job(struct
> drm_sched_job *sched_job)
> if (first) {
> struct drm_gpu_scheduler *sched;
>
> + if (drm_sched_policy == DRM_SCHED_POLICY_DEADLINE)
> + submit_ts =
> __drm_sched_entity_get_job_deadline(entity,
> +
> submit_ts);
> +
> sched = drm_sched_rq_add_entity(entity->rq, entity,
> submit_ts);
> if (sched)
> drm_sched_wakeup(sched);
> diff --git a/drivers/gpu/drm/scheduler/sched_main.c
> b/drivers/gpu/drm/scheduler/sched_main.c
> index ba9b0274b185..433bef85eeaf 100644
> --- a/drivers/gpu/drm/scheduler/sched_main.c
> +++ b/drivers/gpu/drm/scheduler/sched_main.c
> @@ -87,13 +87,13 @@ static struct lockdep_map drm_sched_lockdep_map =
> {
> };
> #endif
>
> -int drm_sched_policy = DRM_SCHED_POLICY_FIFO;
> +int drm_sched_policy = DRM_SCHED_POLICY_DEADLINE;
>
> /**
> * DOC: sched_policy (int)
> * Used to override default entities scheduling policy in a run
> queue.
> */
> -MODULE_PARM_DESC(sched_policy, "Specify the scheduling policy for
> entities on a run-queue, " __stringify(DRM_SCHED_POLICY_RR) " = Round
> Robin, " __stringify(DRM_SCHED_POLICY_FIFO) " = FIFO (default).");
> +MODULE_PARM_DESC(sched_policy, "Specify the scheduling policy for
> entities on a run-queue, " __stringify(DRM_SCHED_POLICY_RR) " = Round
> Robin, " __stringify(DRM_SCHED_POLICY_FIFO) " = FIFO, "
> __stringify(DRM_SCHED_POLICY_DEADLINE) " = Virtual deadline
> (default).");
> module_param_named(sched_policy, drm_sched_policy, int, 0444);
>
> static u32 drm_sched_available_credits(struct drm_gpu_scheduler
> *sched)
> @@ -1109,11 +1109,15 @@ int drm_sched_init(struct drm_gpu_scheduler
> *sched,
> sched->own_submit_wq = true;
> }
>
> - sched->sched_rq = kmalloc_array(num_rqs, sizeof(*sched-
> >sched_rq),
> + sched->num_user_rqs = num_rqs;
> + sched->num_rqs = drm_sched_policy !=
> DRM_SCHED_POLICY_DEADLINE ?
> + num_rqs : 1;
> + sched->sched_rq = kmalloc_array(sched->num_rqs,
> + sizeof(*sched->sched_rq),
> GFP_KERNEL | __GFP_ZERO);
> if (!sched->sched_rq)
> goto Out_check_own;
> - sched->num_rqs = num_rqs;
> +
> for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++)
> {
> sched->sched_rq[i] = kzalloc(sizeof(*sched-
> >sched_rq[i]), GFP_KERNEL);
> if (!sched->sched_rq[i])
> @@ -1227,7 +1231,7 @@ void drm_sched_increase_karma(struct
> drm_sched_job *bad)
> if (bad->s_priority != DRM_SCHED_PRIORITY_KERNEL) {
> atomic_inc(&bad->karma);
>
> - for (i = DRM_SCHED_PRIORITY_HIGH; i < sched-
> >num_rqs; i++) {
> + for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched-
> >num_rqs; i++) {
> struct drm_sched_rq *rq = sched-
> >sched_rq[i];
>
> spin_lock(&rq->lock);
> diff --git a/drivers/gpu/drm/scheduler/sched_rq.c
> b/drivers/gpu/drm/scheduler/sched_rq.c
> index 5b31e5434d12..a6bb21250350 100644
> --- a/drivers/gpu/drm/scheduler/sched_rq.c
> +++ b/drivers/gpu/drm/scheduler/sched_rq.c
> @@ -152,7 +152,10 @@ void drm_sched_rq_pop_entity(struct drm_sched_rq
> *rq,
> if (next_job) {
> ktime_t ts;
>
> - if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
> + if (drm_sched_policy == DRM_SCHED_POLICY_DEADLINE)
> + ts =
> drm_sched_entity_get_job_deadline(entity,
> +
> next_job);
> + else if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
> ts = next_job->submit_ts;
> else
> ts = drm_sched_rq_get_rr_deadline(rq);
> diff --git a/include/drm/gpu_scheduler.h
> b/include/drm/gpu_scheduler.h
> index 6fee85e45d45..7532071fbea8 100644
> --- a/include/drm/gpu_scheduler.h
> +++ b/include/drm/gpu_scheduler.h
> @@ -74,8 +74,9 @@ enum drm_sched_priority {
> /* Used to choose between FIFO and RR job-scheduling */
> extern int drm_sched_policy;
>
> -#define DRM_SCHED_POLICY_RR 0
> -#define DRM_SCHED_POLICY_FIFO 1
> +#define DRM_SCHED_POLICY_RR 0
> +#define DRM_SCHED_POLICY_FIFO 1
> +#define DRM_SCHED_POLICY_DEADLINE 2
>
> /**
> * struct drm_sched_entity - A wrapper around a job queue (typically
> @@ -153,6 +154,8 @@ struct drm_sched_entity {
> */
> struct spsc_queue job_queue;
>
> + enum drm_sched_priority rq_priority;
> +
> /**
> * @fence_seq:
> *
> @@ -522,6 +525,7 @@ struct drm_gpu_scheduler {
> long timeout;
> const char *name;
> u32 num_rqs;
> + u32 num_user_rqs;
> struct drm_sched_rq **sched_rq;
> wait_queue_head_t job_scheduled;
> atomic64_t job_id_count;
> @@ -623,6 +627,8 @@ void drm_sched_entity_set_priority(struct
> drm_sched_entity *entity,
> enum drm_sched_priority
> priority);
> bool drm_sched_entity_is_ready(struct drm_sched_entity *entity);
> int drm_sched_entity_error(struct drm_sched_entity *entity);
> +ktime_t drm_sched_entity_get_job_deadline(struct drm_sched_entity
> *entity,
> + struct drm_sched_job
> *job);
>
> struct drm_sched_fence *drm_sched_fence_alloc(
> struct drm_sched_entity *s_entity, void *owner);
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 08/14] drm/sched: Add deadline policy
2025-01-02 13:11 ` Philipp Stanner
@ 2025-01-03 12:40 ` Tvrtko Ursulin
2025-01-03 12:59 ` Philipp Stanner
0 siblings, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-03 12:40 UTC (permalink / raw)
To: Philipp Stanner, Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Christian König, Danilo Krummrich, Matthew Brost
On 02/01/2025 13:11, Philipp Stanner wrote:
> On Mon, 2024-12-30 at 16:52 +0000, Tvrtko Ursulin wrote:
>> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>>
>> Deadline scheduling policy should be a fairer flavour of FIFO with
>> two
>> main advantages being that it can naturally connect with the dma-
>> fence
>> deadlines, and secondly that it can get away with multiple run queues
>> per
>> scheduler.
>>
>> From the latter comes the fairness advantage. Where the current FIFO
>> policy will always starve low priority entities by normal, and normal
>> by high etc, deadline tracks all runnable entities in a single run
>> queue
>> and assigns them deadlines based on priority. Instead of being
>> ordered
>> strictly by priority, jobs and entities become ordered by deadlines.
>>
>> This means that a later higher priority submission can still overtake
>> an
>> earlier lower priority one, but eventually the lower priority will
>> get its
>> turn even if high priority is constantly feeding new work.
>
> So, as you're aware of, this is a major change in behavior. FIFO's
> purpose actually is to be unfair, and my understanding has always been
> that it is on purpose that the higher priority will with absolute
> certainty take precedence.
>
> Reason being that on the high priority things like configuring memory /
> mappings are done, which you want to be prioritized.
Right. For the kernel priority for instance I could make them get a very
early deadline ensuring they still run first.
> IOW in which scenario would you want the low priorities to be able to
> overtake the higher ones?
I would say always. I don't see it as overtaking but avoiding complete
starvation. In the CPU world if you run:
$ game & nice computation
You don't expect the computation to get zero CPU time while the game is
running.
Although I am not saying with the current DRM scheduler it is guaranteed
to get zero GPU time. It will still get scheduled in cases when the
priority run queues happen to be temporarily empty. But if someone would
be submitting work very efficiently low priority would never run.
Deadline in its current form is not perfect or immune to all submission
patterns either, which is why this is RFC.
> @Danilo, @Christian?
>
>
>>
>> Current mapping of priority to deadlines is somewhat arbitrary and
>> looks
>> like this (submit timestamp plus constant offset in micro-seconds):
>>
>> static const unsigned int d_us[] = {
>> [DRM_SCHED_PRIORITY_KERNEL] = 100,
>> [DRM_SCHED_PRIORITY_HIGH] = 1000,
>> [DRM_SCHED_PRIORITY_NORMAL] = 5000,
>> [DRM_SCHED_PRIORITY_LOW] = 100000,
>> };
>>
>> Assuming simultaneous submission of one normal and one low prioriy
>> job at
>> a time of "t", they will get respective deadlines of t+5ms and
>> t+100ms.
>> Hence normal will run first and low will run after it, or at the
>> latest
>> 100ms after it was submitted in case other higher priority
>> submissions
>> overtake it in the meantime.
>>
>> Because deadline policy does not need run queues, if the FIFO and RR
>> polices are later removed, that would allow for a significant
>> simplification of the code base by reducing the 1:N to 1:1 scheduler
>> to run queue relationship.
>
> So the proposed upsides for the rework are that a) code can arguably be
> simplified and that b) deadline is fairer than FIFO.
>
> Focusing on b) right now: Have you seen it in the wild that high
> priorities starve lower ones? Is that a problem already?
>
> I assume you have been working on that for a reason – do you have a
> usecase in amdgpu or similar where the deadline policy improves things
> in a way?
I don't have any observed use cases as of right now. It is an experiment
to see if we can make the code simpler without adding regressions and
improvements would be a bonus.
Hence the RFC and even RFT on top because I am looking for a) some ideas
on what and how to test, b) because different drivers use the scheduler
differently and I cannot try them all, seeing if there is interest from
people to try it out and provide feedback.
(I had a more drastic version where deadlines were based on runnable
status (after dependencies were resolved). That version showed
significantly lower scheduling jitter but was unstable becuase I took
too many shortcuts to sketch it out. I don't think it is feasible
without a much larger rewrite.)
Regards,
Tvrtko
>> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>> Cc: Christian König <christian.koenig@amd.com>
>> Cc: Danilo Krummrich <dakr@redhat.com>
>> Cc: Matthew Brost <matthew.brost@intel.com>
>> Cc: Philipp Stanner <pstanner@redhat.com>
>> ---
>> drivers/gpu/drm/scheduler/sched_entity.c | 53 +++++++++++++++++++---
>> --
>> drivers/gpu/drm/scheduler/sched_main.c | 14 ++++---
>> drivers/gpu/drm/scheduler/sched_rq.c | 5 ++-
>> include/drm/gpu_scheduler.h | 10 ++++-
>> 4 files changed, 64 insertions(+), 18 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/scheduler/sched_entity.c
>> b/drivers/gpu/drm/scheduler/sched_entity.c
>> index 608bc43ff256..6928ec19ec23 100644
>> --- a/drivers/gpu/drm/scheduler/sched_entity.c
>> +++ b/drivers/gpu/drm/scheduler/sched_entity.c
>> @@ -71,6 +71,8 @@ int drm_sched_entity_init(struct drm_sched_entity
>> *entity,
>> entity->guilty = guilty;
>> entity->num_sched_list = num_sched_list;
>> entity->priority = priority;
>> + entity->rq_priority = drm_sched_policy ==
>> DRM_SCHED_POLICY_DEADLINE ?
>> + DRM_SCHED_PRIORITY_KERNEL : priority;
>> /*
>> * It's perfectly valid to initialize an entity without
>> having a valid
>> * scheduler attached. It's just not valid to use the
>> scheduler before it
>> @@ -87,17 +89,23 @@ int drm_sched_entity_init(struct drm_sched_entity
>> *entity,
>> */
>> pr_warn("%s: called with uninitialized scheduler\n",
>> __func__);
>> } else if (num_sched_list) {
>> - /* The "priority" of an entity cannot exceed the
>> number of run-queues of a
>> - * scheduler. Protect against num_rqs being 0, by
>> converting to signed. Choose
>> - * the lowest priority available.
>> + enum drm_sched_priority p = entity->priority;
>> +
>> + /*
>> + * The "priority" of an entity cannot exceed the
>> number of
>> + * run-queues of a scheduler. Protect against
>> num_rqs being 0,
>> + * by converting to signed. Choose the lowest
>> priority
>> + * available.
>> */
>> - if (entity->priority >= sched_list[0]->num_rqs) {
>> - drm_err(sched_list[0], "entity with out-of-
>> bounds priority:%u num_rqs:%u\n",
>> - entity->priority, sched_list[0]-
>>> num_rqs);
>> - entity->priority = max_t(s32, (s32)
>> sched_list[0]->num_rqs - 1,
>> - (s32)
>> DRM_SCHED_PRIORITY_KERNEL);
>> + if (p >= sched_list[0]->num_user_rqs) {
>> + drm_err(sched_list[0], "entity with out-of-
>> bounds priority:%u num_user_rqs:%u\n",
>> + p, sched_list[0]->num_user_rqs);
>> + p = max_t(s32,
>> + (s32)sched_list[0]->num_user_rqs -
>> 1,
>> + (s32)DRM_SCHED_PRIORITY_KERNEL);
>> + entity->priority = p;
>> }
>> - entity->rq = sched_list[0]->sched_rq[entity-
>>> priority];
>> + entity->rq = sched_list[0]->sched_rq[entity-
>>> rq_priority];
>> }
>>
>> init_completion(&entity->entity_idle);
>> @@ -377,6 +385,27 @@ void drm_sched_entity_set_priority(struct
>> drm_sched_entity *entity,
>> }
>> EXPORT_SYMBOL(drm_sched_entity_set_priority);
>>
>> +static ktime_t
>> +__drm_sched_entity_get_job_deadline(struct drm_sched_entity *entity,
>> + ktime_t submit_ts)
>> +{
>> + static const unsigned int d_us[] = {
>> + [DRM_SCHED_PRIORITY_KERNEL] = 100,
>> + [DRM_SCHED_PRIORITY_HIGH] = 1000,
>> + [DRM_SCHED_PRIORITY_NORMAL] = 5000,
>> + [DRM_SCHED_PRIORITY_LOW] = 100000,
>> + };
>> +
>> + return ktime_add_us(submit_ts, d_us[entity->priority]);
>> +}
>> +
>> +ktime_t
>> +drm_sched_entity_get_job_deadline(struct drm_sched_entity *entity,
>> + struct drm_sched_job *job)
>> +{
>> + return __drm_sched_entity_get_job_deadline(entity, job-
>>> submit_ts);
>> +}
>> +
>> /*
>> * drm_sched_entity_wakeup - callback to clear the entity's
>> dependency and
>> * wake up the scheduler
>> @@ -503,7 +532,7 @@ void drm_sched_entity_select_rq(struct
>> drm_sched_entity *entity)
>>
>> spin_lock(&entity->lock);
>> sched = drm_sched_pick_best(entity->sched_list, entity-
>>> num_sched_list);
>> - rq = sched ? sched->sched_rq[entity->priority] : NULL;
>> + rq = sched ? sched->sched_rq[entity->rq_priority] : NULL;
>> if (rq != entity->rq) {
>> drm_sched_rq_remove_entity(entity->rq, entity);
>> entity->rq = rq;
>> @@ -547,6 +576,10 @@ void drm_sched_entity_push_job(struct
>> drm_sched_job *sched_job)
>> if (first) {
>> struct drm_gpu_scheduler *sched;
>>
>> + if (drm_sched_policy == DRM_SCHED_POLICY_DEADLINE)
>> + submit_ts =
>> __drm_sched_entity_get_job_deadline(entity,
>> +
>> submit_ts);
>> +
>> sched = drm_sched_rq_add_entity(entity->rq, entity,
>> submit_ts);
>> if (sched)
>> drm_sched_wakeup(sched);
>> diff --git a/drivers/gpu/drm/scheduler/sched_main.c
>> b/drivers/gpu/drm/scheduler/sched_main.c
>> index ba9b0274b185..433bef85eeaf 100644
>> --- a/drivers/gpu/drm/scheduler/sched_main.c
>> +++ b/drivers/gpu/drm/scheduler/sched_main.c
>> @@ -87,13 +87,13 @@ static struct lockdep_map drm_sched_lockdep_map =
>> {
>> };
>> #endif
>>
>> -int drm_sched_policy = DRM_SCHED_POLICY_FIFO;
>> +int drm_sched_policy = DRM_SCHED_POLICY_DEADLINE;
>>
>> /**
>> * DOC: sched_policy (int)
>> * Used to override default entities scheduling policy in a run
>> queue.
>> */
>> -MODULE_PARM_DESC(sched_policy, "Specify the scheduling policy for
>> entities on a run-queue, " __stringify(DRM_SCHED_POLICY_RR) " = Round
>> Robin, " __stringify(DRM_SCHED_POLICY_FIFO) " = FIFO (default).");
>> +MODULE_PARM_DESC(sched_policy, "Specify the scheduling policy for
>> entities on a run-queue, " __stringify(DRM_SCHED_POLICY_RR) " = Round
>> Robin, " __stringify(DRM_SCHED_POLICY_FIFO) " = FIFO, "
>> __stringify(DRM_SCHED_POLICY_DEADLINE) " = Virtual deadline
>> (default).");
>> module_param_named(sched_policy, drm_sched_policy, int, 0444);
>>
>> static u32 drm_sched_available_credits(struct drm_gpu_scheduler
>> *sched)
>> @@ -1109,11 +1109,15 @@ int drm_sched_init(struct drm_gpu_scheduler
>> *sched,
>> sched->own_submit_wq = true;
>> }
>>
>> - sched->sched_rq = kmalloc_array(num_rqs, sizeof(*sched-
>>> sched_rq),
>> + sched->num_user_rqs = num_rqs;
>> + sched->num_rqs = drm_sched_policy !=
>> DRM_SCHED_POLICY_DEADLINE ?
>> + num_rqs : 1;
>> + sched->sched_rq = kmalloc_array(sched->num_rqs,
>> + sizeof(*sched->sched_rq),
>> GFP_KERNEL | __GFP_ZERO);
>> if (!sched->sched_rq)
>> goto Out_check_own;
>> - sched->num_rqs = num_rqs;
>> +
>> for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++)
>> {
>> sched->sched_rq[i] = kzalloc(sizeof(*sched-
>>> sched_rq[i]), GFP_KERNEL);
>> if (!sched->sched_rq[i])
>> @@ -1227,7 +1231,7 @@ void drm_sched_increase_karma(struct
>> drm_sched_job *bad)
>> if (bad->s_priority != DRM_SCHED_PRIORITY_KERNEL) {
>> atomic_inc(&bad->karma);
>>
>> - for (i = DRM_SCHED_PRIORITY_HIGH; i < sched-
>>> num_rqs; i++) {
>> + for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched-
>>> num_rqs; i++) {
>> struct drm_sched_rq *rq = sched-
>>> sched_rq[i];
>>
>> spin_lock(&rq->lock);
>> diff --git a/drivers/gpu/drm/scheduler/sched_rq.c
>> b/drivers/gpu/drm/scheduler/sched_rq.c
>> index 5b31e5434d12..a6bb21250350 100644
>> --- a/drivers/gpu/drm/scheduler/sched_rq.c
>> +++ b/drivers/gpu/drm/scheduler/sched_rq.c
>> @@ -152,7 +152,10 @@ void drm_sched_rq_pop_entity(struct drm_sched_rq
>> *rq,
>> if (next_job) {
>> ktime_t ts;
>>
>> - if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
>> + if (drm_sched_policy == DRM_SCHED_POLICY_DEADLINE)
>> + ts =
>> drm_sched_entity_get_job_deadline(entity,
>> +
>> next_job);
>> + else if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
>> ts = next_job->submit_ts;
>> else
>> ts = drm_sched_rq_get_rr_deadline(rq);
>> diff --git a/include/drm/gpu_scheduler.h
>> b/include/drm/gpu_scheduler.h
>> index 6fee85e45d45..7532071fbea8 100644
>> --- a/include/drm/gpu_scheduler.h
>> +++ b/include/drm/gpu_scheduler.h
>> @@ -74,8 +74,9 @@ enum drm_sched_priority {
>> /* Used to choose between FIFO and RR job-scheduling */
>> extern int drm_sched_policy;
>>
>> -#define DRM_SCHED_POLICY_RR 0
>> -#define DRM_SCHED_POLICY_FIFO 1
>> +#define DRM_SCHED_POLICY_RR 0
>> +#define DRM_SCHED_POLICY_FIFO 1
>> +#define DRM_SCHED_POLICY_DEADLINE 2
>>
>> /**
>> * struct drm_sched_entity - A wrapper around a job queue (typically
>> @@ -153,6 +154,8 @@ struct drm_sched_entity {
>> */
>> struct spsc_queue job_queue;
>>
>> + enum drm_sched_priority rq_priority;
>> +
>> /**
>> * @fence_seq:
>> *
>> @@ -522,6 +525,7 @@ struct drm_gpu_scheduler {
>> long timeout;
>> const char *name;
>> u32 num_rqs;
>> + u32 num_user_rqs;
>> struct drm_sched_rq **sched_rq;
>> wait_queue_head_t job_scheduled;
>> atomic64_t job_id_count;
>> @@ -623,6 +627,8 @@ void drm_sched_entity_set_priority(struct
>> drm_sched_entity *entity,
>> enum drm_sched_priority
>> priority);
>> bool drm_sched_entity_is_ready(struct drm_sched_entity *entity);
>> int drm_sched_entity_error(struct drm_sched_entity *entity);
>> +ktime_t drm_sched_entity_get_job_deadline(struct drm_sched_entity
>> *entity,
>> + struct drm_sched_job
>> *job);
>>
>> struct drm_sched_fence *drm_sched_fence_alloc(
>> struct drm_sched_entity *s_entity, void *owner);
>
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 08/14] drm/sched: Add deadline policy
2025-01-03 12:40 ` Tvrtko Ursulin
@ 2025-01-03 12:59 ` Philipp Stanner
2025-01-03 15:11 ` Tvrtko Ursulin
0 siblings, 1 reply; 61+ messages in thread
From: Philipp Stanner @ 2025-01-03 12:59 UTC (permalink / raw)
To: Tvrtko Ursulin, Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Christian König, Danilo Krummrich, Matthew Brost
On Fri, 2025-01-03 at 12:40 +0000, Tvrtko Ursulin wrote:
>
> On 02/01/2025 13:11, Philipp Stanner wrote:
> > On Mon, 2024-12-30 at 16:52 +0000, Tvrtko Ursulin wrote:
> > > From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> > >
> > > Deadline scheduling policy should be a fairer flavour of FIFO
> > > with
> > > two
> > > main advantages being that it can naturally connect with the dma-
> > > fence
> > > deadlines, and secondly that it can get away with multiple run
> > > queues
> > > per
> > > scheduler.
> > >
> > > From the latter comes the fairness advantage. Where the current
> > > FIFO
> > > policy will always starve low priority entities by normal, and
> > > normal
> > > by high etc, deadline tracks all runnable entities in a single
> > > run
> > > queue
> > > and assigns them deadlines based on priority. Instead of being
> > > ordered
> > > strictly by priority, jobs and entities become ordered by
> > > deadlines.
> > >
> > > This means that a later higher priority submission can still
> > > overtake
> > > an
> > > earlier lower priority one, but eventually the lower priority
> > > will
> > > get its
> > > turn even if high priority is constantly feeding new work.
> >
> > So, as you're aware of, this is a major change in behavior. FIFO's
> > purpose actually is to be unfair, and my understanding has always
> > been
> > that it is on purpose that the higher priority will with absolute
> > certainty take precedence.
> >
> > Reason being that on the high priority things like configuring
> > memory /
> > mappings are done, which you want to be prioritized.
>
> Right. For the kernel priority for instance I could make them get a
> very
> early deadline ensuring they still run first.
That definitely sounds reasonable to me.
I saw that you already gave the kernel quite a low deadline value.
>
> > IOW in which scenario would you want the low priorities to be able
> > to
> > overtake the higher ones?
>
> I would say always. I don't see it as overtaking but avoiding
> complete
> starvation. In the CPU world if you run:
>
> $ game & nice computation
>
> You don't expect the computation to get zero CPU time while the game
> is
> running.
I expect exactly that *if* game is scheduled with SCHED_FIFO :)
That's why the process scheduler also has SCHED_DEADLINE since a few
years, to address basically exactly the problem you're addressing here
>
> Although I am not saying with the current DRM scheduler it is
> guaranteed
> to get zero GPU time. It will still get scheduled in cases when the
> priority run queues happen to be temporarily empty. But if someone
> would
> be submitting work very efficiently low priority would never run.
>
> Deadline in its current form is not perfect or immune to all
> submission
> patterns either, which is why this is RFC.
Will have to think about that, thx.
I'd definitely be more interested in why the priority levels were
exposed to userspace and what applications most typically do with them.
As you're describing it it sounds as if they're not intending to use it
like in the classic process scheduler with SCHED_FIFO, but that they
are more on the default (SCHED_OTHER) and are trying to set the
*niceness*
P.
>
> > @Danilo, @Christian?
> >
> >
> > >
> > > Current mapping of priority to deadlines is somewhat arbitrary
> > > and
> > > looks
> > > like this (submit timestamp plus constant offset in micro-
> > > seconds):
> > >
> > > static const unsigned int d_us[] = {
> > > [DRM_SCHED_PRIORITY_KERNEL] = 100,
> > > [DRM_SCHED_PRIORITY_HIGH] = 1000,
> > > [DRM_SCHED_PRIORITY_NORMAL] = 5000,
> > > [DRM_SCHED_PRIORITY_LOW] = 100000,
> > > };
> > >
> > > Assuming simultaneous submission of one normal and one low
> > > prioriy
> > > job at
> > > a time of "t", they will get respective deadlines of t+5ms and
> > > t+100ms.
> > > Hence normal will run first and low will run after it, or at the
> > > latest
> > > 100ms after it was submitted in case other higher priority
> > > submissions
> > > overtake it in the meantime.
> > >
> > > Because deadline policy does not need run queues, if the FIFO and
> > > RR
> > > polices are later removed, that would allow for a significant
> > > simplification of the code base by reducing the 1:N to 1:1
> > > scheduler
> > > to run queue relationship.
> >
> > So the proposed upsides for the rework are that a) code can
> > arguably be
> > simplified and that b) deadline is fairer than FIFO.
> >
> > Focusing on b) right now: Have you seen it in the wild that high
> > priorities starve lower ones? Is that a problem already?
> >
> > I assume you have been working on that for a reason – do you have a
> > usecase in amdgpu or similar where the deadline policy improves
> > things
> > in a way?
>
> I don't have any observed use cases as of right now. It is an
> experiment
> to see if we can make the code simpler without adding regressions and
> improvements would be a bonus.
>
> Hence the RFC and even RFT on top because I am looking for a) some
> ideas
> on what and how to test, b) because different drivers use the
> scheduler
> differently and I cannot try them all, seeing if there is interest
> from
> people to try it out and provide feedback.
>
> (I had a more drastic version where deadlines were based on runnable
> status (after dependencies were resolved). That version showed
> significantly lower scheduling jitter but was unstable becuase I took
> too many shortcuts to sketch it out. I don't think it is feasible
> without a much larger rewrite.)
>
> Regards,
>
> Tvrtko
>
> > > Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> > > Cc: Christian König <christian.koenig@amd.com>
> > > Cc: Danilo Krummrich <dakr@redhat.com>
> > > Cc: Matthew Brost <matthew.brost@intel.com>
> > > Cc: Philipp Stanner <pstanner@redhat.com>
> > > ---
> > > drivers/gpu/drm/scheduler/sched_entity.c | 53
> > > +++++++++++++++++++---
> > > --
> > > drivers/gpu/drm/scheduler/sched_main.c | 14 ++++---
> > > drivers/gpu/drm/scheduler/sched_rq.c | 5 ++-
> > > include/drm/gpu_scheduler.h | 10 ++++-
> > > 4 files changed, 64 insertions(+), 18 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/scheduler/sched_entity.c
> > > b/drivers/gpu/drm/scheduler/sched_entity.c
> > > index 608bc43ff256..6928ec19ec23 100644
> > > --- a/drivers/gpu/drm/scheduler/sched_entity.c
> > > +++ b/drivers/gpu/drm/scheduler/sched_entity.c
> > > @@ -71,6 +71,8 @@ int drm_sched_entity_init(struct
> > > drm_sched_entity
> > > *entity,
> > > entity->guilty = guilty;
> > > entity->num_sched_list = num_sched_list;
> > > entity->priority = priority;
> > > + entity->rq_priority = drm_sched_policy ==
> > > DRM_SCHED_POLICY_DEADLINE ?
> > > + DRM_SCHED_PRIORITY_KERNEL :
> > > priority;
> > > /*
> > > * It's perfectly valid to initialize an entity without
> > > having a valid
> > > * scheduler attached. It's just not valid to use the
> > > scheduler before it
> > > @@ -87,17 +89,23 @@ int drm_sched_entity_init(struct
> > > drm_sched_entity
> > > *entity,
> > > */
> > > pr_warn("%s: called with uninitialized
> > > scheduler\n",
> > > __func__);
> > > } else if (num_sched_list) {
> > > - /* The "priority" of an entity cannot exceed the
> > > number of run-queues of a
> > > - * scheduler. Protect against num_rqs being 0,
> > > by
> > > converting to signed. Choose
> > > - * the lowest priority available.
> > > + enum drm_sched_priority p = entity->priority;
> > > +
> > > + /*
> > > + * The "priority" of an entity cannot exceed the
> > > number of
> > > + * run-queues of a scheduler. Protect against
> > > num_rqs being 0,
> > > + * by converting to signed. Choose the lowest
> > > priority
> > > + * available.
> > > */
> > > - if (entity->priority >= sched_list[0]->num_rqs)
> > > {
> > > - drm_err(sched_list[0], "entity with out-
> > > of-
> > > bounds priority:%u num_rqs:%u\n",
> > > - entity->priority, sched_list[0]-
> > > > num_rqs);
> > > - entity->priority = max_t(s32, (s32)
> > > sched_list[0]->num_rqs - 1,
> > > - (s32)
> > > DRM_SCHED_PRIORITY_KERNEL);
> > > + if (p >= sched_list[0]->num_user_rqs) {
> > > + drm_err(sched_list[0], "entity with out-
> > > of-
> > > bounds priority:%u num_user_rqs:%u\n",
> > > + p, sched_list[0]->num_user_rqs);
> > > + p = max_t(s32,
> > > + (s32)sched_list[0]-
> > > >num_user_rqs -
> > > 1,
> > > +
> > > (s32)DRM_SCHED_PRIORITY_KERNEL);
> > > + entity->priority = p;
> > > }
> > > - entity->rq = sched_list[0]->sched_rq[entity-
> > > > priority];
> > > + entity->rq = sched_list[0]->sched_rq[entity-
> > > > rq_priority];
> > > }
> > >
> > > init_completion(&entity->entity_idle);
> > > @@ -377,6 +385,27 @@ void drm_sched_entity_set_priority(struct
> > > drm_sched_entity *entity,
> > > }
> > > EXPORT_SYMBOL(drm_sched_entity_set_priority);
> > >
> > > +static ktime_t
> > > +__drm_sched_entity_get_job_deadline(struct drm_sched_entity
> > > *entity,
> > > + ktime_t submit_ts)
> > > +{
> > > + static const unsigned int d_us[] = {
> > > + [DRM_SCHED_PRIORITY_KERNEL] = 100,
> > > + [DRM_SCHED_PRIORITY_HIGH] = 1000,
> > > + [DRM_SCHED_PRIORITY_NORMAL] = 5000,
> > > + [DRM_SCHED_PRIORITY_LOW] = 100000,
> > > + };
> > > +
> > > + return ktime_add_us(submit_ts, d_us[entity->priority]);
> > > +}
> > > +
> > > +ktime_t
> > > +drm_sched_entity_get_job_deadline(struct drm_sched_entity
> > > *entity,
> > > + struct drm_sched_job *job)
> > > +{
> > > + return __drm_sched_entity_get_job_deadline(entity, job-
> > > > submit_ts);
> > > +}
> > > +
> > > /*
> > > * drm_sched_entity_wakeup - callback to clear the entity's
> > > dependency and
> > > * wake up the scheduler
> > > @@ -503,7 +532,7 @@ void drm_sched_entity_select_rq(struct
> > > drm_sched_entity *entity)
> > >
> > > spin_lock(&entity->lock);
> > > sched = drm_sched_pick_best(entity->sched_list, entity-
> > > > num_sched_list);
> > > - rq = sched ? sched->sched_rq[entity->priority] : NULL;
> > > + rq = sched ? sched->sched_rq[entity->rq_priority] :
> > > NULL;
> > > if (rq != entity->rq) {
> > > drm_sched_rq_remove_entity(entity->rq, entity);
> > > entity->rq = rq;
> > > @@ -547,6 +576,10 @@ void drm_sched_entity_push_job(struct
> > > drm_sched_job *sched_job)
> > > if (first) {
> > > struct drm_gpu_scheduler *sched;
> > >
> > > + if (drm_sched_policy ==
> > > DRM_SCHED_POLICY_DEADLINE)
> > > + submit_ts =
> > > __drm_sched_entity_get_job_deadline(entity,
> > > +
> > > submit_ts);
> > > +
> > > sched = drm_sched_rq_add_entity(entity->rq,
> > > entity,
> > > submit_ts);
> > > if (sched)
> > > drm_sched_wakeup(sched);
> > > diff --git a/drivers/gpu/drm/scheduler/sched_main.c
> > > b/drivers/gpu/drm/scheduler/sched_main.c
> > > index ba9b0274b185..433bef85eeaf 100644
> > > --- a/drivers/gpu/drm/scheduler/sched_main.c
> > > +++ b/drivers/gpu/drm/scheduler/sched_main.c
> > > @@ -87,13 +87,13 @@ static struct lockdep_map
> > > drm_sched_lockdep_map =
> > > {
> > > };
> > > #endif
> > >
> > > -int drm_sched_policy = DRM_SCHED_POLICY_FIFO;
> > > +int drm_sched_policy = DRM_SCHED_POLICY_DEADLINE;
> > >
> > > /**
> > > * DOC: sched_policy (int)
> > > * Used to override default entities scheduling policy in a run
> > > queue.
> > > */
> > > -MODULE_PARM_DESC(sched_policy, "Specify the scheduling policy
> > > for
> > > entities on a run-queue, " __stringify(DRM_SCHED_POLICY_RR) " =
> > > Round
> > > Robin, " __stringify(DRM_SCHED_POLICY_FIFO) " = FIFO
> > > (default).");
> > > +MODULE_PARM_DESC(sched_policy, "Specify the scheduling policy
> > > for
> > > entities on a run-queue, " __stringify(DRM_SCHED_POLICY_RR) " =
> > > Round
> > > Robin, " __stringify(DRM_SCHED_POLICY_FIFO) " = FIFO, "
> > > __stringify(DRM_SCHED_POLICY_DEADLINE) " = Virtual deadline
> > > (default).");
> > > module_param_named(sched_policy, drm_sched_policy, int, 0444);
> > >
> > > static u32 drm_sched_available_credits(struct drm_gpu_scheduler
> > > *sched)
> > > @@ -1109,11 +1109,15 @@ int drm_sched_init(struct
> > > drm_gpu_scheduler
> > > *sched,
> > > sched->own_submit_wq = true;
> > > }
> > >
> > > - sched->sched_rq = kmalloc_array(num_rqs, sizeof(*sched-
> > > > sched_rq),
> > > + sched->num_user_rqs = num_rqs;
> > > + sched->num_rqs = drm_sched_policy !=
> > > DRM_SCHED_POLICY_DEADLINE ?
> > > + num_rqs : 1;
> > > + sched->sched_rq = kmalloc_array(sched->num_rqs,
> > > + sizeof(*sched-
> > > >sched_rq),
> > > GFP_KERNEL |
> > > __GFP_ZERO);
> > > if (!sched->sched_rq)
> > > goto Out_check_own;
> > > - sched->num_rqs = num_rqs;
> > > +
> > > for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs;
> > > i++)
> > > {
> > > sched->sched_rq[i] = kzalloc(sizeof(*sched-
> > > > sched_rq[i]), GFP_KERNEL);
> > > if (!sched->sched_rq[i])
> > > @@ -1227,7 +1231,7 @@ void drm_sched_increase_karma(struct
> > > drm_sched_job *bad)
> > > if (bad->s_priority != DRM_SCHED_PRIORITY_KERNEL) {
> > > atomic_inc(&bad->karma);
> > >
> > > - for (i = DRM_SCHED_PRIORITY_HIGH; i < sched-
> > > > num_rqs; i++) {
> > > + for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched-
> > > > num_rqs; i++) {
> > > struct drm_sched_rq *rq = sched-
> > > > sched_rq[i];
> > >
> > > spin_lock(&rq->lock);
> > > diff --git a/drivers/gpu/drm/scheduler/sched_rq.c
> > > b/drivers/gpu/drm/scheduler/sched_rq.c
> > > index 5b31e5434d12..a6bb21250350 100644
> > > --- a/drivers/gpu/drm/scheduler/sched_rq.c
> > > +++ b/drivers/gpu/drm/scheduler/sched_rq.c
> > > @@ -152,7 +152,10 @@ void drm_sched_rq_pop_entity(struct
> > > drm_sched_rq
> > > *rq,
> > > if (next_job) {
> > > ktime_t ts;
> > >
> > > - if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
> > > + if (drm_sched_policy ==
> > > DRM_SCHED_POLICY_DEADLINE)
> > > + ts =
> > > drm_sched_entity_get_job_deadline(entity,
> > > +
> > > next_job);
> > > + else if (drm_sched_policy ==
> > > DRM_SCHED_POLICY_FIFO)
> > > ts = next_job->submit_ts;
> > > else
> > > ts = drm_sched_rq_get_rr_deadline(rq);
> > > diff --git a/include/drm/gpu_scheduler.h
> > > b/include/drm/gpu_scheduler.h
> > > index 6fee85e45d45..7532071fbea8 100644
> > > --- a/include/drm/gpu_scheduler.h
> > > +++ b/include/drm/gpu_scheduler.h
> > > @@ -74,8 +74,9 @@ enum drm_sched_priority {
> > > /* Used to choose between FIFO and RR job-scheduling */
> > > extern int drm_sched_policy;
> > >
> > > -#define DRM_SCHED_POLICY_RR 0
> > > -#define DRM_SCHED_POLICY_FIFO 1
> > > +#define DRM_SCHED_POLICY_RR 0
> > > +#define DRM_SCHED_POLICY_FIFO 1
> > > +#define DRM_SCHED_POLICY_DEADLINE 2
> > >
> > > /**
> > > * struct drm_sched_entity - A wrapper around a job queue
> > > (typically
> > > @@ -153,6 +154,8 @@ struct drm_sched_entity {
> > > */
> > > struct spsc_queue job_queue;
> > >
> > > + enum drm_sched_priority rq_priority;
> > > +
> > > /**
> > > * @fence_seq:
> > > *
> > > @@ -522,6 +525,7 @@ struct drm_gpu_scheduler {
> > > long timeout;
> > > const char *name;
> > > u32 num_rqs;
> > > + u32 num_user_rqs;
> > > struct drm_sched_rq **sched_rq;
> > > wait_queue_head_t job_scheduled;
> > > atomic64_t job_id_count;
> > > @@ -623,6 +627,8 @@ void drm_sched_entity_set_priority(struct
> > > drm_sched_entity *entity,
> > > enum drm_sched_priority
> > > priority);
> > > bool drm_sched_entity_is_ready(struct drm_sched_entity
> > > *entity);
> > > int drm_sched_entity_error(struct drm_sched_entity *entity);
> > > +ktime_t drm_sched_entity_get_job_deadline(struct
> > > drm_sched_entity
> > > *entity,
> > > + struct drm_sched_job
> > > *job);
> > >
> > > struct drm_sched_fence *drm_sched_fence_alloc(
> > > struct drm_sched_entity *s_entity, void *owner);
> >
>
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 08/14] drm/sched: Add deadline policy
2025-01-03 12:59 ` Philipp Stanner
@ 2025-01-03 15:11 ` Tvrtko Ursulin
0 siblings, 0 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-03 15:11 UTC (permalink / raw)
To: Philipp Stanner, Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Christian König, Danilo Krummrich, Matthew Brost
On 03/01/2025 12:59, Philipp Stanner wrote:
> On Fri, 2025-01-03 at 12:40 +0000, Tvrtko Ursulin wrote:
>>
>> On 02/01/2025 13:11, Philipp Stanner wrote:
>>> On Mon, 2024-12-30 at 16:52 +0000, Tvrtko Ursulin wrote:
>>>> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>>>>
>>>> Deadline scheduling policy should be a fairer flavour of FIFO
>>>> with
>>>> two
>>>> main advantages being that it can naturally connect with the dma-
>>>> fence
>>>> deadlines, and secondly that it can get away with multiple run
>>>> queues
>>>> per
>>>> scheduler.
>>>>
>>>> From the latter comes the fairness advantage. Where the current
>>>> FIFO
>>>> policy will always starve low priority entities by normal, and
>>>> normal
>>>> by high etc, deadline tracks all runnable entities in a single
>>>> run
>>>> queue
>>>> and assigns them deadlines based on priority. Instead of being
>>>> ordered
>>>> strictly by priority, jobs and entities become ordered by
>>>> deadlines.
>>>>
>>>> This means that a later higher priority submission can still
>>>> overtake
>>>> an
>>>> earlier lower priority one, but eventually the lower priority
>>>> will
>>>> get its
>>>> turn even if high priority is constantly feeding new work.
>>>
>>> So, as you're aware of, this is a major change in behavior. FIFO's
>>> purpose actually is to be unfair, and my understanding has always
>>> been
>>> that it is on purpose that the higher priority will with absolute
>>> certainty take precedence.
>>>
>>> Reason being that on the high priority things like configuring
>>> memory /
>>> mappings are done, which you want to be prioritized.
>>
>> Right. For the kernel priority for instance I could make them get a
>> very
>> early deadline ensuring they still run first.
>
> That definitely sounds reasonable to me.
> I saw that you already gave the kernel quite a low deadline value.
>
>>
>>> IOW in which scenario would you want the low priorities to be able
>>> to
>>> overtake the higher ones?
>>
>> I would say always. I don't see it as overtaking but avoiding
>> complete
>> starvation. In the CPU world if you run:
>>
>> $ game & nice computation
>>
>> You don't expect the computation to get zero CPU time while the game
>> is
>> running.
>
> I expect exactly that *if* game is scheduled with SCHED_FIFO :)
:))
> That's why the process scheduler also has SCHED_DEADLINE since a few
> years, to address basically exactly the problem you're addressing he >
>> Although I am not saying with the current DRM scheduler it is
>> guaranteed
>> to get zero GPU time. It will still get scheduled in cases when the
>> priority run queues happen to be temporarily empty. But if someone
>> would
>> be submitting work very efficiently low priority would never run.
>>
>> Deadline in its current form is not perfect or immune to all
>> submission
>> patterns either, which is why this is RFC.
>
> Will have to think about that, thx.
>
> I'd definitely be more interested in why the priority levels were
> exposed to userspace and what applications most typically do with them.
EGL_IMG_context_priority and VK_KHR_global_priority. But both are just
hints and definitely do not prescribe or require SCHED_FIFO like behaviour.
> As you're describing it it sounds as if they're not intending to use it
> like in the classic process scheduler with SCHED_FIFO, but that they
> are more on the default (SCHED_OTHER) and are trying to set the
> *niceness*
Yes exactly. I don't think DRM scheduler _needs_ to be like SCHED_FIFO.
More like SCHED_OTHER would I think work better if we were to (finally)
expose some external control (see
https://blogs.igalia.com/tursulin/drm-scheduling-cgroup-controller/ for
one related example).
Regards,
Tvrtko
^ permalink raw reply [flat|nested] 61+ messages in thread
* [RFC 09/14] drm/sched: Remove FIFO and RR and simplify to a single run queue
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
` (7 preceding siblings ...)
2024-12-30 16:52 ` [RFC 08/14] drm/sched: Add deadline policy Tvrtko Ursulin
@ 2024-12-30 16:52 ` Tvrtko Ursulin
2024-12-30 16:52 ` [RFC 10/14] drm/sched: Queue all free credits in one worker invocation Tvrtko Ursulin
` (8 subsequent siblings)
17 siblings, 0 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2024-12-30 16:52 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
If the new deadline policy is at least as good as FIFO and we can afford
to remove round-robin, we can simplify the scheduler code by making the
scheduler to run queue relationship always 1:1 and remove some code.
Also, now that the FIFO policy is gone the tree of entities is not a FIFO
tree any more so rename it to just the tree.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <pstanner@redhat.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 23 ++--
drivers/gpu/drm/scheduler/sched_entity.c | 30 +----
drivers/gpu/drm/scheduler/sched_main.c | 136 ++++++-----------------
drivers/gpu/drm/scheduler/sched_rq.c | 35 ++----
include/drm/gpu_scheduler.h | 13 +--
5 files changed, 56 insertions(+), 181 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index b9d08bc96581..918b6d4919e1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -418,25 +418,22 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job)
void amdgpu_job_stop_all_jobs_on_sched(struct drm_gpu_scheduler *sched)
{
+ struct drm_sched_rq *rq = sched->rq;
+ struct drm_sched_entity *s_entity;
struct drm_sched_job *s_job;
- struct drm_sched_entity *s_entity = NULL;
- int i;
/* Signal all jobs not yet scheduled */
- for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) {
- struct drm_sched_rq *rq = sched->sched_rq[i];
- spin_lock(&rq->lock);
- list_for_each_entry(s_entity, &rq->entities, list) {
- while ((s_job = to_drm_sched_job(spsc_queue_pop(&s_entity->job_queue)))) {
- struct drm_sched_fence *s_fence = s_job->s_fence;
+ spin_lock(&rq->lock);
+ list_for_each_entry(s_entity, &rq->entities, list) {
+ while ((s_job = to_drm_sched_job(spsc_queue_pop(&s_entity->job_queue)))) {
+ struct drm_sched_fence *s_fence = s_job->s_fence;
- dma_fence_signal(&s_fence->scheduled);
- dma_fence_set_error(&s_fence->finished, -EHWPOISON);
- dma_fence_signal(&s_fence->finished);
- }
+ dma_fence_signal(&s_fence->scheduled);
+ dma_fence_set_error(&s_fence->finished, -EHWPOISON);
+ dma_fence_signal(&s_fence->finished);
}
- spin_unlock(&rq->lock);
}
+ spin_unlock(&rq->lock);
/* Signal all jobs already scheduled to HW */
list_for_each_entry(s_job, &sched->pending_list, list) {
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index 6928ec19ec23..14bc3f797079 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -71,8 +71,6 @@ int drm_sched_entity_init(struct drm_sched_entity *entity,
entity->guilty = guilty;
entity->num_sched_list = num_sched_list;
entity->priority = priority;
- entity->rq_priority = drm_sched_policy == DRM_SCHED_POLICY_DEADLINE ?
- DRM_SCHED_PRIORITY_KERNEL : priority;
/*
* It's perfectly valid to initialize an entity without having a valid
* scheduler attached. It's just not valid to use the scheduler before it
@@ -82,30 +80,14 @@ int drm_sched_entity_init(struct drm_sched_entity *entity,
RCU_INIT_POINTER(entity->last_scheduled, NULL);
RB_CLEAR_NODE(&entity->rb_tree_node);
- if (num_sched_list && !sched_list[0]->sched_rq) {
+ if (num_sched_list && !sched_list[0]->rq) {
/* Since every entry covered by num_sched_list
* should be non-NULL and therefore we warn drivers
* not to do this and to fix their DRM calling order.
*/
pr_warn("%s: called with uninitialized scheduler\n", __func__);
} else if (num_sched_list) {
- enum drm_sched_priority p = entity->priority;
-
- /*
- * The "priority" of an entity cannot exceed the number of
- * run-queues of a scheduler. Protect against num_rqs being 0,
- * by converting to signed. Choose the lowest priority
- * available.
- */
- if (p >= sched_list[0]->num_user_rqs) {
- drm_err(sched_list[0], "entity with out-of-bounds priority:%u num_user_rqs:%u\n",
- p, sched_list[0]->num_user_rqs);
- p = max_t(s32,
- (s32)sched_list[0]->num_user_rqs - 1,
- (s32)DRM_SCHED_PRIORITY_KERNEL);
- entity->priority = p;
- }
- entity->rq = sched_list[0]->sched_rq[entity->rq_priority];
+ entity->rq = sched_list[0]->rq;
}
init_completion(&entity->entity_idle);
@@ -532,7 +514,7 @@ void drm_sched_entity_select_rq(struct drm_sched_entity *entity)
spin_lock(&entity->lock);
sched = drm_sched_pick_best(entity->sched_list, entity->num_sched_list);
- rq = sched ? sched->sched_rq[entity->rq_priority] : NULL;
+ rq = sched ? sched->rq : NULL;
if (rq != entity->rq) {
drm_sched_rq_remove_entity(entity->rq, entity);
entity->rq = rq;
@@ -576,10 +558,8 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
if (first) {
struct drm_gpu_scheduler *sched;
- if (drm_sched_policy == DRM_SCHED_POLICY_DEADLINE)
- submit_ts = __drm_sched_entity_get_job_deadline(entity,
- submit_ts);
-
+ submit_ts = __drm_sched_entity_get_job_deadline(entity,
+ submit_ts);
sched = drm_sched_rq_add_entity(entity->rq, entity, submit_ts);
if (sched)
drm_sched_wakeup(sched);
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index 433bef85eeaf..4ba9ed27a8a6 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -87,15 +87,6 @@ static struct lockdep_map drm_sched_lockdep_map = {
};
#endif
-int drm_sched_policy = DRM_SCHED_POLICY_DEADLINE;
-
-/**
- * DOC: sched_policy (int)
- * Used to override default entities scheduling policy in a run queue.
- */
-MODULE_PARM_DESC(sched_policy, "Specify the scheduling policy for entities on a run-queue, " __stringify(DRM_SCHED_POLICY_RR) " = Round Robin, " __stringify(DRM_SCHED_POLICY_FIFO) " = FIFO, " __stringify(DRM_SCHED_POLICY_DEADLINE) " = Virtual deadline (default).");
-module_param_named(sched_policy, drm_sched_policy, int, 0444);
-
static u32 drm_sched_available_credits(struct drm_gpu_scheduler *sched)
{
u32 credits;
@@ -850,34 +841,6 @@ void drm_sched_wakeup(struct drm_gpu_scheduler *sched)
drm_sched_run_job_queue(sched);
}
-/**
- * drm_sched_select_entity - Select next entity to process
- *
- * @sched: scheduler instance
- *
- * Return an entity to process or NULL if none are found.
- *
- * Note, that we break out of the for-loop when "entity" is non-null, which can
- * also be an error-pointer--this assures we don't process lower priority
- * run-queues. See comments in the respectively called functions.
- */
-static struct drm_sched_entity *
-drm_sched_select_entity(struct drm_gpu_scheduler *sched)
-{
- struct drm_sched_entity *entity = NULL;
- int i;
-
- /* Start with the highest priority.
- */
- for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) {
- entity = drm_sched_rq_select_entity(sched, sched->sched_rq[i]);
- if (entity)
- break;
- }
-
- return IS_ERR(entity) ? NULL : entity;;
-}
-
/**
* drm_sched_get_finished_job - fetch the next finished job to be destroyed
*
@@ -1000,8 +963,8 @@ static void drm_sched_run_job_work(struct work_struct *w)
return;
/* Find entity with a ready job */
- entity = drm_sched_select_entity(sched);
- if (!entity)
+ entity = drm_sched_rq_select_entity(sched, sched->rq);
+ if (IS_ERR_OR_NULL(entity))
return; /* No more work */
sched_job = drm_sched_entity_pop_job(entity);
@@ -1047,7 +1010,7 @@ static void drm_sched_run_job_work(struct work_struct *w)
* @ops: backend operations for this scheduler
* @submit_wq: workqueue to use for submission. If NULL, an ordered wq is
* allocated and used
- * @num_rqs: number of runqueues, one for each priority, up to DRM_SCHED_PRIORITY_COUNT
+ * @num_rqs: deprecated and ignored
* @credit_limit: the number of credits this scheduler can hold from all jobs
* @hang_limit: number of times to allow a job to hang before dropping it
* @timeout: timeout value in jiffies for the scheduler
@@ -1066,8 +1029,6 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
long timeout, struct workqueue_struct *timeout_wq,
atomic_t *score, const char *name, struct device *dev)
{
- int i;
-
sched->ops = ops;
sched->credit_limit = credit_limit;
sched->name = name;
@@ -1077,13 +1038,7 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
sched->score = score ? score : &sched->_score;
sched->dev = dev;
- if (num_rqs > DRM_SCHED_PRIORITY_COUNT) {
- /* This is a gross violation--tell drivers what the problem is.
- */
- drm_err(sched, "%s: num_rqs cannot be greater than DRM_SCHED_PRIORITY_COUNT\n",
- __func__);
- return -EINVAL;
- } else if (sched->sched_rq) {
+ if (sched->rq) {
/* Not an error, but warn anyway so drivers can
* fine-tune their DRM calling order, and return all
* is good.
@@ -1109,21 +1064,11 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
sched->own_submit_wq = true;
}
- sched->num_user_rqs = num_rqs;
- sched->num_rqs = drm_sched_policy != DRM_SCHED_POLICY_DEADLINE ?
- num_rqs : 1;
- sched->sched_rq = kmalloc_array(sched->num_rqs,
- sizeof(*sched->sched_rq),
- GFP_KERNEL | __GFP_ZERO);
- if (!sched->sched_rq)
+ sched->rq = kmalloc(sizeof(*sched->rq), GFP_KERNEL | __GFP_ZERO);
+ if (!sched->rq)
goto Out_check_own;
- for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) {
- sched->sched_rq[i] = kzalloc(sizeof(*sched->sched_rq[i]), GFP_KERNEL);
- if (!sched->sched_rq[i])
- goto Out_unroll;
- drm_sched_rq_init(sched, sched->sched_rq[i]);
- }
+ drm_sched_rq_init(sched, sched->rq);
init_waitqueue_head(&sched->job_scheduled);
INIT_LIST_HEAD(&sched->pending_list);
@@ -1135,15 +1080,9 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
atomic_set(&sched->_score, 0);
atomic64_set(&sched->job_id_count, 0);
sched->pause_submit = false;
-
sched->ready = true;
return 0;
-Out_unroll:
- for (--i ; i >= DRM_SCHED_PRIORITY_KERNEL; i--)
- kfree(sched->sched_rq[i]);
- kfree(sched->sched_rq);
- sched->sched_rq = NULL;
Out_check_own:
if (sched->own_submit_wq)
destroy_workqueue(sched->submit_wq);
@@ -1174,25 +1113,21 @@ EXPORT_SYMBOL(drm_sched_init);
*/
void drm_sched_fini(struct drm_gpu_scheduler *sched)
{
+
+ struct drm_sched_rq *rq = sched->rq;
struct drm_sched_entity *s_entity;
- int i;
drm_sched_wqueue_stop(sched);
- for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) {
- struct drm_sched_rq *rq = sched->sched_rq[i];
-
- spin_lock(&rq->lock);
- list_for_each_entry(s_entity, &rq->entities, list)
- /*
- * Prevents reinsertion and marks job_queue as idle,
- * it will be removed from the rq in drm_sched_entity_fini()
- * eventually
- */
- s_entity->stopped = true;
- spin_unlock(&rq->lock);
- kfree(sched->sched_rq[i]);
- }
+ spin_lock(&rq->lock);
+ list_for_each_entry(s_entity, &rq->entities, list)
+ /*
+ * Prevents reinsertion and marks job_queue as idle,
+ * it will be removed from the rq in drm_sched_entity_fini()
+ * eventually
+ */
+ s_entity->stopped = true;
+ spin_unlock(&rq->lock);
/* Wakeup everyone stuck in drm_sched_entity_flush for this scheduler */
wake_up_all(&sched->job_scheduled);
@@ -1203,8 +1138,8 @@ void drm_sched_fini(struct drm_gpu_scheduler *sched)
if (sched->own_submit_wq)
destroy_workqueue(sched->submit_wq);
sched->ready = false;
- kfree(sched->sched_rq);
- sched->sched_rq = NULL;
+ kfree(sched->rq);
+ sched->rq = NULL;
}
EXPORT_SYMBOL(drm_sched_fini);
@@ -1219,35 +1154,28 @@ EXPORT_SYMBOL(drm_sched_fini);
*/
void drm_sched_increase_karma(struct drm_sched_job *bad)
{
- int i;
- struct drm_sched_entity *tmp;
- struct drm_sched_entity *entity;
struct drm_gpu_scheduler *sched = bad->sched;
+ struct drm_sched_entity *entity, *tmp;
+ struct drm_sched_rq *rq = sched->rq;
/* don't change @bad's karma if it's from KERNEL RQ,
* because sometimes GPU hang would cause kernel jobs (like VM updating jobs)
* corrupt but keep in mind that kernel jobs always considered good.
*/
- if (bad->s_priority != DRM_SCHED_PRIORITY_KERNEL) {
- atomic_inc(&bad->karma);
+ if (bad->s_priority == DRM_SCHED_PRIORITY_KERNEL)
+ return;
- for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) {
- struct drm_sched_rq *rq = sched->sched_rq[i];
+ atomic_inc(&bad->karma);
- spin_lock(&rq->lock);
- list_for_each_entry_safe(entity, tmp, &rq->entities, list) {
- if (bad->s_fence->scheduled.context ==
- entity->fence_context) {
- if (entity->guilty)
- atomic_set(entity->guilty, 1);
- break;
- }
- }
- spin_unlock(&rq->lock);
- if (&entity->list != &rq->entities)
- break;
+ spin_lock(&rq->lock);
+ list_for_each_entry_safe(entity, tmp, &rq->entities, list) {
+ if (bad->s_fence->scheduled.context == entity->fence_context) {
+ if (entity->guilty)
+ atomic_set(entity->guilty, 1);
+ break;
}
}
+ spin_unlock(&rq->lock);
}
EXPORT_SYMBOL(drm_sched_increase_karma);
diff --git a/drivers/gpu/drm/scheduler/sched_rq.c b/drivers/gpu/drm/scheduler/sched_rq.c
index a6bb21250350..0b7a2b8b48db 100644
--- a/drivers/gpu/drm/scheduler/sched_rq.c
+++ b/drivers/gpu/drm/scheduler/sched_rq.c
@@ -12,7 +12,7 @@ static __always_inline bool drm_sched_entity_compare_before(struct rb_node *a,
return ktime_before(ent_a->oldest_job_waiting, ent_b->oldest_job_waiting);
}
-static void __drm_sched_rq_remove_fifo_locked(struct drm_sched_entity *entity,
+static void __drm_sched_rq_remove_tree_locked(struct drm_sched_entity *entity,
struct drm_sched_rq *rq)
{
lockdep_assert_held(&entity->lock);
@@ -22,7 +22,7 @@ static void __drm_sched_rq_remove_fifo_locked(struct drm_sched_entity *entity,
RB_CLEAR_NODE(&entity->rb_tree_node);
}
-static void __drm_sched_rq_add_fifo_locked(struct drm_sched_entity *entity,
+static void __drm_sched_rq_add_tree_locked(struct drm_sched_entity *entity,
struct drm_sched_rq *rq,
ktime_t ts)
{
@@ -56,16 +56,6 @@ void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
rq->sched = sched;
}
-static ktime_t
-drm_sched_rq_get_rr_deadline(struct drm_sched_rq *rq)
-{
- lockdep_assert_held(&rq->lock);
-
- rq->rr_deadline = ktime_add_ns(rq->rr_deadline, 1);
-
- return rq->rr_deadline;
-}
-
/**
* drm_sched_rq_add_entity - add an entity
*
@@ -97,12 +87,9 @@ drm_sched_rq_add_entity(struct drm_sched_rq *rq,
if (!list_empty(&entity->list))
list_add_tail(&entity->list, &rq->entities);
- if (drm_sched_policy == DRM_SCHED_POLICY_RR)
- ts = drm_sched_rq_get_rr_deadline(rq);
-
if (!RB_EMPTY_NODE(&entity->rb_tree_node))
- __drm_sched_rq_remove_fifo_locked(entity, rq);
- __drm_sched_rq_add_fifo_locked(entity, rq, ts);
+ __drm_sched_rq_remove_tree_locked(entity, rq);
+ __drm_sched_rq_add_tree_locked(entity, rq, ts);
spin_unlock(&rq->lock);
spin_unlock(&entity->lock);
@@ -132,7 +119,7 @@ void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
list_del_init(&entity->list);
if (!RB_EMPTY_NODE(&entity->rb_tree_node))
- __drm_sched_rq_remove_fifo_locked(entity, rq);
+ __drm_sched_rq_remove_tree_locked(entity, rq);
spin_unlock(&rq->lock);
}
@@ -147,20 +134,14 @@ void drm_sched_rq_pop_entity(struct drm_sched_rq *rq,
spin_lock(&entity->lock);
spin_lock(&rq->lock);
- __drm_sched_rq_remove_fifo_locked(entity, rq);
+ __drm_sched_rq_remove_tree_locked(entity, rq);
if (next_job) {
ktime_t ts;
- if (drm_sched_policy == DRM_SCHED_POLICY_DEADLINE)
- ts = drm_sched_entity_get_job_deadline(entity,
- next_job);
- else if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
- ts = next_job->submit_ts;
- else
- ts = drm_sched_rq_get_rr_deadline(rq);
+ ts = drm_sched_entity_get_job_deadline(entity, next_job);
- __drm_sched_rq_add_fifo_locked(entity, rq, ts);
+ __drm_sched_rq_add_tree_locked(entity, rq, ts);
}
spin_unlock(&rq->lock);
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index 7532071fbea8..93f6fcfe3ba0 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -71,13 +71,6 @@ enum drm_sched_priority {
DRM_SCHED_PRIORITY_COUNT
};
-/* Used to choose between FIFO and RR job-scheduling */
-extern int drm_sched_policy;
-
-#define DRM_SCHED_POLICY_RR 0
-#define DRM_SCHED_POLICY_FIFO 1
-#define DRM_SCHED_POLICY_DEADLINE 2
-
/**
* struct drm_sched_entity - A wrapper around a job queue (typically
* attached to the DRM file_priv).
@@ -154,8 +147,6 @@ struct drm_sched_entity {
*/
struct spsc_queue job_queue;
- enum drm_sched_priority rq_priority;
-
/**
* @fence_seq:
*
@@ -524,9 +515,7 @@ struct drm_gpu_scheduler {
atomic_t credit_count;
long timeout;
const char *name;
- u32 num_rqs;
- u32 num_user_rqs;
- struct drm_sched_rq **sched_rq;
+ struct drm_sched_rq *rq;
wait_queue_head_t job_scheduled;
atomic64_t job_id_count;
struct workqueue_struct *submit_wq;
--
2.47.1
^ permalink raw reply related [flat|nested] 61+ messages in thread* [RFC 10/14] drm/sched: Queue all free credits in one worker invocation
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
` (8 preceding siblings ...)
2024-12-30 16:52 ` [RFC 09/14] drm/sched: Remove FIFO and RR and simplify to a single run queue Tvrtko Ursulin
@ 2024-12-30 16:52 ` Tvrtko Ursulin
2025-01-07 11:08 ` Tvrtko Ursulin
2024-12-30 16:52 ` [RFC 11/14] drm/sched: Connect with dma-fence deadlines Tvrtko Ursulin
` (7 subsequent siblings)
17 siblings, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2024-12-30 16:52 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
There is no reason to queue just a single job if scheduler can take more
and re-queue the worker to queue more. We can simply feed the hardware
with as much as it can take in one go and hopefully win some latency.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <pstanner@redhat.com>
---
drivers/gpu/drm/scheduler/sched_main.c | 112 +++++++++++--------------
drivers/gpu/drm/scheduler/sched_rq.c | 19 ++---
include/drm/gpu_scheduler.h | 3 -
3 files changed, 58 insertions(+), 76 deletions(-)
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index 4ba9ed27a8a6..6f4ea8a2ca17 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -98,33 +98,6 @@ static u32 drm_sched_available_credits(struct drm_gpu_scheduler *sched)
return credits;
}
-/**
- * drm_sched_can_queue -- Can we queue more to the hardware?
- * @sched: scheduler instance
- * @entity: the scheduler entity
- *
- * Return true if we can push at least one more job from @entity, false
- * otherwise.
- */
-bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
- struct drm_sched_entity *entity)
-{
- struct drm_sched_job *s_job;
-
- s_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
- if (!s_job)
- return false;
-
- /* If a job exceeds the credit limit, truncate it to the credit limit
- * itself to guarantee forward progress.
- */
- if (drm_WARN(sched, s_job->credits > sched->credit_limit,
- "Jobs may not exceed the credit limit, truncate.\n"))
- s_job->credits = sched->credit_limit;
-
- return drm_sched_available_credits(sched) >= s_job->credits;
-}
-
/**
* drm_sched_run_job_queue - enqueue run-job work
* @sched: scheduler instance
@@ -174,6 +147,7 @@ static void drm_sched_job_done(struct drm_sched_job *s_job, int result)
atomic_sub(s_job->credits, &sched->credit_count);
atomic_dec(sched->score);
+ drm_sched_run_job_queue(sched);
trace_drm_sched_process_job(s_fence);
@@ -941,7 +915,6 @@ static void drm_sched_free_job_work(struct work_struct *w)
sched->ops->free_job(job);
drm_sched_run_free_queue(sched);
- drm_sched_run_job_queue(sched);
}
/**
@@ -953,54 +926,71 @@ static void drm_sched_run_job_work(struct work_struct *w)
{
struct drm_gpu_scheduler *sched =
container_of(w, struct drm_gpu_scheduler, work_run_job);
+ u32 job_credits, submitted_credits = 0;
struct drm_sched_entity *entity;
- struct dma_fence *fence;
- struct drm_sched_fence *s_fence;
struct drm_sched_job *sched_job;
- int r;
+ struct dma_fence *fence;
if (READ_ONCE(sched->pause_submit))
return;
- /* Find entity with a ready job */
- entity = drm_sched_rq_select_entity(sched, sched->rq);
- if (IS_ERR_OR_NULL(entity))
- return; /* No more work */
+ for (;;) {
+ /* Find entity with a ready job */
+ entity = drm_sched_rq_select_entity(sched, sched->rq);
+ if (!entity)
+ break; /* No more work */
- sched_job = drm_sched_entity_pop_job(entity);
- if (!sched_job) {
+ /*
+ * If a job exceeds the credit limit truncate it to guarantee
+ * forward progress.
+ */
+ sched_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
+ job_credits = sched_job->credits;
+ if (drm_WARN_ONCE(sched, job_credits > sched->credit_limit,
+ "Jobs may not exceed the credit limit, truncating.\n"))
+ job_credits = sched_job->credits = sched->credit_limit;
+
+ if (job_credits > drm_sched_available_credits(sched)) {
+ complete_all(&entity->entity_idle);
+ break;
+ }
+
+ sched_job = drm_sched_entity_pop_job(entity);
complete_all(&entity->entity_idle);
- drm_sched_run_job_queue(sched);
- return;
- }
+ if (!sched_job) {
+ /* Top entity is not yet runnable after all */
+ continue;
+ }
- s_fence = sched_job->s_fence;
+ drm_sched_job_begin(sched_job);
+ trace_drm_run_job(sched_job, entity);
+ submitted_credits += job_credits;
+ atomic_add(job_credits, &sched->credit_count);
- atomic_add(sched_job->credits, &sched->credit_count);
- drm_sched_job_begin(sched_job);
+ fence = sched->ops->run_job(sched_job);
+ drm_sched_fence_scheduled(sched_job->s_fence, fence);
- trace_drm_run_job(sched_job, entity);
- fence = sched->ops->run_job(sched_job);
- complete_all(&entity->entity_idle);
- drm_sched_fence_scheduled(s_fence, fence);
+ if (!IS_ERR_OR_NULL(fence)) {
+ int r;
- if (!IS_ERR_OR_NULL(fence)) {
- /* Drop for original kref_init of the fence */
- dma_fence_put(fence);
+ /* Drop for original kref_init of the fence */
+ dma_fence_put(fence);
- r = dma_fence_add_callback(fence, &sched_job->cb,
- drm_sched_job_done_cb);
- if (r == -ENOENT)
- drm_sched_job_done(sched_job, fence->error);
- else if (r)
- DRM_DEV_ERROR(sched->dev, "fence add callback failed (%d)\n", r);
- } else {
- drm_sched_job_done(sched_job, IS_ERR(fence) ?
- PTR_ERR(fence) : 0);
+ r = dma_fence_add_callback(fence, &sched_job->cb,
+ drm_sched_job_done_cb);
+ if (r == -ENOENT)
+ drm_sched_job_done(sched_job, fence->error);
+ else if (r)
+ DRM_DEV_ERROR(sched->dev,
+ "fence add callback failed (%d)\n", r);
+ } else {
+ drm_sched_job_done(sched_job, IS_ERR(fence) ?
+ PTR_ERR(fence) : 0);
+ }
}
- wake_up(&sched->job_scheduled);
- drm_sched_run_job_queue(sched);
+ if (submitted_credits)
+ wake_up(&sched->job_scheduled);
}
/**
diff --git a/drivers/gpu/drm/scheduler/sched_rq.c b/drivers/gpu/drm/scheduler/sched_rq.c
index 0b7a2b8b48db..1a454384ab25 100644
--- a/drivers/gpu/drm/scheduler/sched_rq.c
+++ b/drivers/gpu/drm/scheduler/sched_rq.c
@@ -156,9 +156,7 @@ void drm_sched_rq_pop_entity(struct drm_sched_rq *rq,
*
* Find oldest waiting ready entity.
*
- * Return an entity if one is found; return an error-pointer (!NULL) if an
- * entity was ready, but the scheduler had insufficient credits to accommodate
- * its job; return NULL, if no ready entity was found.
+ * Return an entity if one is found or NULL if no ready entity was found.
*/
struct drm_sched_entity *
drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched,
@@ -170,16 +168,13 @@ drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched,
spin_lock(&rq->lock);
for (rb = rb_first_cached(&rq->rb_tree_root); rb; rb = rb_next(rb)) {
entity = rb_entry(rb, struct drm_sched_entity, rb_tree_node);
- if (drm_sched_entity_is_ready(entity)) {
- if (!drm_sched_can_queue(sched, entity)) {
- entity = ERR_PTR(-ENOSPC);
- break;
- }
-
- reinit_completion(&entity->entity_idle);
- break;
+ if (!drm_sched_entity_is_ready(entity)) {
+ entity = NULL;
+ continue;
}
- entity = NULL;
+
+ reinit_completion(&entity->entity_idle);
+ break;
}
spin_unlock(&rq->lock);
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index 93f6fcfe3ba0..85f3a0d5a7be 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -544,9 +544,6 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
void drm_sched_fini(struct drm_gpu_scheduler *sched);
-bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
- struct drm_sched_entity *entity);
-
int drm_sched_job_init(struct drm_sched_job *job,
struct drm_sched_entity *entity,
u32 credits, void *owner);
--
2.47.1
^ permalink raw reply related [flat|nested] 61+ messages in thread* Re: [RFC 10/14] drm/sched: Queue all free credits in one worker invocation
2024-12-30 16:52 ` [RFC 10/14] drm/sched: Queue all free credits in one worker invocation Tvrtko Ursulin
@ 2025-01-07 11:08 ` Tvrtko Ursulin
0 siblings, 0 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-07 11:08 UTC (permalink / raw)
To: Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
On 30/12/2024 16:52, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>
> There is no reason to queue just a single job if scheduler can take more
> and re-queue the worker to queue more. We can simply feed the hardware
> with as much as it can take in one go and hopefully win some latency.
>
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: Danilo Krummrich <dakr@redhat.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Philipp Stanner <pstanner@redhat.com>
> ---
> drivers/gpu/drm/scheduler/sched_main.c | 112 +++++++++++--------------
> drivers/gpu/drm/scheduler/sched_rq.c | 19 ++---
> include/drm/gpu_scheduler.h | 3 -
> 3 files changed, 58 insertions(+), 76 deletions(-)
>
> diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
> index 4ba9ed27a8a6..6f4ea8a2ca17 100644
> --- a/drivers/gpu/drm/scheduler/sched_main.c
> +++ b/drivers/gpu/drm/scheduler/sched_main.c
> @@ -98,33 +98,6 @@ static u32 drm_sched_available_credits(struct drm_gpu_scheduler *sched)
> return credits;
> }
>
> -/**
> - * drm_sched_can_queue -- Can we queue more to the hardware?
> - * @sched: scheduler instance
> - * @entity: the scheduler entity
> - *
> - * Return true if we can push at least one more job from @entity, false
> - * otherwise.
> - */
> -bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
> - struct drm_sched_entity *entity)
> -{
> - struct drm_sched_job *s_job;
> -
> - s_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
> - if (!s_job)
> - return false;
> -
> - /* If a job exceeds the credit limit, truncate it to the credit limit
> - * itself to guarantee forward progress.
> - */
> - if (drm_WARN(sched, s_job->credits > sched->credit_limit,
> - "Jobs may not exceed the credit limit, truncate.\n"))
> - s_job->credits = sched->credit_limit;
> -
> - return drm_sched_available_credits(sched) >= s_job->credits;
> -}
> -
> /**
> * drm_sched_run_job_queue - enqueue run-job work
> * @sched: scheduler instance
> @@ -174,6 +147,7 @@ static void drm_sched_job_done(struct drm_sched_job *s_job, int result)
>
> atomic_sub(s_job->credits, &sched->credit_count);
> atomic_dec(sched->score);
> + drm_sched_run_job_queue(sched);
>
> trace_drm_sched_process_job(s_fence);
>
> @@ -941,7 +915,6 @@ static void drm_sched_free_job_work(struct work_struct *w)
> sched->ops->free_job(job);
>
> drm_sched_run_free_queue(sched);
> - drm_sched_run_job_queue(sched);
Two hunks above are somewhat of a rebasing artifact since I've been
re-ordering patches and cherry-picking from some different
implementations for the public post. Nevertheless, there is likely
something broken with this patch in terms of missing to re-queue the
worker in some cases which I need to get to the bottom of. It's odd
though.. I would have thought re-queue triggers of 1) first job
submitted, 2) dependency resolved and 3) job completed should have been
enough but I am obviously missing somthing subtle.
Regards,
Tvrtko
> }
>
> /**
> @@ -953,54 +926,71 @@ static void drm_sched_run_job_work(struct work_struct *w)
> {
> struct drm_gpu_scheduler *sched =
> container_of(w, struct drm_gpu_scheduler, work_run_job);
> + u32 job_credits, submitted_credits = 0;
> struct drm_sched_entity *entity;
> - struct dma_fence *fence;
> - struct drm_sched_fence *s_fence;
> struct drm_sched_job *sched_job;
> - int r;
> + struct dma_fence *fence;
>
> if (READ_ONCE(sched->pause_submit))
> return;
>
> - /* Find entity with a ready job */
> - entity = drm_sched_rq_select_entity(sched, sched->rq);
> - if (IS_ERR_OR_NULL(entity))
> - return; /* No more work */
> + for (;;) {
> + /* Find entity with a ready job */
> + entity = drm_sched_rq_select_entity(sched, sched->rq);
> + if (!entity)
> + break; /* No more work */
>
> - sched_job = drm_sched_entity_pop_job(entity);
> - if (!sched_job) {
> + /*
> + * If a job exceeds the credit limit truncate it to guarantee
> + * forward progress.
> + */
> + sched_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
> + job_credits = sched_job->credits;
> + if (drm_WARN_ONCE(sched, job_credits > sched->credit_limit,
> + "Jobs may not exceed the credit limit, truncating.\n"))
> + job_credits = sched_job->credits = sched->credit_limit;
> +
> + if (job_credits > drm_sched_available_credits(sched)) {
> + complete_all(&entity->entity_idle);
> + break;
> + }
> +
> + sched_job = drm_sched_entity_pop_job(entity);
> complete_all(&entity->entity_idle);
> - drm_sched_run_job_queue(sched);
> - return;
> - }
> + if (!sched_job) {
> + /* Top entity is not yet runnable after all */
> + continue;
> + }
>
> - s_fence = sched_job->s_fence;
> + drm_sched_job_begin(sched_job);
> + trace_drm_run_job(sched_job, entity);
> + submitted_credits += job_credits;
> + atomic_add(job_credits, &sched->credit_count);
>
> - atomic_add(sched_job->credits, &sched->credit_count);
> - drm_sched_job_begin(sched_job);
> + fence = sched->ops->run_job(sched_job);
> + drm_sched_fence_scheduled(sched_job->s_fence, fence);
>
> - trace_drm_run_job(sched_job, entity);
> - fence = sched->ops->run_job(sched_job);
> - complete_all(&entity->entity_idle);
> - drm_sched_fence_scheduled(s_fence, fence);
> + if (!IS_ERR_OR_NULL(fence)) {
> + int r;
>
> - if (!IS_ERR_OR_NULL(fence)) {
> - /* Drop for original kref_init of the fence */
> - dma_fence_put(fence);
> + /* Drop for original kref_init of the fence */
> + dma_fence_put(fence);
>
> - r = dma_fence_add_callback(fence, &sched_job->cb,
> - drm_sched_job_done_cb);
> - if (r == -ENOENT)
> - drm_sched_job_done(sched_job, fence->error);
> - else if (r)
> - DRM_DEV_ERROR(sched->dev, "fence add callback failed (%d)\n", r);
> - } else {
> - drm_sched_job_done(sched_job, IS_ERR(fence) ?
> - PTR_ERR(fence) : 0);
> + r = dma_fence_add_callback(fence, &sched_job->cb,
> + drm_sched_job_done_cb);
> + if (r == -ENOENT)
> + drm_sched_job_done(sched_job, fence->error);
> + else if (r)
> + DRM_DEV_ERROR(sched->dev,
> + "fence add callback failed (%d)\n", r);
> + } else {
> + drm_sched_job_done(sched_job, IS_ERR(fence) ?
> + PTR_ERR(fence) : 0);
> + }
> }
>
> - wake_up(&sched->job_scheduled);
> - drm_sched_run_job_queue(sched);
> + if (submitted_credits)
> + wake_up(&sched->job_scheduled);
> }
>
> /**
> diff --git a/drivers/gpu/drm/scheduler/sched_rq.c b/drivers/gpu/drm/scheduler/sched_rq.c
> index 0b7a2b8b48db..1a454384ab25 100644
> --- a/drivers/gpu/drm/scheduler/sched_rq.c
> +++ b/drivers/gpu/drm/scheduler/sched_rq.c
> @@ -156,9 +156,7 @@ void drm_sched_rq_pop_entity(struct drm_sched_rq *rq,
> *
> * Find oldest waiting ready entity.
> *
> - * Return an entity if one is found; return an error-pointer (!NULL) if an
> - * entity was ready, but the scheduler had insufficient credits to accommodate
> - * its job; return NULL, if no ready entity was found.
> + * Return an entity if one is found or NULL if no ready entity was found.
> */
> struct drm_sched_entity *
> drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched,
> @@ -170,16 +168,13 @@ drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched,
> spin_lock(&rq->lock);
> for (rb = rb_first_cached(&rq->rb_tree_root); rb; rb = rb_next(rb)) {
> entity = rb_entry(rb, struct drm_sched_entity, rb_tree_node);
> - if (drm_sched_entity_is_ready(entity)) {
> - if (!drm_sched_can_queue(sched, entity)) {
> - entity = ERR_PTR(-ENOSPC);
> - break;
> - }
> -
> - reinit_completion(&entity->entity_idle);
> - break;
> + if (!drm_sched_entity_is_ready(entity)) {
> + entity = NULL;
> + continue;
> }
> - entity = NULL;
> +
> + reinit_completion(&entity->entity_idle);
> + break;
> }
> spin_unlock(&rq->lock);
>
> diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
> index 93f6fcfe3ba0..85f3a0d5a7be 100644
> --- a/include/drm/gpu_scheduler.h
> +++ b/include/drm/gpu_scheduler.h
> @@ -544,9 +544,6 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
>
> void drm_sched_fini(struct drm_gpu_scheduler *sched);
>
> -bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
> - struct drm_sched_entity *entity);
> -
> int drm_sched_job_init(struct drm_sched_job *job,
> struct drm_sched_entity *entity,
> u32 credits, void *owner);
^ permalink raw reply [flat|nested] 61+ messages in thread
* [RFC 11/14] drm/sched: Connect with dma-fence deadlines
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
` (9 preceding siblings ...)
2024-12-30 16:52 ` [RFC 10/14] drm/sched: Queue all free credits in one worker invocation Tvrtko Ursulin
@ 2024-12-30 16:52 ` Tvrtko Ursulin
2025-01-07 11:10 ` Tvrtko Ursulin
2025-01-09 11:38 ` Michel Dänzer
2024-12-30 16:52 ` [RFC 12/14] drm/sched: Embed run queue singleton into the scheduler Tvrtko Ursulin
` (6 subsequent siblings)
17 siblings, 2 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2024-12-30 16:52 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner, Rob Clark
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Now that the scheduling policy is deadline based it feels completely
natural to allow propagating externaly set deadlines to the scheduler.
Scheduler deadlines are not a guarantee but as the dma-fence facility is
already in use by userspace lets wire it up.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <pstanner@redhat.com>
Cc: Rob Clark <robdclark@gmail.com>
---
drivers/gpu/drm/scheduler/sched_entity.c | 30 +++++++++++++++++++++++-
drivers/gpu/drm/scheduler/sched_fence.c | 3 +++
drivers/gpu/drm/scheduler/sched_rq.c | 16 +++++++++++++
include/drm/gpu_scheduler.h | 8 +++++++
4 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index 14bc3f797079..c5a4c04b2455 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -385,7 +385,24 @@ ktime_t
drm_sched_entity_get_job_deadline(struct drm_sched_entity *entity,
struct drm_sched_job *job)
{
- return __drm_sched_entity_get_job_deadline(entity, job->submit_ts);
+ struct drm_sched_fence *s_fence = job->s_fence;
+ struct dma_fence *fence = &s_fence->finished;
+ ktime_t deadline;
+
+ deadline = __drm_sched_entity_get_job_deadline(entity, job->submit_ts);
+ if (test_bit(DRM_SCHED_FENCE_FLAG_HAS_DEADLINE_BIT, &fence->flags) &&
+ ktime_before(s_fence->deadline, deadline))
+ deadline = s_fence->deadline;
+
+ return deadline;
+}
+
+void drm_sched_entity_set_deadline(struct drm_sched_entity *entity,
+ ktime_t deadline)
+{
+ spin_lock(&entity->lock);
+ drm_sched_rq_update_deadline(entity->rq, entity, deadline);
+ spin_unlock(&entity->lock);
}
/*
@@ -536,8 +553,11 @@ void drm_sched_entity_select_rq(struct drm_sched_entity *entity)
*/
void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
{
+ struct drm_sched_fence *s_fence = sched_job->s_fence;
struct drm_sched_entity *entity = sched_job->entity;
+ struct dma_fence *fence = &s_fence->finished;
ktime_t submit_ts = ktime_get();
+ ktime_t fence_deadline;
bool first;
trace_drm_sched_job(sched_job, entity);
@@ -552,6 +572,11 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
* Make sure to set the submit_ts first, to avoid a race.
*/
sched_job->submit_ts = submit_ts;
+ if (test_bit(DRM_SCHED_FENCE_FLAG_HAS_DEADLINE_BIT, &fence->flags))
+ fence_deadline = s_fence->deadline;
+ else
+ fence_deadline = KTIME_MAX;
+
first = spsc_queue_push(&entity->job_queue, &sched_job->queue_node);
/* first job wakes up scheduler */
@@ -560,6 +585,9 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
submit_ts = __drm_sched_entity_get_job_deadline(entity,
submit_ts);
+ if (ktime_before(fence_deadline, submit_ts))
+ submit_ts = fence_deadline;
+
sched = drm_sched_rq_add_entity(entity->rq, entity, submit_ts);
if (sched)
drm_sched_wakeup(sched);
diff --git a/drivers/gpu/drm/scheduler/sched_fence.c b/drivers/gpu/drm/scheduler/sched_fence.c
index 0f35f009b9d3..dfc7f50d4e0d 100644
--- a/drivers/gpu/drm/scheduler/sched_fence.c
+++ b/drivers/gpu/drm/scheduler/sched_fence.c
@@ -168,6 +168,8 @@ static void drm_sched_fence_set_deadline_finished(struct dma_fence *f,
spin_unlock_irqrestore(&fence->lock, flags);
+ drm_sched_entity_set_deadline(fence->entity, deadline);
+
/*
* smp_load_aquire() to ensure that if we are racing another
* thread calling drm_sched_fence_set_parent(), that we see
@@ -223,6 +225,7 @@ void drm_sched_fence_init(struct drm_sched_fence *fence,
{
unsigned seq;
+ fence->entity = entity;
fence->sched = entity->rq->sched;
seq = atomic_inc_return(&entity->fence_seq);
dma_fence_init(&fence->scheduled, &drm_sched_fence_ops_scheduled,
diff --git a/drivers/gpu/drm/scheduler/sched_rq.c b/drivers/gpu/drm/scheduler/sched_rq.c
index 1a454384ab25..e96c8ca9c54b 100644
--- a/drivers/gpu/drm/scheduler/sched_rq.c
+++ b/drivers/gpu/drm/scheduler/sched_rq.c
@@ -148,6 +148,22 @@ void drm_sched_rq_pop_entity(struct drm_sched_rq *rq,
spin_unlock(&entity->lock);
}
+void drm_sched_rq_update_deadline(struct drm_sched_rq *rq,
+ struct drm_sched_entity *entity,
+ ktime_t deadline)
+{
+ lockdep_assert_held(&entity->lock);
+
+ if (ktime_before(deadline, entity->oldest_job_waiting)) {
+ spin_lock(&rq->lock);
+ if (!RB_EMPTY_NODE(&entity->rb_tree_node)) {
+ __drm_sched_rq_remove_tree_locked(entity, rq);
+ __drm_sched_rq_add_tree_locked(entity, rq, deadline);
+ }
+ spin_unlock(&rq->lock);
+ }
+}
+
/**
* drm_sched_rq_select_entity - Select an entity which provides a job to run
*
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index 85f3a0d5a7be..c68dce8af063 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -291,6 +291,9 @@ struct drm_sched_fence {
* &drm_sched_fence.finished fence once parent is signalled.
*/
struct dma_fence *parent;
+
+ struct drm_sched_entity *entity;
+
/**
* @sched: the scheduler instance to which the job having this struct
* belongs to.
@@ -597,6 +600,9 @@ void drm_sched_rq_pop_entity(struct drm_sched_rq *rq,
struct drm_sched_entity *
drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched,
struct drm_sched_rq *rq);
+void drm_sched_rq_update_deadline(struct drm_sched_rq *rq,
+ struct drm_sched_entity *entity,
+ ktime_t deadline);
int drm_sched_entity_init(struct drm_sched_entity *entity,
enum drm_sched_priority priority,
@@ -612,6 +618,8 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job);
void drm_sched_entity_set_priority(struct drm_sched_entity *entity,
enum drm_sched_priority priority);
bool drm_sched_entity_is_ready(struct drm_sched_entity *entity);
+void drm_sched_entity_set_deadline(struct drm_sched_entity *entity,
+ ktime_t deadline);
int drm_sched_entity_error(struct drm_sched_entity *entity);
ktime_t drm_sched_entity_get_job_deadline(struct drm_sched_entity *entity,
struct drm_sched_job *job);
--
2.47.1
^ permalink raw reply related [flat|nested] 61+ messages in thread* Re: [RFC 11/14] drm/sched: Connect with dma-fence deadlines
2024-12-30 16:52 ` [RFC 11/14] drm/sched: Connect with dma-fence deadlines Tvrtko Ursulin
@ 2025-01-07 11:10 ` Tvrtko Ursulin
2025-01-09 11:38 ` Michel Dänzer
1 sibling, 0 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-07 11:10 UTC (permalink / raw)
To: Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner, Rob Clark
On 30/12/2024 16:52, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>
> Now that the scheduling policy is deadline based it feels completely
> natural to allow propagating externaly set deadlines to the scheduler.
>
> Scheduler deadlines are not a guarantee but as the dma-fence facility is
> already in use by userspace lets wire it up.
>
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: Danilo Krummrich <dakr@redhat.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Philipp Stanner <pstanner@redhat.com>
> Cc: Rob Clark <robdclark@gmail.com>
> ---
> drivers/gpu/drm/scheduler/sched_entity.c | 30 +++++++++++++++++++++++-
> drivers/gpu/drm/scheduler/sched_fence.c | 3 +++
> drivers/gpu/drm/scheduler/sched_rq.c | 16 +++++++++++++
> include/drm/gpu_scheduler.h | 8 +++++++
> 4 files changed, 56 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
> index 14bc3f797079..c5a4c04b2455 100644
> --- a/drivers/gpu/drm/scheduler/sched_entity.c
> +++ b/drivers/gpu/drm/scheduler/sched_entity.c
> @@ -385,7 +385,24 @@ ktime_t
> drm_sched_entity_get_job_deadline(struct drm_sched_entity *entity,
> struct drm_sched_job *job)
> {
> - return __drm_sched_entity_get_job_deadline(entity, job->submit_ts);
> + struct drm_sched_fence *s_fence = job->s_fence;
> + struct dma_fence *fence = &s_fence->finished;
> + ktime_t deadline;
> +
> + deadline = __drm_sched_entity_get_job_deadline(entity, job->submit_ts);
> + if (test_bit(DRM_SCHED_FENCE_FLAG_HAS_DEADLINE_BIT, &fence->flags) &&
> + ktime_before(s_fence->deadline, deadline))
> + deadline = s_fence->deadline;
> +
> + return deadline;
> +}
> +
> +void drm_sched_entity_set_deadline(struct drm_sched_entity *entity,
> + ktime_t deadline)
> +{
> + spin_lock(&entity->lock);
> + drm_sched_rq_update_deadline(entity->rq, entity, deadline);
> + spin_unlock(&entity->lock);
> }
>
> /*
> @@ -536,8 +553,11 @@ void drm_sched_entity_select_rq(struct drm_sched_entity *entity)
> */
> void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
> {
> + struct drm_sched_fence *s_fence = sched_job->s_fence;
> struct drm_sched_entity *entity = sched_job->entity;
> + struct dma_fence *fence = &s_fence->finished;
> ktime_t submit_ts = ktime_get();
> + ktime_t fence_deadline;
> bool first;
>
> trace_drm_sched_job(sched_job, entity);
> @@ -552,6 +572,11 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
> * Make sure to set the submit_ts first, to avoid a race.
> */
> sched_job->submit_ts = submit_ts;
> + if (test_bit(DRM_SCHED_FENCE_FLAG_HAS_DEADLINE_BIT, &fence->flags))
> + fence_deadline = s_fence->deadline;
> + else
> + fence_deadline = KTIME_MAX;
> +
> first = spsc_queue_push(&entity->job_queue, &sched_job->queue_node);
>
> /* first job wakes up scheduler */
> @@ -560,6 +585,9 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
>
> submit_ts = __drm_sched_entity_get_job_deadline(entity,
> submit_ts);
> + if (ktime_before(fence_deadline, submit_ts))
> + submit_ts = fence_deadline;
> +
> sched = drm_sched_rq_add_entity(entity->rq, entity, submit_ts);
> if (sched)
> drm_sched_wakeup(sched);
> diff --git a/drivers/gpu/drm/scheduler/sched_fence.c b/drivers/gpu/drm/scheduler/sched_fence.c
> index 0f35f009b9d3..dfc7f50d4e0d 100644
> --- a/drivers/gpu/drm/scheduler/sched_fence.c
> +++ b/drivers/gpu/drm/scheduler/sched_fence.c
> @@ -168,6 +168,8 @@ static void drm_sched_fence_set_deadline_finished(struct dma_fence *f,
>
> spin_unlock_irqrestore(&fence->lock, flags);
>
> + drm_sched_entity_set_deadline(fence->entity, deadline);
This I think needs re-work too becuase entities must not be acccessed
from jobs. Sigh. I can make it update the deadline inside the job itself
which will be applied when the job becomes first in the queue.
Regards,
Tvrtko
> +
> /*
> * smp_load_aquire() to ensure that if we are racing another
> * thread calling drm_sched_fence_set_parent(), that we see
> @@ -223,6 +225,7 @@ void drm_sched_fence_init(struct drm_sched_fence *fence,
> {
> unsigned seq;
>
> + fence->entity = entity;
> fence->sched = entity->rq->sched;
> seq = atomic_inc_return(&entity->fence_seq);
> dma_fence_init(&fence->scheduled, &drm_sched_fence_ops_scheduled,
> diff --git a/drivers/gpu/drm/scheduler/sched_rq.c b/drivers/gpu/drm/scheduler/sched_rq.c
> index 1a454384ab25..e96c8ca9c54b 100644
> --- a/drivers/gpu/drm/scheduler/sched_rq.c
> +++ b/drivers/gpu/drm/scheduler/sched_rq.c
> @@ -148,6 +148,22 @@ void drm_sched_rq_pop_entity(struct drm_sched_rq *rq,
> spin_unlock(&entity->lock);
> }
>
> +void drm_sched_rq_update_deadline(struct drm_sched_rq *rq,
> + struct drm_sched_entity *entity,
> + ktime_t deadline)
> +{
> + lockdep_assert_held(&entity->lock);
> +
> + if (ktime_before(deadline, entity->oldest_job_waiting)) {
> + spin_lock(&rq->lock);
> + if (!RB_EMPTY_NODE(&entity->rb_tree_node)) {
> + __drm_sched_rq_remove_tree_locked(entity, rq);
> + __drm_sched_rq_add_tree_locked(entity, rq, deadline);
> + }
> + spin_unlock(&rq->lock);
> + }
> +}
> +
> /**
> * drm_sched_rq_select_entity - Select an entity which provides a job to run
> *
> diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
> index 85f3a0d5a7be..c68dce8af063 100644
> --- a/include/drm/gpu_scheduler.h
> +++ b/include/drm/gpu_scheduler.h
> @@ -291,6 +291,9 @@ struct drm_sched_fence {
> * &drm_sched_fence.finished fence once parent is signalled.
> */
> struct dma_fence *parent;
> +
> + struct drm_sched_entity *entity;
> +
> /**
> * @sched: the scheduler instance to which the job having this struct
> * belongs to.
> @@ -597,6 +600,9 @@ void drm_sched_rq_pop_entity(struct drm_sched_rq *rq,
> struct drm_sched_entity *
> drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched,
> struct drm_sched_rq *rq);
> +void drm_sched_rq_update_deadline(struct drm_sched_rq *rq,
> + struct drm_sched_entity *entity,
> + ktime_t deadline);
>
> int drm_sched_entity_init(struct drm_sched_entity *entity,
> enum drm_sched_priority priority,
> @@ -612,6 +618,8 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job);
> void drm_sched_entity_set_priority(struct drm_sched_entity *entity,
> enum drm_sched_priority priority);
> bool drm_sched_entity_is_ready(struct drm_sched_entity *entity);
> +void drm_sched_entity_set_deadline(struct drm_sched_entity *entity,
> + ktime_t deadline);
> int drm_sched_entity_error(struct drm_sched_entity *entity);
> ktime_t drm_sched_entity_get_job_deadline(struct drm_sched_entity *entity,
> struct drm_sched_job *job);
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 11/14] drm/sched: Connect with dma-fence deadlines
2024-12-30 16:52 ` [RFC 11/14] drm/sched: Connect with dma-fence deadlines Tvrtko Ursulin
2025-01-07 11:10 ` Tvrtko Ursulin
@ 2025-01-09 11:38 ` Michel Dänzer
2025-01-09 13:31 ` Tvrtko Ursulin
1 sibling, 1 reply; 61+ messages in thread
From: Michel Dänzer @ 2025-01-09 11:38 UTC (permalink / raw)
To: Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner, Rob Clark
On 2024-12-30 17:52, Tvrtko Ursulin wrote:
>
> diff --git a/drivers/gpu/drm/scheduler/sched_fence.c b/drivers/gpu/drm/scheduler/sched_fence.c
> index 0f35f009b9d3..dfc7f50d4e0d 100644
> --- a/drivers/gpu/drm/scheduler/sched_fence.c
> +++ b/drivers/gpu/drm/scheduler/sched_fence.c
> @@ -168,6 +168,8 @@ static void drm_sched_fence_set_deadline_finished(struct dma_fence *f,
>
> spin_unlock_irqrestore(&fence->lock, flags);
>
> + drm_sched_entity_set_deadline(fence->entity, deadline);
AFAICT sync_file_ioctl_set_deadline passes through the unmodified deadline from user space. If the scheduler uses that directly, all user space can fake unlimited high priority for its jobs via the ioctl?
--
Earthling Michel Dänzer \ GNOME / Xwayland / Mesa developer
https://redhat.com \ Libre software enthusiast
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [RFC 11/14] drm/sched: Connect with dma-fence deadlines
2025-01-09 11:38 ` Michel Dänzer
@ 2025-01-09 13:31 ` Tvrtko Ursulin
2025-01-09 14:44 ` Michel Dänzer
0 siblings, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-09 13:31 UTC (permalink / raw)
To: Michel Dänzer, Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Christian König, Danilo Krummrich, Matthew Brost,
Philipp Stanner, Rob Clark
On 09/01/2025 11:38, Michel Dänzer wrote:
> On 2024-12-30 17:52, Tvrtko Ursulin wrote:
>>
>> diff --git a/drivers/gpu/drm/scheduler/sched_fence.c b/drivers/gpu/drm/scheduler/sched_fence.c
>> index 0f35f009b9d3..dfc7f50d4e0d 100644
>> --- a/drivers/gpu/drm/scheduler/sched_fence.c
>> +++ b/drivers/gpu/drm/scheduler/sched_fence.c
>> @@ -168,6 +168,8 @@ static void drm_sched_fence_set_deadline_finished(struct dma_fence *f,
>>
>> spin_unlock_irqrestore(&fence->lock, flags);
>>
>> + drm_sched_entity_set_deadline(fence->entity, deadline);
>
> AFAICT sync_file_ioctl_set_deadline passes through the unmodified deadline from user space. If the scheduler uses that directly, all user space can fake unlimited high priority for its jobs via the ioctl?
Yes, that wouldn't be great. I could only allow high priority
contexts/entities to have their deadlines respected. I hope the uapi
side of deadlines did not make any hard promises. Well obviously it did
not since it is not wired up at the moment anyway.
I also need to improve it and pull in the internal deadline to some time
before the userspace one.
Regards,
Tvrtko
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [RFC 11/14] drm/sched: Connect with dma-fence deadlines
2025-01-09 13:31 ` Tvrtko Ursulin
@ 2025-01-09 14:44 ` Michel Dänzer
2025-01-09 16:44 ` Tvrtko Ursulin
0 siblings, 1 reply; 61+ messages in thread
From: Michel Dänzer @ 2025-01-09 14:44 UTC (permalink / raw)
To: Tvrtko Ursulin, Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Christian König, Danilo Krummrich, Matthew Brost,
Philipp Stanner, Rob Clark
On 2025-01-09 14:31, Tvrtko Ursulin wrote:
> On 09/01/2025 11:38, Michel Dänzer wrote:
>> On 2024-12-30 17:52, Tvrtko Ursulin wrote:
>>>
>>> diff --git a/drivers/gpu/drm/scheduler/sched_fence.c b/drivers/gpu/drm/scheduler/sched_fence.c
>>> index 0f35f009b9d3..dfc7f50d4e0d 100644
>>> --- a/drivers/gpu/drm/scheduler/sched_fence.c
>>> +++ b/drivers/gpu/drm/scheduler/sched_fence.c
>>> @@ -168,6 +168,8 @@ static void drm_sched_fence_set_deadline_finished(struct dma_fence *f,
>>> spin_unlock_irqrestore(&fence->lock, flags);
>>> + drm_sched_entity_set_deadline(fence->entity, deadline);
>>
>> AFAICT sync_file_ioctl_set_deadline passes through the unmodified deadline from user space. If the scheduler uses that directly, all user space can fake unlimited high priority for its jobs via the ioctl?
>
> Yes, that wouldn't be great. I could only allow high priority contexts/entities to have their deadlines respected.
FWIW, there are more wrinkles here:
The user-space entity which sets the fence deadline isn't necessarily the one which submitted the corresponding GPU job, e.g. it could be the Wayland compositor. Not sure offhand whether the scheduling priority of the GPU job submitter and/or fence deadline setter should be taken into account in this case.
If the fence deadline is later than the original scheduler deadline based on job submission time and scheduling priority, should the scheduling deadline be moved back or not?
> I hope the uapi side of deadlines did not make any hard promises. Well obviously it did not since it is not wired up at the moment anyway.
Right, I guess it's essentially a hint by when user space would like the fence to have signalled if possible.
> I also need to improve it and pull in the internal deadline to some time before the userspace one.
Because the internal deadline corresponds to when the job starts executing, whereas the fence deadline to when it finishes? Not sure how that can be accounted for though, not knowing how long the job will take to execute.
In summary, I'm not sure using the fence deadline for the scheduler one really makes sense after all.
--
Earthling Michel Dänzer \ GNOME / Xwayland / Mesa developer
https://redhat.com \ Libre software enthusiast
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [RFC 11/14] drm/sched: Connect with dma-fence deadlines
2025-01-09 14:44 ` Michel Dänzer
@ 2025-01-09 16:44 ` Tvrtko Ursulin
0 siblings, 0 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-09 16:44 UTC (permalink / raw)
To: Michel Dänzer, Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Christian König, Danilo Krummrich, Matthew Brost,
Philipp Stanner, Rob Clark
On 09/01/2025 14:44, Michel Dänzer wrote:
> On 2025-01-09 14:31, Tvrtko Ursulin wrote:
>> On 09/01/2025 11:38, Michel Dänzer wrote:
>>> On 2024-12-30 17:52, Tvrtko Ursulin wrote:
>>>>
>>>> diff --git a/drivers/gpu/drm/scheduler/sched_fence.c b/drivers/gpu/drm/scheduler/sched_fence.c
>>>> index 0f35f009b9d3..dfc7f50d4e0d 100644
>>>> --- a/drivers/gpu/drm/scheduler/sched_fence.c
>>>> +++ b/drivers/gpu/drm/scheduler/sched_fence.c
>>>> @@ -168,6 +168,8 @@ static void drm_sched_fence_set_deadline_finished(struct dma_fence *f,
>>>> spin_unlock_irqrestore(&fence->lock, flags);
>>>> + drm_sched_entity_set_deadline(fence->entity, deadline);
>>>
>>> AFAICT sync_file_ioctl_set_deadline passes through the unmodified deadline from user space. If the scheduler uses that directly, all user space can fake unlimited high priority for its jobs via the ioctl?
>>
>> Yes, that wouldn't be great. I could only allow high priority contexts/entities to have their deadlines respected.
>
> FWIW, there are more wrinkles here:
>
> The user-space entity which sets the fence deadline isn't necessarily the one which submitted the corresponding GPU job, e.g. it could be the Wayland compositor. Not sure offhand whether the scheduling priority of the GPU job submitter and/or fence deadline setter should be taken into account in this case.
Hmm excellent point. Is that how things typically work? Compositors
setting deadlines on fences received from clients?
> If the fence deadline is later than the original scheduler deadline based on job submission time and scheduling priority, should the scheduling deadline be moved back or not?
In the RFC I only pull in if fence deadline is sooner which I think
makes more sense.
>> I hope the uapi side of deadlines did not make any hard promises. Well obviously it did not since it is not wired up at the moment anyway.
>
> Right, I guess it's essentially a hint by when user space would like the fence to have signalled if possible.
>
>
>> I also need to improve it and pull in the internal deadline to some time before the userspace one.
>
> Because the internal deadline corresponds to when the job starts executing, whereas the fence deadline to when it finishes? Not sure how that can be accounted for though, not knowing how long the job will take to execute.
Yes exactly. It would have to be heuristics. But likely something would
be better than nothing.
> In summary, I'm not sure using the fence deadline for the scheduler one really makes sense after all.
IMO it doesn't have to be perfect. Just if we find a clean way which
improves real uses cases.
Regards,
Tvrtko
^ permalink raw reply [flat|nested] 61+ messages in thread
* [RFC 12/14] drm/sched: Embed run queue singleton into the scheduler
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
` (10 preceding siblings ...)
2024-12-30 16:52 ` [RFC 11/14] drm/sched: Connect with dma-fence deadlines Tvrtko Ursulin
@ 2024-12-30 16:52 ` Tvrtko Ursulin
2024-12-31 2:39 ` kernel test robot
2024-12-30 16:52 ` [RFC 13/14] dma-fence: Add helper for custom fence context when merging fences Tvrtko Ursulin
` (5 subsequent siblings)
17 siblings, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2024-12-30 16:52 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Now that the run queue to scheduler relationship is always 1:1 we can
embed it (the run queue) directly in the scheduler struct and save on
some allocation error handling code and such.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <pstanner@redhat.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 ++--
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 6 ++--
drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 5 +++-
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 8 ++++--
drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 8 +++---
drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 8 +++---
drivers/gpu/drm/scheduler/sched_entity.c | 27 ++++++++----------
drivers/gpu/drm/scheduler/sched_fence.c | 2 +-
drivers/gpu/drm/scheduler/sched_main.c | 31 ++++-----------------
drivers/gpu/drm/scheduler/sched_rq.c | 17 +++++------
include/drm/gpu_scheduler.h | 11 ++------
11 files changed, 56 insertions(+), 73 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index d891ab779ca7..25028ac48844 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -1108,7 +1108,8 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
if (p->gang_size > 1 && !p->adev->vm_manager.concurrent_flush) {
for (i = 0; i < p->gang_size; ++i) {
struct drm_sched_entity *entity = p->entities[i];
- struct drm_gpu_scheduler *sched = entity->rq->sched;
+ struct drm_gpu_scheduler *sched =
+ container_of(entity->rq, typeof(*sched), rq);
struct amdgpu_ring *ring = to_amdgpu_ring(sched);
if (amdgpu_vmid_uses_reserved(adev, vm, ring->vm_hub))
@@ -1233,7 +1234,8 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
return r;
}
- sched = p->gang_leader->base.entity->rq->sched;
+ sched = container_of(p->gang_leader->base.entity->rq, typeof(*sched),
+ rq);
while ((fence = amdgpu_sync_get_fence(&p->sync))) {
struct drm_sched_fence *s_fence = to_drm_sched_fence(fence);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index 918b6d4919e1..f7abe413044e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -349,7 +349,9 @@ static struct dma_fence *
amdgpu_job_prepare_job(struct drm_sched_job *sched_job,
struct drm_sched_entity *s_entity)
{
- struct amdgpu_ring *ring = to_amdgpu_ring(s_entity->rq->sched);
+ struct drm_gpu_scheduler *sched =
+ container_of(s_entity->rq, typeof(*sched), rq);
+ struct amdgpu_ring *ring = to_amdgpu_ring(sched);
struct amdgpu_job *job = to_amdgpu_job(sched_job);
struct dma_fence *fence = NULL;
int r;
@@ -418,7 +420,7 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job)
void amdgpu_job_stop_all_jobs_on_sched(struct drm_gpu_scheduler *sched)
{
- struct drm_sched_rq *rq = sched->rq;
+ struct drm_sched_rq *rq = &sched->rq;
struct drm_sched_entity *s_entity;
struct drm_sched_job *s_job;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h
index ce6b9ba967ff..d6872baeba1e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h
@@ -85,7 +85,10 @@ struct amdgpu_job {
static inline struct amdgpu_ring *amdgpu_job_ring(struct amdgpu_job *job)
{
- return to_amdgpu_ring(job->base.entity->rq->sched);
+ struct drm_gpu_scheduler *sched =
+ container_of(job->base.entity->rq, typeof(*sched), rq);
+
+ return to_amdgpu_ring(sched);
}
int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
index 383fce40d4dd..a3819ed20d27 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
@@ -145,6 +145,7 @@ TRACE_EVENT(amdgpu_cs,
struct amdgpu_ib *ib),
TP_ARGS(p, job, ib),
TP_STRUCT__entry(
+ __field(struct drm_gpu_scheduler *, sched)
__field(struct amdgpu_bo_list *, bo_list)
__field(u32, ring)
__field(u32, dw)
@@ -152,11 +153,14 @@ TRACE_EVENT(amdgpu_cs,
),
TP_fast_assign(
+ __entry->sched = container_of(job->base.entity->rq,
+ typeof(*__entry->sched),
+ rq);
__entry->bo_list = p->bo_list;
- __entry->ring = to_amdgpu_ring(job->base.entity->rq->sched)->idx;
+ __entry->ring = to_amdgpu_ring(__entry->sched)->idx;
__entry->dw = ib->length_dw;
__entry->fences = amdgpu_fence_count_emitted(
- to_amdgpu_ring(job->base.entity->rq->sched));
+ to_amdgpu_ring(__entry->sched));
),
TP_printk("bo_list=%p, ring=%u, dw=%u, fences=%u",
__entry->bo_list, __entry->ring, __entry->dw,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
index 46d9fb433ab2..42f2bfb30af1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
@@ -105,13 +105,13 @@ static int amdgpu_vm_sdma_prepare(struct amdgpu_vm_update_params *p,
static int amdgpu_vm_sdma_commit(struct amdgpu_vm_update_params *p,
struct dma_fence **fence)
{
+ struct drm_gpu_scheduler *sched =
+ container_of(p->vm->delayed.rq, typeof(*sched), rq);
+ struct amdgpu_ring *ring =
+ container_of(sched, struct amdgpu_ring, sched);
struct amdgpu_ib *ib = p->job->ibs;
- struct amdgpu_ring *ring;
struct dma_fence *f;
- ring = container_of(p->vm->delayed.rq->sched, struct amdgpu_ring,
- sched);
-
WARN_ON(ib->length_dw == 0);
amdgpu_ring_pad_ib(ring, ib);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
index e209b5e101df..182744c5f0cf 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
@@ -420,15 +420,15 @@ int amdgpu_xcp_open_device(struct amdgpu_device *adev,
void amdgpu_xcp_release_sched(struct amdgpu_device *adev,
struct amdgpu_ctx_entity *entity)
{
- struct drm_gpu_scheduler *sched;
- struct amdgpu_ring *ring;
+ struct drm_gpu_scheduler *sched =
+ container_of(entity->entity.rq, typeof(*sched), rq);
if (!adev->xcp_mgr)
return;
- sched = entity->entity.rq->sched;
if (sched->ready) {
- ring = to_amdgpu_ring(entity->entity.rq->sched);
+ struct amdgpu_ring *ring = to_amdgpu_ring(sched);
+
atomic_dec(&adev->xcp_mgr->xcp[ring->xcp_id].ref_cnt);
}
}
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index c5a4c04b2455..dc5105ca8381 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -77,19 +77,12 @@ int drm_sched_entity_init(struct drm_sched_entity *entity,
* is initialized itself.
*/
entity->sched_list = num_sched_list > 1 ? sched_list : NULL;
+ if (num_sched_list) {
+ entity->sched_list = num_sched_list > 1 ? sched_list : NULL;
+ entity->rq = &sched_list[0]->rq;
+ }
RCU_INIT_POINTER(entity->last_scheduled, NULL);
RB_CLEAR_NODE(&entity->rb_tree_node);
-
- if (num_sched_list && !sched_list[0]->rq) {
- /* Since every entry covered by num_sched_list
- * should be non-NULL and therefore we warn drivers
- * not to do this and to fix their DRM calling order.
- */
- pr_warn("%s: called with uninitialized scheduler\n", __func__);
- } else if (num_sched_list) {
- entity->rq = sched_list[0]->rq;
- }
-
init_completion(&entity->entity_idle);
/* We start in an idle state. */
@@ -279,7 +272,7 @@ long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout)
if (!entity->rq)
return 0;
- sched = entity->rq->sched;
+ sched = container_of(entity->rq, typeof(*sched), rq);
/**
* The client will not queue more IBs during this fini, consume existing
* queued IBs or discard them on SIGKILL
@@ -414,10 +407,12 @@ static void drm_sched_entity_wakeup(struct dma_fence *f,
{
struct drm_sched_entity *entity =
container_of(cb, struct drm_sched_entity, cb);
+ struct drm_gpu_scheduler *sched =
+ container_of(entity->rq, typeof(*sched), rq);
entity->dependency = NULL;
dma_fence_put(f);
- drm_sched_wakeup(entity->rq->sched);
+ drm_sched_wakeup(sched);
}
/*
@@ -531,7 +526,7 @@ void drm_sched_entity_select_rq(struct drm_sched_entity *entity)
spin_lock(&entity->lock);
sched = drm_sched_pick_best(entity->sched_list, entity->num_sched_list);
- rq = sched ? sched->rq : NULL;
+ rq = sched ? &sched->rq : NULL;
if (rq != entity->rq) {
drm_sched_rq_remove_entity(entity->rq, entity);
entity->rq = rq;
@@ -556,12 +551,14 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
struct drm_sched_fence *s_fence = sched_job->s_fence;
struct drm_sched_entity *entity = sched_job->entity;
struct dma_fence *fence = &s_fence->finished;
+ struct drm_gpu_scheduler *sched =
+ container_of(entity->rq, typeof(*sched), rq);
ktime_t submit_ts = ktime_get();
ktime_t fence_deadline;
bool first;
trace_drm_sched_job(sched_job, entity);
- atomic_inc(entity->rq->sched->score);
+ atomic_inc(sched->score);
WRITE_ONCE(entity->last_user, current->group_leader);
drm_sched_job_prepare_dependecies(sched_job);
diff --git a/drivers/gpu/drm/scheduler/sched_fence.c b/drivers/gpu/drm/scheduler/sched_fence.c
index dfc7f50d4e0d..a0f8fbba6d7e 100644
--- a/drivers/gpu/drm/scheduler/sched_fence.c
+++ b/drivers/gpu/drm/scheduler/sched_fence.c
@@ -226,7 +226,7 @@ void drm_sched_fence_init(struct drm_sched_fence *fence,
unsigned seq;
fence->entity = entity;
- fence->sched = entity->rq->sched;
+ fence->sched = container_of(entity->rq, typeof(*fence->sched), rq);
seq = atomic_inc_return(&entity->fence_seq);
dma_fence_init(&fence->scheduled, &drm_sched_fence_ops_scheduled,
&fence->lock, entity->fence_context, seq);
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index 6f4ea8a2ca17..67bf0bec3309 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -590,7 +590,7 @@ void drm_sched_job_arm(struct drm_sched_job *job)
BUG_ON(!entity);
drm_sched_entity_select_rq(entity);
- sched = entity->rq->sched;
+ sched = container_of(entity->rq, typeof(*sched), rq);
job->sched = sched;
job->s_priority = entity->priority;
@@ -936,7 +936,7 @@ static void drm_sched_run_job_work(struct work_struct *w)
for (;;) {
/* Find entity with a ready job */
- entity = drm_sched_rq_select_entity(sched, sched->rq);
+ entity = drm_sched_rq_select_entity(sched);
if (!entity)
break; /* No more work */
@@ -1028,15 +1028,6 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
sched->score = score ? score : &sched->_score;
sched->dev = dev;
- if (sched->rq) {
- /* Not an error, but warn anyway so drivers can
- * fine-tune their DRM calling order, and return all
- * is good.
- */
- drm_warn(sched, "%s: scheduler already initialized!\n", __func__);
- return 0;
- }
-
if (submit_wq) {
sched->submit_wq = submit_wq;
sched->own_submit_wq = false;
@@ -1054,11 +1045,7 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
sched->own_submit_wq = true;
}
- sched->rq = kmalloc(sizeof(*sched->rq), GFP_KERNEL | __GFP_ZERO);
- if (!sched->rq)
- goto Out_check_own;
-
- drm_sched_rq_init(sched, sched->rq);
+ drm_sched_rq_init(sched);
init_waitqueue_head(&sched->job_scheduled);
INIT_LIST_HEAD(&sched->pending_list);
@@ -1072,12 +1059,6 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
sched->pause_submit = false;
sched->ready = true;
return 0;
-
-Out_check_own:
- if (sched->own_submit_wq)
- destroy_workqueue(sched->submit_wq);
- drm_err(sched, "%s: Failed to setup GPU scheduler--out of memory\n", __func__);
- return -ENOMEM;
}
EXPORT_SYMBOL(drm_sched_init);
@@ -1104,7 +1085,7 @@ EXPORT_SYMBOL(drm_sched_init);
void drm_sched_fini(struct drm_gpu_scheduler *sched)
{
- struct drm_sched_rq *rq = sched->rq;
+ struct drm_sched_rq *rq = &sched->rq;
struct drm_sched_entity *s_entity;
drm_sched_wqueue_stop(sched);
@@ -1128,8 +1109,6 @@ void drm_sched_fini(struct drm_gpu_scheduler *sched)
if (sched->own_submit_wq)
destroy_workqueue(sched->submit_wq);
sched->ready = false;
- kfree(sched->rq);
- sched->rq = NULL;
}
EXPORT_SYMBOL(drm_sched_fini);
@@ -1146,7 +1125,7 @@ void drm_sched_increase_karma(struct drm_sched_job *bad)
{
struct drm_gpu_scheduler *sched = bad->sched;
struct drm_sched_entity *entity, *tmp;
- struct drm_sched_rq *rq = sched->rq;
+ struct drm_sched_rq *rq = &sched->rq;
/* don't change @bad's karma if it's from KERNEL RQ,
* because sometimes GPU hang would cause kernel jobs (like VM updating jobs)
diff --git a/drivers/gpu/drm/scheduler/sched_rq.c b/drivers/gpu/drm/scheduler/sched_rq.c
index e96c8ca9c54b..2956d719c42d 100644
--- a/drivers/gpu/drm/scheduler/sched_rq.c
+++ b/drivers/gpu/drm/scheduler/sched_rq.c
@@ -47,13 +47,13 @@ static void __drm_sched_rq_add_tree_locked(struct drm_sched_entity *entity,
*
* Initializes a scheduler runqueue.
*/
-void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
- struct drm_sched_rq *rq)
+void drm_sched_rq_init(struct drm_gpu_scheduler *sched)
{
+ struct drm_sched_rq *rq = &sched->rq;
+
spin_lock_init(&rq->lock);
INIT_LIST_HEAD(&rq->entities);
rq->rb_tree_root = RB_ROOT_CACHED;
- rq->sched = sched;
}
/**
@@ -71,7 +71,7 @@ drm_sched_rq_add_entity(struct drm_sched_rq *rq,
struct drm_sched_entity *entity,
ktime_t ts)
{
- struct drm_gpu_scheduler *sched;
+ struct drm_gpu_scheduler *sched = container_of(rq, typeof(*sched), rq);
if (entity->stopped) {
DRM_ERROR("Trying to push to a killed entity\n");
@@ -81,7 +81,6 @@ drm_sched_rq_add_entity(struct drm_sched_rq *rq,
spin_lock(&entity->lock);
spin_lock(&rq->lock);
- sched = rq->sched;
atomic_inc(sched->score);
if (!list_empty(&entity->list))
@@ -108,6 +107,8 @@ drm_sched_rq_add_entity(struct drm_sched_rq *rq,
void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
struct drm_sched_entity *entity)
{
+ struct drm_gpu_scheduler *sched = container_of(rq, typeof(*sched), rq);
+
lockdep_assert_held(&entity->lock);
if (list_empty(&entity->list))
@@ -115,7 +116,7 @@ void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
spin_lock(&rq->lock);
- atomic_dec(rq->sched->score);
+ atomic_dec(sched->score);
list_del_init(&entity->list);
if (!RB_EMPTY_NODE(&entity->rb_tree_node))
@@ -175,10 +176,10 @@ void drm_sched_rq_update_deadline(struct drm_sched_rq *rq,
* Return an entity if one is found or NULL if no ready entity was found.
*/
struct drm_sched_entity *
-drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched,
- struct drm_sched_rq *rq)
+drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched)
{
struct drm_sched_entity *entity = NULL;
+ struct drm_sched_rq *rq = &sched->rq;
struct rb_node *rb;
spin_lock(&rq->lock);
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index c68dce8af063..7b29f45aa1da 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -238,7 +238,6 @@ struct drm_sched_entity {
/**
* struct drm_sched_rq - queue of entities to be scheduled.
*
- * @sched: the scheduler to which this rq belongs to.
* @lock: protects @entities, @rb_tree_root and @rr_deadline.
* @entities: list of the entities to be scheduled.
* @rb_tree_root: root of time based priority queue of entities for FIFO scheduling
@@ -248,8 +247,6 @@ struct drm_sched_entity {
* the next entity to emit commands from.
*/
struct drm_sched_rq {
- struct drm_gpu_scheduler *sched;
-
spinlock_t lock;
/* Following members are protected by the @lock: */
ktime_t rr_deadline;
@@ -518,7 +515,7 @@ struct drm_gpu_scheduler {
atomic_t credit_count;
long timeout;
const char *name;
- struct drm_sched_rq *rq;
+ struct drm_sched_rq rq;
wait_queue_head_t job_scheduled;
atomic64_t job_id_count;
struct workqueue_struct *submit_wq;
@@ -585,8 +582,7 @@ bool drm_sched_dependency_optimized(struct dma_fence* fence,
struct drm_sched_entity *entity);
void drm_sched_fault(struct drm_gpu_scheduler *sched);
-void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
- struct drm_sched_rq *rq);
+void drm_sched_rq_init(struct drm_gpu_scheduler *sched);
struct drm_gpu_scheduler *
drm_sched_rq_add_entity(struct drm_sched_rq *rq,
@@ -598,8 +594,7 @@ void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
void drm_sched_rq_pop_entity(struct drm_sched_rq *rq,
struct drm_sched_entity *entity);
struct drm_sched_entity *
-drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched,
- struct drm_sched_rq *rq);
+drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched);
void drm_sched_rq_update_deadline(struct drm_sched_rq *rq,
struct drm_sched_entity *entity,
ktime_t deadline);
--
2.47.1
^ permalink raw reply related [flat|nested] 61+ messages in thread* Re: [RFC 12/14] drm/sched: Embed run queue singleton into the scheduler
2024-12-30 16:52 ` [RFC 12/14] drm/sched: Embed run queue singleton into the scheduler Tvrtko Ursulin
@ 2024-12-31 2:39 ` kernel test robot
0 siblings, 0 replies; 61+ messages in thread
From: kernel test robot @ 2024-12-31 2:39 UTC (permalink / raw)
To: Tvrtko Ursulin; +Cc: oe-kbuild-all
Hi Tvrtko,
[This is a private test report for your RFC patch.]
kernel test robot noticed the following build warnings:
[auto build test WARNING on drm-exynos/exynos-drm-next]
[also build test WARNING on linus/master v6.13-rc5 next-20241220]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Tvrtko-Ursulin/drm-sched-Delete-unused-update_job_credits/20241231-011327
base: https://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git exynos-drm-next
patch link: https://lore.kernel.org/r/20241230165259.95855-13-tursulin%40igalia.com
patch subject: [RFC 12/14] drm/sched: Embed run queue singleton into the scheduler
config: s390-randconfig-001-20241231 (https://download.01.org/0day-ci/archive/20241231/202412311056.o5TzUipo-lkp@intel.com/config)
compiler: s390-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241231/202412311056.o5TzUipo-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202412311056.o5TzUipo-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/gpu/drm/scheduler/sched_rq.c:51: warning: Excess function parameter 'rq' description in 'drm_sched_rq_init'
drivers/gpu/drm/scheduler/sched_rq.c:73: warning: Function parameter or struct member 'ts' not described in 'drm_sched_rq_add_entity'
>> drivers/gpu/drm/scheduler/sched_rq.c:180: warning: Excess function parameter 'rq' description in 'drm_sched_rq_select_entity'
vim +51 drivers/gpu/drm/scheduler/sched_rq.c
03348b1b12c10a Tvrtko Ursulin 2024-12-30 41
03348b1b12c10a Tvrtko Ursulin 2024-12-30 42 /**
03348b1b12c10a Tvrtko Ursulin 2024-12-30 43 * drm_sched_rq_init - initialize a given run queue struct
03348b1b12c10a Tvrtko Ursulin 2024-12-30 44 *
03348b1b12c10a Tvrtko Ursulin 2024-12-30 45 * @sched: scheduler instance to associate with this run queue
03348b1b12c10a Tvrtko Ursulin 2024-12-30 46 * @rq: scheduler run queue
03348b1b12c10a Tvrtko Ursulin 2024-12-30 47 *
03348b1b12c10a Tvrtko Ursulin 2024-12-30 48 * Initializes a scheduler runqueue.
03348b1b12c10a Tvrtko Ursulin 2024-12-30 49 */
681ae19ad5eaac Tvrtko Ursulin 2024-12-30 50 void drm_sched_rq_init(struct drm_gpu_scheduler *sched)
03348b1b12c10a Tvrtko Ursulin 2024-12-30 @51 {
681ae19ad5eaac Tvrtko Ursulin 2024-12-30 52 struct drm_sched_rq *rq = &sched->rq;
681ae19ad5eaac Tvrtko Ursulin 2024-12-30 53
03348b1b12c10a Tvrtko Ursulin 2024-12-30 54 spin_lock_init(&rq->lock);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 55 INIT_LIST_HEAD(&rq->entities);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 56 rq->rb_tree_root = RB_ROOT_CACHED;
03348b1b12c10a Tvrtko Ursulin 2024-12-30 57 }
03348b1b12c10a Tvrtko Ursulin 2024-12-30 58
03348b1b12c10a Tvrtko Ursulin 2024-12-30 59 /**
03348b1b12c10a Tvrtko Ursulin 2024-12-30 60 * drm_sched_rq_add_entity - add an entity
03348b1b12c10a Tvrtko Ursulin 2024-12-30 61 *
03348b1b12c10a Tvrtko Ursulin 2024-12-30 62 * @rq: scheduler run queue
03348b1b12c10a Tvrtko Ursulin 2024-12-30 63 * @entity: scheduler entity
03348b1b12c10a Tvrtko Ursulin 2024-12-30 64 *
03348b1b12c10a Tvrtko Ursulin 2024-12-30 65 * Adds a scheduler entity to the run queue.
03348b1b12c10a Tvrtko Ursulin 2024-12-30 66 *
03348b1b12c10a Tvrtko Ursulin 2024-12-30 67 * Returns a DRM scheduler pre-selected to handle this entity.
03348b1b12c10a Tvrtko Ursulin 2024-12-30 68 */
03348b1b12c10a Tvrtko Ursulin 2024-12-30 69 struct drm_gpu_scheduler *
03348b1b12c10a Tvrtko Ursulin 2024-12-30 70 drm_sched_rq_add_entity(struct drm_sched_rq *rq,
03348b1b12c10a Tvrtko Ursulin 2024-12-30 71 struct drm_sched_entity *entity,
03348b1b12c10a Tvrtko Ursulin 2024-12-30 72 ktime_t ts)
03348b1b12c10a Tvrtko Ursulin 2024-12-30 73 {
681ae19ad5eaac Tvrtko Ursulin 2024-12-30 74 struct drm_gpu_scheduler *sched = container_of(rq, typeof(*sched), rq);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 75
03348b1b12c10a Tvrtko Ursulin 2024-12-30 76 if (entity->stopped) {
03348b1b12c10a Tvrtko Ursulin 2024-12-30 77 DRM_ERROR("Trying to push to a killed entity\n");
03348b1b12c10a Tvrtko Ursulin 2024-12-30 78 return NULL;
03348b1b12c10a Tvrtko Ursulin 2024-12-30 79 }
03348b1b12c10a Tvrtko Ursulin 2024-12-30 80
03348b1b12c10a Tvrtko Ursulin 2024-12-30 81 spin_lock(&entity->lock);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 82 spin_lock(&rq->lock);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 83
03348b1b12c10a Tvrtko Ursulin 2024-12-30 84 atomic_inc(sched->score);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 85
03348b1b12c10a Tvrtko Ursulin 2024-12-30 86 if (!list_empty(&entity->list))
03348b1b12c10a Tvrtko Ursulin 2024-12-30 87 list_add_tail(&entity->list, &rq->entities);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 88
03348b1b12c10a Tvrtko Ursulin 2024-12-30 89 if (!RB_EMPTY_NODE(&entity->rb_tree_node))
54d8ff2da30f08 Tvrtko Ursulin 2024-12-30 90 __drm_sched_rq_remove_tree_locked(entity, rq);
54d8ff2da30f08 Tvrtko Ursulin 2024-12-30 91 __drm_sched_rq_add_tree_locked(entity, rq, ts);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 92
03348b1b12c10a Tvrtko Ursulin 2024-12-30 93 spin_unlock(&rq->lock);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 94 spin_unlock(&entity->lock);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 95
03348b1b12c10a Tvrtko Ursulin 2024-12-30 96 return sched;
03348b1b12c10a Tvrtko Ursulin 2024-12-30 97 }
03348b1b12c10a Tvrtko Ursulin 2024-12-30 98
03348b1b12c10a Tvrtko Ursulin 2024-12-30 99 /**
03348b1b12c10a Tvrtko Ursulin 2024-12-30 100 * drm_sched_rq_remove_entity - remove an entity
03348b1b12c10a Tvrtko Ursulin 2024-12-30 101 *
03348b1b12c10a Tvrtko Ursulin 2024-12-30 102 * @rq: scheduler run queue
03348b1b12c10a Tvrtko Ursulin 2024-12-30 103 * @entity: scheduler entity
03348b1b12c10a Tvrtko Ursulin 2024-12-30 104 *
03348b1b12c10a Tvrtko Ursulin 2024-12-30 105 * Removes a scheduler entity from the run queue.
03348b1b12c10a Tvrtko Ursulin 2024-12-30 106 */
03348b1b12c10a Tvrtko Ursulin 2024-12-30 107 void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
03348b1b12c10a Tvrtko Ursulin 2024-12-30 108 struct drm_sched_entity *entity)
03348b1b12c10a Tvrtko Ursulin 2024-12-30 109 {
681ae19ad5eaac Tvrtko Ursulin 2024-12-30 110 struct drm_gpu_scheduler *sched = container_of(rq, typeof(*sched), rq);
681ae19ad5eaac Tvrtko Ursulin 2024-12-30 111
03348b1b12c10a Tvrtko Ursulin 2024-12-30 112 lockdep_assert_held(&entity->lock);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 113
03348b1b12c10a Tvrtko Ursulin 2024-12-30 114 if (list_empty(&entity->list))
03348b1b12c10a Tvrtko Ursulin 2024-12-30 115 return;
03348b1b12c10a Tvrtko Ursulin 2024-12-30 116
03348b1b12c10a Tvrtko Ursulin 2024-12-30 117 spin_lock(&rq->lock);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 118
681ae19ad5eaac Tvrtko Ursulin 2024-12-30 119 atomic_dec(sched->score);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 120 list_del_init(&entity->list);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 121
03348b1b12c10a Tvrtko Ursulin 2024-12-30 122 if (!RB_EMPTY_NODE(&entity->rb_tree_node))
54d8ff2da30f08 Tvrtko Ursulin 2024-12-30 123 __drm_sched_rq_remove_tree_locked(entity, rq);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 124
03348b1b12c10a Tvrtko Ursulin 2024-12-30 125 spin_unlock(&rq->lock);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 126 }
03348b1b12c10a Tvrtko Ursulin 2024-12-30 127
03348b1b12c10a Tvrtko Ursulin 2024-12-30 128 void drm_sched_rq_pop_entity(struct drm_sched_rq *rq,
03348b1b12c10a Tvrtko Ursulin 2024-12-30 129 struct drm_sched_entity *entity)
03348b1b12c10a Tvrtko Ursulin 2024-12-30 130 {
03348b1b12c10a Tvrtko Ursulin 2024-12-30 131 struct drm_sched_job *next_job;
03348b1b12c10a Tvrtko Ursulin 2024-12-30 132
03348b1b12c10a Tvrtko Ursulin 2024-12-30 133 next_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
03348b1b12c10a Tvrtko Ursulin 2024-12-30 134
03348b1b12c10a Tvrtko Ursulin 2024-12-30 135 spin_lock(&entity->lock);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 136 spin_lock(&rq->lock);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 137
54d8ff2da30f08 Tvrtko Ursulin 2024-12-30 138 __drm_sched_rq_remove_tree_locked(entity, rq);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 139
03348b1b12c10a Tvrtko Ursulin 2024-12-30 140 if (next_job) {
03348b1b12c10a Tvrtko Ursulin 2024-12-30 141 ktime_t ts;
03348b1b12c10a Tvrtko Ursulin 2024-12-30 142
54d8ff2da30f08 Tvrtko Ursulin 2024-12-30 143 ts = drm_sched_entity_get_job_deadline(entity, next_job);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 144
54d8ff2da30f08 Tvrtko Ursulin 2024-12-30 145 __drm_sched_rq_add_tree_locked(entity, rq, ts);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 146 }
03348b1b12c10a Tvrtko Ursulin 2024-12-30 147
03348b1b12c10a Tvrtko Ursulin 2024-12-30 148 spin_unlock(&rq->lock);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 149 spin_unlock(&entity->lock);
03348b1b12c10a Tvrtko Ursulin 2024-12-30 150 }
03348b1b12c10a Tvrtko Ursulin 2024-12-30 151
4adee88d458462 Tvrtko Ursulin 2024-12-30 152 void drm_sched_rq_update_deadline(struct drm_sched_rq *rq,
4adee88d458462 Tvrtko Ursulin 2024-12-30 153 struct drm_sched_entity *entity,
4adee88d458462 Tvrtko Ursulin 2024-12-30 154 ktime_t deadline)
4adee88d458462 Tvrtko Ursulin 2024-12-30 155 {
4adee88d458462 Tvrtko Ursulin 2024-12-30 156 lockdep_assert_held(&entity->lock);
4adee88d458462 Tvrtko Ursulin 2024-12-30 157
4adee88d458462 Tvrtko Ursulin 2024-12-30 158 if (ktime_before(deadline, entity->oldest_job_waiting)) {
4adee88d458462 Tvrtko Ursulin 2024-12-30 159 spin_lock(&rq->lock);
4adee88d458462 Tvrtko Ursulin 2024-12-30 160 if (!RB_EMPTY_NODE(&entity->rb_tree_node)) {
4adee88d458462 Tvrtko Ursulin 2024-12-30 161 __drm_sched_rq_remove_tree_locked(entity, rq);
4adee88d458462 Tvrtko Ursulin 2024-12-30 162 __drm_sched_rq_add_tree_locked(entity, rq, deadline);
4adee88d458462 Tvrtko Ursulin 2024-12-30 163 }
4adee88d458462 Tvrtko Ursulin 2024-12-30 164 spin_unlock(&rq->lock);
4adee88d458462 Tvrtko Ursulin 2024-12-30 165 }
4adee88d458462 Tvrtko Ursulin 2024-12-30 166 }
4adee88d458462 Tvrtko Ursulin 2024-12-30 167
03348b1b12c10a Tvrtko Ursulin 2024-12-30 168 /**
03348b1b12c10a Tvrtko Ursulin 2024-12-30 169 * drm_sched_rq_select_entity - Select an entity which provides a job to run
03348b1b12c10a Tvrtko Ursulin 2024-12-30 170 *
03348b1b12c10a Tvrtko Ursulin 2024-12-30 171 * @sched: the gpu scheduler
03348b1b12c10a Tvrtko Ursulin 2024-12-30 172 * @rq: scheduler run queue to check.
03348b1b12c10a Tvrtko Ursulin 2024-12-30 173 *
03348b1b12c10a Tvrtko Ursulin 2024-12-30 174 * Find oldest waiting ready entity.
03348b1b12c10a Tvrtko Ursulin 2024-12-30 175 *
85eeed2590b5c2 Tvrtko Ursulin 2024-12-30 176 * Return an entity if one is found or NULL if no ready entity was found.
03348b1b12c10a Tvrtko Ursulin 2024-12-30 177 */
03348b1b12c10a Tvrtko Ursulin 2024-12-30 178 struct drm_sched_entity *
681ae19ad5eaac Tvrtko Ursulin 2024-12-30 179 drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched)
03348b1b12c10a Tvrtko Ursulin 2024-12-30 @180 {
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 61+ messages in thread
* [RFC 13/14] dma-fence: Add helper for custom fence context when merging fences
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
` (11 preceding siblings ...)
2024-12-30 16:52 ` [RFC 12/14] drm/sched: Embed run queue singleton into the scheduler Tvrtko Ursulin
@ 2024-12-30 16:52 ` Tvrtko Ursulin
2024-12-30 16:52 ` [RFC 14/14] drm/sched: Resolve all job dependencies in one go Tvrtko Ursulin
` (4 subsequent siblings)
17 siblings, 0 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2024-12-30 16:52 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Add a dma_fence_unwrap_merge_context() helper which works exactly the same
as the existing dma_fence_unwrap_merge() apart that instead of always
allocating a new fence context it allows the caller to specify it.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <pstanner@redhat.com>
---
drivers/dma-buf/dma-fence-unwrap.c | 8 ++++----
include/linux/dma-fence-unwrap.h | 31 ++++++++++++++++++++++++++++--
2 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/drivers/dma-buf/dma-fence-unwrap.c b/drivers/dma-buf/dma-fence-unwrap.c
index 2a059ac0ed27..fd9813a50532 100644
--- a/drivers/dma-buf/dma-fence-unwrap.c
+++ b/drivers/dma-buf/dma-fence-unwrap.c
@@ -80,7 +80,8 @@ static int fence_cmp(const void *_a, const void *_b)
}
/* Implementation for the dma_fence_merge() marco, don't use directly */
-struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
+struct dma_fence *__dma_fence_unwrap_merge(u64 context,
+ unsigned int num_fences,
struct dma_fence **fences,
struct dma_fence_unwrap *iter)
{
@@ -156,9 +157,8 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
count = ++j;
if (count > 1) {
- result = dma_fence_array_create(count, array,
- dma_fence_context_alloc(1),
- 1, false);
+ result = dma_fence_array_create(count, array, context, 1,
+ false);
if (!result) {
for (i = 0; i < count; i++)
dma_fence_put(array[i]);
diff --git a/include/linux/dma-fence-unwrap.h b/include/linux/dma-fence-unwrap.h
index 66b1e56fbb81..12e8c43848ce 100644
--- a/include/linux/dma-fence-unwrap.h
+++ b/include/linux/dma-fence-unwrap.h
@@ -8,6 +8,8 @@
#ifndef __LINUX_DMA_FENCE_UNWRAP_H
#define __LINUX_DMA_FENCE_UNWRAP_H
+#include <linux/types.h>
+
struct dma_fence;
/**
@@ -48,7 +50,8 @@ struct dma_fence *dma_fence_unwrap_next(struct dma_fence_unwrap *cursor);
for (fence = dma_fence_unwrap_first(head, cursor); fence; \
fence = dma_fence_unwrap_next(cursor))
-struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
+struct dma_fence *__dma_fence_unwrap_merge(u64 context,
+ unsigned int num_fences,
struct dma_fence **fences,
struct dma_fence_unwrap *cursors);
@@ -69,7 +72,31 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
struct dma_fence *__f[] = { __VA_ARGS__ }; \
struct dma_fence_unwrap __c[ARRAY_SIZE(__f)]; \
\
- __dma_fence_unwrap_merge(ARRAY_SIZE(__f), __f, __c); \
+ __dma_fence_unwrap_merge(dma_fence_context_alloc(1), \
+ ARRAY_SIZE(__f), __f, __c); \
+ })
+
+/**
+ * dma_fence_unwrap_merge_context - unwrap and merge fences with context
+ *
+ * All fences given as parameters are unwrapped and merged back together as flat
+ * dma_fence_array. Useful if multiple containers need to be merged together.
+ *
+ * Implemented as a macro to allocate the necessary arrays on the stack and
+ * account the stack frame size to the caller.
+ *
+ * Fence context is passed in and not automatically allocated.
+ *
+ * Returns NULL on memory allocation failure, a dma_fence object representing
+ * all the given fences otherwise.
+ */
+#define dma_fence_unwrap_merge_context(context, ...) \
+ ({ \
+ struct dma_fence *__f[] = { __VA_ARGS__ }; \
+ struct dma_fence_unwrap __c[ARRAY_SIZE(__f)]; \
+ \
+ __dma_fence_unwrap_merge((context), \
+ ARRAY_SIZE(__f), __f, __c); \
})
#endif
--
2.47.1
^ permalink raw reply related [flat|nested] 61+ messages in thread* [RFC 14/14] drm/sched: Resolve all job dependencies in one go
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
` (12 preceding siblings ...)
2024-12-30 16:52 ` [RFC 13/14] dma-fence: Add helper for custom fence context when merging fences Tvrtko Ursulin
@ 2024-12-30 16:52 ` Tvrtko Ursulin
2024-12-31 6:01 ` kernel test robot
2025-01-02 13:09 ` [RFC 00/14] Deadline scheduler and other ideas Philipp Stanner
` (3 subsequent siblings)
17 siblings, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2024-12-30 16:52 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Instead of maintaining the dependencies in an xarray and then handling
them one by one every time the scheduler picks the same entity for
execution (requiring potentially multiple worker invocations for a job
to actually get submitted), lets maintain them in a dma_fence_array and
allow the worker to resolved them in one go.
The slightly increased cost of dma_fence_merge_unwrap() when adding
many dependencies (which is not a typical case as far as I can see) is
hopefully annulled by reduced latency on the submission path.
On the implementation side we allocate two more fence context numbers
associated with each entity. One for the job dependency array and
another for the entity cleanup path (seqnos are shared with the job).
On the entity cleanup path we create an second dma-fence-array so we
can add a single callback per job, which also handles all dependencies
at once.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <pstanner@redhat.com>
---
drivers/gpu/drm/scheduler/sched_entity.c | 101 +++++++++++++++-------
drivers/gpu/drm/scheduler/sched_main.c | 104 ++++++++++++-----------
include/drm/gpu_scheduler.h | 14 +--
3 files changed, 126 insertions(+), 93 deletions(-)
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index dc5105ca8381..6c7325719d75 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -21,6 +21,8 @@
*
*/
+#include <linux/dma-fence.h>
+#include <linux/dma-fence-array.h>
#include <linux/kthread.h>
#include <linux/slab.h>
#include <linux/completion.h>
@@ -92,7 +94,7 @@ int drm_sched_entity_init(struct drm_sched_entity *entity,
spsc_queue_init(&entity->job_queue);
atomic_set(&entity->fence_seq, 0);
- entity->fence_context = dma_fence_context_alloc(2);
+ entity->fence_context = dma_fence_context_alloc(4);
return 0;
}
@@ -183,39 +185,78 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f,
{
struct drm_sched_job *job = container_of(cb, struct drm_sched_job,
finish_cb);
- unsigned long index;
dma_fence_put(f);
- /* Wait for all dependencies to avoid data corruptions */
- xa_for_each(&job->dependencies, index, f) {
- struct drm_sched_fence *s_fence = to_drm_sched_fence(f);
-
- if (s_fence && f == &s_fence->scheduled) {
- /* The dependencies array had a reference on the scheduled
- * fence, and the finished fence refcount might have
- * dropped to zero. Use dma_fence_get_rcu() so we get
- * a NULL fence in that case.
+ /* Wait for all dependencies to avoid data corruption */
+ if (!dma_fence_add_callback(job->deps_finished, &job->finish_cb,
+ drm_sched_entity_kill_jobs_cb))
+ return;
+
+ INIT_WORK(&job->work, drm_sched_entity_kill_jobs_work);
+ schedule_work(&job->work);
+}
+
+static struct dma_fence *job_deps_finished(struct drm_sched_job *job)
+{
+ struct dma_fence_array *array;
+ unsigned int i, j, num_fences;
+ struct dma_fence **fences;
+
+ if (job->deps) {
+ array = to_dma_fence_array(job->deps);
+
+ if (array)
+ num_fences = array->num_fences;
+ else
+ num_fences = 1;
+ } else {
+ num_fences = 0;
+ }
+
+ if (!num_fences)
+ return dma_fence_get_stub();
+
+ fences = kmalloc_array(num_fences, sizeof(*fences), GFP_KERNEL);
+ if (!fences)
+ return NULL;
+
+ if (num_fences == 1)
+ fences[0] = job->deps;
+ else
+ memcpy(fences, array->fences, num_fences * sizeof(*fences));
+
+ for (i = 0, j = 0; i < num_fences; i++) {
+ struct dma_fence *fence = dma_fence_get(fences[i]);
+ struct drm_sched_fence *s_fence;
+
+ s_fence = to_drm_sched_fence(fence);
+ if (s_fence && fence == &s_fence->scheduled) {
+ /*
+ * The dependencies array had a reference on the
+ * scheduled fence, and the finished fence refcount
+ * might have dropped to zero. Use dma_fence_get_rcu()
+ * so we get a NULL fence in that case.
*/
- f = dma_fence_get_rcu(&s_fence->finished);
+ fence = dma_fence_get_rcu(&s_fence->finished);
- /* Now that we have a reference on the finished fence,
+ /*
+ * Now that we have a reference on the finished fence,
* we can release the reference the dependencies array
* had on the scheduled fence.
*/
dma_fence_put(&s_fence->scheduled);
}
- xa_erase(&job->dependencies, index);
- if (f && !dma_fence_add_callback(f, &job->finish_cb,
- drm_sched_entity_kill_jobs_cb))
- return;
-
- dma_fence_put(f);
+ if (fence)
+ fences[j++] = fence;
}
- INIT_WORK(&job->work, drm_sched_entity_kill_jobs_work);
- schedule_work(&job->work);
+ array = dma_fence_array_create(j, fences,
+ job->entity->fence_context + 3, 1,
+ false);
+
+ return array ? &array->base : NULL;
}
/* Remove the entity from the scheduler and kill all pending jobs */
@@ -242,6 +283,11 @@ static void drm_sched_entity_kill(struct drm_sched_entity *entity)
struct drm_sched_fence *s_fence = job->s_fence;
dma_fence_get(&s_fence->finished);
+
+ job->deps_finished = job_deps_finished(job);
+ if (WARN_ON_ONCE(!job->deps_finished))
+ continue;
+
if (!prev || dma_fence_add_callback(prev, &job->finish_cb,
drm_sched_entity_kill_jobs_cb))
drm_sched_entity_kill_jobs_cb(NULL, &job->finish_cb);
@@ -435,17 +481,8 @@ static struct dma_fence *
drm_sched_job_dependency(struct drm_sched_job *job,
struct drm_sched_entity *entity)
{
- struct dma_fence *f;
-
- /* We keep the fence around, so we can iterate over all dependencies
- * in drm_sched_entity_kill_jobs_cb() to ensure all deps are signaled
- * before killing the job.
- */
- f = xa_load(&job->dependencies, job->last_dependency);
- if (f) {
- job->last_dependency++;
- return dma_fence_get(f);
- }
+ if (job->deps && !dma_fence_is_signaled(job->deps))
+ return dma_fence_get(job->deps);
if (job->sched->ops->prepare_job)
return job->sched->ops->prepare_job(job, entity);
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index 67bf0bec3309..869d831e94aa 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -69,6 +69,8 @@
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/completion.h>
+#include <linux/dma-fence-array.h>
+#include <linux/dma-fence-unwrap.h>
#include <linux/dma-resv.h>
#include <uapi/linux/sched/types.h>
@@ -564,8 +566,6 @@ int drm_sched_job_init(struct drm_sched_job *job,
INIT_LIST_HEAD(&job->list);
- xa_init_flags(&job->dependencies, XA_FLAGS_ALLOC);
-
return 0;
}
EXPORT_SYMBOL(drm_sched_job_init);
@@ -614,46 +614,34 @@ int drm_sched_job_add_dependency(struct drm_sched_job *job,
struct dma_fence *fence)
{
struct drm_sched_entity *entity = job->entity;
- struct dma_fence *entry;
- unsigned long index;
- u32 id = 0;
- int ret;
+ struct dma_fence *deps;
+ int ret = 0;
if (!fence)
return 0;
- if (fence->context == entity->fence_context ||
- fence->context == entity->fence_context + 1) {
+ if (fence->context >= entity->fence_context &&
+ fence->context <= entity->fence_context + 3) {
/*
* Fence is a scheduled/finished fence from a job
* which belongs to the same entity, we can ignore
* fences from ourself
*/
- dma_fence_put(fence);
- return 0;
+ goto out_put;
}
- /* Deduplicate if we already depend on a fence from the same context.
- * This lets the size of the array of deps scale with the number of
- * engines involved, rather than the number of BOs.
- */
- xa_for_each(&job->dependencies, index, entry) {
- if (entry->context != fence->context)
- continue;
-
- if (dma_fence_is_later(fence, entry)) {
- dma_fence_put(entry);
- xa_store(&job->dependencies, index, fence, GFP_KERNEL);
- } else {
- dma_fence_put(fence);
- }
- return 0;
+ deps = dma_fence_unwrap_merge_context(entity->fence_context + 2,
+ job->deps, fence);
+ if (!deps) {
+ ret = -ENOMEM;
+ goto out_put;
}
- ret = xa_alloc(&job->dependencies, &id, fence, xa_limit_32b, GFP_KERNEL);
- if (ret != 0)
- dma_fence_put(fence);
+ dma_fence_put(job->deps);
+ job->deps = deps;
+out_put:
+ dma_fence_put(fence);
return ret;
}
EXPORT_SYMBOL(drm_sched_job_add_dependency);
@@ -745,26 +733,49 @@ int drm_sched_job_add_implicit_dependencies(struct drm_sched_job *job,
}
EXPORT_SYMBOL(drm_sched_job_add_implicit_dependencies);
+static bool
+can_replace_fence(struct drm_gpu_scheduler *sched,
+ struct drm_sched_fence *s_fence,
+ struct dma_fence *fence)
+{
+ if (fence->error || !s_fence || s_fence->sched != sched ||
+ test_bit(DRM_SCHED_FENCE_DONT_PIPELINE, &fence->flags))
+ return false;
+
+ return true;
+}
+
void drm_sched_job_prepare_dependecies(struct drm_sched_job *job)
{
struct drm_gpu_scheduler *sched = job->sched;
+ struct drm_sched_fence *s_fence;
+ struct dma_fence_array *array;
struct dma_fence *fence;
- unsigned long index;
- xa_for_each(&job->dependencies, index, fence) {
- struct drm_sched_fence *s_fence = to_drm_sched_fence(fence);
+ if (!job->deps)
+ return;
- if (fence->error || !s_fence || s_fence->sched != sched ||
- test_bit(DRM_SCHED_FENCE_DONT_PIPELINE, &fence->flags))
- continue;
+ array = to_dma_fence_array(job->deps);
+ if (!array) {
+ fence = job->deps;
+ s_fence = to_drm_sched_fence(fence);
+ if (can_replace_fence(sched, s_fence, fence)) {
+ job->deps = dma_fence_get(&s_fence->scheduled);
+ dma_fence_put(fence);
+ }
+ } else {
+ unsigned i;
- /*
- * Fence is from the same scheduler, only need to wait for
- * it to be scheduled.
- */
- xa_store(&job->dependencies, index,
- dma_fence_get(&s_fence->scheduled), GFP_KERNEL);
- dma_fence_put(fence);
+ for (i = 0; i < array->num_fences; i++) {
+ fence = array->fences[i];
+ s_fence = to_drm_sched_fence(fence);
+ if (can_replace_fence(sched, s_fence, fence)) {
+ array->fences[i] =
+ dma_fence_get(&s_fence->scheduled);
+ dma_fence_put(fence);
+ }
+ }
+ array->base.seqno = job->s_fence->scheduled.seqno;
}
}
@@ -783,24 +794,17 @@ void drm_sched_job_prepare_dependecies(struct drm_sched_job *job)
*/
void drm_sched_job_cleanup(struct drm_sched_job *job)
{
- struct dma_fence *fence;
- unsigned long index;
-
if (kref_read(&job->s_fence->finished.refcount)) {
/* drm_sched_job_arm() has been called */
dma_fence_put(&job->s_fence->finished);
+ dma_fence_put(job->deps);
+ dma_fence_put(job->deps_finished);
} else {
/* aborted job before committing to run it */
drm_sched_fence_free(job->s_fence);
}
job->s_fence = NULL;
-
- xa_for_each(&job->dependencies, index, fence) {
- dma_fence_put(fence);
- }
- xa_destroy(&job->dependencies);
-
}
EXPORT_SYMBOL(drm_sched_job_cleanup);
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index 7b29f45aa1da..525f1c1dd9c9 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -27,7 +27,6 @@
#include <drm/spsc_queue.h>
#include <linux/dma-fence.h>
#include <linux/completion.h>
-#include <linux/xarray.h>
#include <linux/workqueue.h>
#define MAX_WAIT_SCHED_ENTITY_Q_EMPTY msecs_to_jiffies(1000)
@@ -360,17 +359,10 @@ struct drm_sched_job {
enum drm_sched_priority s_priority;
struct drm_sched_entity *entity;
struct dma_fence_cb cb;
- /**
- * @dependencies:
- *
- * Contains the dependencies as struct dma_fence for this job, see
- * drm_sched_job_add_dependency() and
- * drm_sched_job_add_implicit_dependencies().
- */
- struct xarray dependencies;
- /** @last_dependency: tracks @dependencies as they signal */
- unsigned long last_dependency;
+ struct dma_fence stub_fence;
+ struct dma_fence *deps;
+ struct dma_fence *deps_finished;
/**
* @submit_ts:
--
2.47.1
^ permalink raw reply related [flat|nested] 61+ messages in thread* Re: [RFC 14/14] drm/sched: Resolve all job dependencies in one go
2024-12-30 16:52 ` [RFC 14/14] drm/sched: Resolve all job dependencies in one go Tvrtko Ursulin
@ 2024-12-31 6:01 ` kernel test robot
0 siblings, 0 replies; 61+ messages in thread
From: kernel test robot @ 2024-12-31 6:01 UTC (permalink / raw)
To: Tvrtko Ursulin; +Cc: oe-kbuild-all
Hi Tvrtko,
[This is a private test report for your RFC patch.]
kernel test robot noticed the following build errors:
[auto build test ERROR on drm-exynos/exynos-drm-next]
[also build test ERROR on linus/master v6.13-rc5 next-20241220]
[cannot apply to drm-intel/for-linux-next drm-intel/for-linux-next-fixes drm-misc/drm-misc-next drm-tip/drm-tip]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Tvrtko-Ursulin/drm-sched-Delete-unused-update_job_credits/20241231-011327
base: https://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git exynos-drm-next
patch link: https://lore.kernel.org/r/20241230165259.95855-15-tursulin%40igalia.com
patch subject: [RFC 14/14] drm/sched: Resolve all job dependencies in one go
config: arm64-randconfig-003-20241231 (https://download.01.org/0day-ci/archive/20241231/202412311307.zMjN4cPE-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241231/202412311307.zMjN4cPE-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202412311307.zMjN4cPE-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from drivers/gpu/drm/imagination/pvr_context.h:13,
from drivers/gpu/drm/imagination/pvr_job.c:4:
drivers/gpu/drm/imagination/pvr_job.c: In function 'can_combine_jobs':
>> drivers/gpu/drm/imagination/pvr_job.c:612:36: error: 'struct drm_sched_job' has no member named 'dependencies'
612 | xa_for_each(&frag_job->base.dependencies, index, fence) {
| ^
include/linux/xarray.h:453:30: note: in definition of macro 'xa_for_each_range'
453 | entry = xa_find(xa, &index, last, XA_PRESENT); \
| ^~
include/linux/xarray.h:505:9: note: in expansion of macro 'xa_for_each_start'
505 | xa_for_each_start(xa, index, entry, 0)
| ^~~~~~~~~~~~~~~~~
drivers/gpu/drm/imagination/pvr_job.c:612:9: note: in expansion of macro 'xa_for_each'
612 | xa_for_each(&frag_job->base.dependencies, index, fence) {
| ^~~~~~~~~~~
>> drivers/gpu/drm/imagination/pvr_job.c:612:36: error: 'struct drm_sched_job' has no member named 'dependencies'
612 | xa_for_each(&frag_job->base.dependencies, index, fence) {
| ^
include/linux/xarray.h:455:36: note: in definition of macro 'xa_for_each_range'
455 | entry = xa_find_after(xa, &index, last, XA_PRESENT))
| ^~
include/linux/xarray.h:505:9: note: in expansion of macro 'xa_for_each_start'
505 | xa_for_each_start(xa, index, entry, 0)
| ^~~~~~~~~~~~~~~~~
drivers/gpu/drm/imagination/pvr_job.c:612:9: note: in expansion of macro 'xa_for_each'
612 | xa_for_each(&frag_job->base.dependencies, index, fence) {
| ^~~~~~~~~~~
--
In file included from drivers/gpu/drm/imagination/pvr_context.h:13,
from drivers/gpu/drm/imagination/pvr_queue.c:8:
drivers/gpu/drm/imagination/pvr_queue.c: In function 'job_count_remaining_native_deps':
>> drivers/gpu/drm/imagination/pvr_queue.c:361:31: error: 'struct drm_sched_job' has no member named 'dependencies'
361 | xa_for_each(&job->base.dependencies, index, fence) {
| ^
include/linux/xarray.h:453:30: note: in definition of macro 'xa_for_each_range'
453 | entry = xa_find(xa, &index, last, XA_PRESENT); \
| ^~
include/linux/xarray.h:505:9: note: in expansion of macro 'xa_for_each_start'
505 | xa_for_each_start(xa, index, entry, 0)
| ^~~~~~~~~~~~~~~~~
drivers/gpu/drm/imagination/pvr_queue.c:361:9: note: in expansion of macro 'xa_for_each'
361 | xa_for_each(&job->base.dependencies, index, fence) {
| ^~~~~~~~~~~
>> drivers/gpu/drm/imagination/pvr_queue.c:361:31: error: 'struct drm_sched_job' has no member named 'dependencies'
361 | xa_for_each(&job->base.dependencies, index, fence) {
| ^
include/linux/xarray.h:455:36: note: in definition of macro 'xa_for_each_range'
455 | entry = xa_find_after(xa, &index, last, XA_PRESENT))
| ^~
include/linux/xarray.h:505:9: note: in expansion of macro 'xa_for_each_start'
505 | xa_for_each_start(xa, index, entry, 0)
| ^~~~~~~~~~~~~~~~~
drivers/gpu/drm/imagination/pvr_queue.c:361:9: note: in expansion of macro 'xa_for_each'
361 | xa_for_each(&job->base.dependencies, index, fence) {
| ^~~~~~~~~~~
drivers/gpu/drm/imagination/pvr_queue.c: In function 'pvr_queue_get_paired_frag_job_dep':
drivers/gpu/drm/imagination/pvr_queue.c:471:36: error: 'struct drm_sched_job' has no member named 'dependencies'
471 | xa_for_each(&frag_job->base.dependencies, index, f) {
| ^
include/linux/xarray.h:453:30: note: in definition of macro 'xa_for_each_range'
453 | entry = xa_find(xa, &index, last, XA_PRESENT); \
| ^~
include/linux/xarray.h:505:9: note: in expansion of macro 'xa_for_each_start'
505 | xa_for_each_start(xa, index, entry, 0)
| ^~~~~~~~~~~~~~~~~
drivers/gpu/drm/imagination/pvr_queue.c:471:9: note: in expansion of macro 'xa_for_each'
471 | xa_for_each(&frag_job->base.dependencies, index, f) {
| ^~~~~~~~~~~
drivers/gpu/drm/imagination/pvr_queue.c:471:36: error: 'struct drm_sched_job' has no member named 'dependencies'
471 | xa_for_each(&frag_job->base.dependencies, index, f) {
| ^
include/linux/xarray.h:455:36: note: in definition of macro 'xa_for_each_range'
455 | entry = xa_find_after(xa, &index, last, XA_PRESENT))
| ^~
include/linux/xarray.h:505:9: note: in expansion of macro 'xa_for_each_start'
505 | xa_for_each_start(xa, index, entry, 0)
| ^~~~~~~~~~~~~~~~~
drivers/gpu/drm/imagination/pvr_queue.c:471:9: note: in expansion of macro 'xa_for_each'
471 | xa_for_each(&frag_job->base.dependencies, index, f) {
| ^~~~~~~~~~~
drivers/gpu/drm/imagination/pvr_queue.c: In function 'pvr_queue_submit_job_to_cccb':
drivers/gpu/drm/imagination/pvr_queue.c:618:31: error: 'struct drm_sched_job' has no member named 'dependencies'
618 | xa_for_each(&job->base.dependencies, index, fence) {
| ^
include/linux/xarray.h:453:30: note: in definition of macro 'xa_for_each_range'
453 | entry = xa_find(xa, &index, last, XA_PRESENT); \
| ^~
include/linux/xarray.h:505:9: note: in expansion of macro 'xa_for_each_start'
505 | xa_for_each_start(xa, index, entry, 0)
| ^~~~~~~~~~~~~~~~~
drivers/gpu/drm/imagination/pvr_queue.c:618:9: note: in expansion of macro 'xa_for_each'
618 | xa_for_each(&job->base.dependencies, index, fence) {
| ^~~~~~~~~~~
drivers/gpu/drm/imagination/pvr_queue.c:618:31: error: 'struct drm_sched_job' has no member named 'dependencies'
618 | xa_for_each(&job->base.dependencies, index, fence) {
| ^
include/linux/xarray.h:455:36: note: in definition of macro 'xa_for_each_range'
455 | entry = xa_find_after(xa, &index, last, XA_PRESENT))
| ^~
include/linux/xarray.h:505:9: note: in expansion of macro 'xa_for_each_start'
505 | xa_for_each_start(xa, index, entry, 0)
| ^~~~~~~~~~~~~~~~~
drivers/gpu/drm/imagination/pvr_queue.c:618:9: note: in expansion of macro 'xa_for_each'
618 | xa_for_each(&job->base.dependencies, index, fence) {
| ^~~~~~~~~~~
vim +612 drivers/gpu/drm/imagination/pvr_job.c
eaf01ee5ba28b9 Sarah Walker 2023-11-22 596
eaf01ee5ba28b9 Sarah Walker 2023-11-22 597 static bool can_combine_jobs(struct pvr_job *a, struct pvr_job *b)
eaf01ee5ba28b9 Sarah Walker 2023-11-22 598 {
eaf01ee5ba28b9 Sarah Walker 2023-11-22 599 struct pvr_job *geom_job = a, *frag_job = b;
eaf01ee5ba28b9 Sarah Walker 2023-11-22 600 struct dma_fence *fence;
eaf01ee5ba28b9 Sarah Walker 2023-11-22 601 unsigned long index;
eaf01ee5ba28b9 Sarah Walker 2023-11-22 602
eaf01ee5ba28b9 Sarah Walker 2023-11-22 603 /* Geometry and fragment jobs can be combined if they are queued to the
eaf01ee5ba28b9 Sarah Walker 2023-11-22 604 * same context and targeting the same HWRT.
eaf01ee5ba28b9 Sarah Walker 2023-11-22 605 */
eaf01ee5ba28b9 Sarah Walker 2023-11-22 606 if (a->type != DRM_PVR_JOB_TYPE_GEOMETRY ||
eaf01ee5ba28b9 Sarah Walker 2023-11-22 607 b->type != DRM_PVR_JOB_TYPE_FRAGMENT ||
eaf01ee5ba28b9 Sarah Walker 2023-11-22 608 a->ctx != b->ctx ||
eaf01ee5ba28b9 Sarah Walker 2023-11-22 609 a->hwrt != b->hwrt)
eaf01ee5ba28b9 Sarah Walker 2023-11-22 610 return false;
eaf01ee5ba28b9 Sarah Walker 2023-11-22 611
eaf01ee5ba28b9 Sarah Walker 2023-11-22 @612 xa_for_each(&frag_job->base.dependencies, index, fence) {
eaf01ee5ba28b9 Sarah Walker 2023-11-22 613 /* We combine when we see an explicit geom -> frag dep. */
eaf01ee5ba28b9 Sarah Walker 2023-11-22 614 if (&geom_job->base.s_fence->scheduled == fence)
eaf01ee5ba28b9 Sarah Walker 2023-11-22 615 return true;
eaf01ee5ba28b9 Sarah Walker 2023-11-22 616 }
eaf01ee5ba28b9 Sarah Walker 2023-11-22 617
eaf01ee5ba28b9 Sarah Walker 2023-11-22 618 return false;
eaf01ee5ba28b9 Sarah Walker 2023-11-22 619 }
eaf01ee5ba28b9 Sarah Walker 2023-11-22 620
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [RFC 00/14] Deadline scheduler and other ideas
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
` (13 preceding siblings ...)
2024-12-30 16:52 ` [RFC 14/14] drm/sched: Resolve all job dependencies in one go Tvrtko Ursulin
@ 2025-01-02 13:09 ` Philipp Stanner
2025-01-03 12:02 ` Tvrtko Ursulin
2025-01-03 15:16 ` AW: " Koenig, Christian
` (2 subsequent siblings)
17 siblings, 1 reply; 61+ messages in thread
From: Philipp Stanner @ 2025-01-02 13:09 UTC (permalink / raw)
To: Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost
On Mon, 2024-12-30 at 16:52 +0000, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>
> <tldr>
> Replacing FIFO with a flavour of deadline driven scheduling and
> removing round-
> robin. Connecting the scheduler with dma-fence deadlines. First draft
> and
> testing by different drivers and feedback would be nice. I was only
> able to test
> it with amdgpu. Other drivers may not even compile.
(on my machine I could build them all)
> </tldr>
>
> If I remember correctly Christian mentioned recently (give or take)
> that maybe
> round-robin could be removed. That got me thinking how and what could
> be
> improved and simplified. So I played a bit in the scheduler code and
> came up
> with something which appears to not crash at least. Whether or not
> there are
> significant advantages apart from maybe code consolidation and
> reduction is the
> main thing to be determined.
Hi,
so first of all: Happy new year and thx for putting in all that effort
:)
I gave the series a first look; Since this is an RFC, let's abstain
from doing deeper reviews of the exact code for now.
>
> One big question is whether round-robin can really be removed. Does
> anyone use
> it, rely on it, or what are even use cases where it is much better
> than FIFO.
So AFAICS Round Robin is not used anymore by anyone. And my
understanding indeed is, too, that there is not really any use-case
where one would like anything except for FIFO.
Looking at 977d97f18b5b ("drm/scheduler: Set the FIFO scheduling policy
as the default"), it seems to me that RR just was easy to implement and
it had the disadvantage of systems under high load cause the oldest job
to be starved to death, which is why FIFO was introduced.
So my guess would be that RR just is a relict.
If we agree on that, then we could remove RR in any case, and the
subsequent question would be whether FIFO should be replaced with
deadline (or: if there should be FIFO *and* deadline?), wouldn't it?
>
> See "drm/sched: Add deadline policy" commit message for a short
> description on
> what flavour of deadline scheduling it is. But in essence it should a
> more fair
> FIFO where higher priority can not forever starve lower priorities.
See my answer on that patch.
As you can imagine I'm wondering if that "better FIFO" would be worth
it considering that we are running into a certain risk of regressing
stuff through this rework.
>
> "drm/sched: Connect with dma-fence deadlines" wires up dma-fence
> deadlines to
> the scheduler because it is easy and makes logical sense with this.
> And I
> noticed userspace already uses it so why not wire it up fully.
Userspace uses the dma-fence deadlines you mean? Do you have a pointer
for us?
>
> Otherwise the series is a bit of progression from consolidating RR
> into FIFO
> code paths and going from there to deadline and then to a change in
> how
> dependencies are handled. And code simplification to 1:1 run queue to
> scheduler
> relationship, because deadline does not need per priority run queues.
>
> There is quite a bit of code to go throught here so I think it could
> be even
> better if other drivers could give it a spin as is and see if some
> improvements
> can be detected. Or at least no regressions.
I hope I can dive deeper into the Nouveau side soon.
>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: Danilo Krummrich <dakr@redhat.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Philipp Stanner <pstanner@redhat.com>
>
> Tvrtko Ursulin (14):
> drm/sched: Delete unused update_job_credits
> drm/sched: Remove idle entity from tree
> drm/sched: Implement RR via FIFO
> drm/sched: Consolidate entity run queue management
> drm/sched: Move run queue related code into a separate file
> drm/sched: Ignore own fence earlier
> drm/sched: Resolve same scheduler dependencies earlier
> drm/sched: Add deadline policy
> drm/sched: Remove FIFO and RR and simplify to a single run queue
> drm/sched: Queue all free credits in one worker invocation
> drm/sched: Connect with dma-fence deadlines
> drm/sched: Embed run queue singleton into the scheduler
> dma-fence: Add helper for custom fence context when merging fences
> drm/sched: Resolve all job dependencies in one go
It seems to me that this series is a "port RR and FIFO to deadline"-
series with some additional patches that could be branched out and be
reviewed through a separate series?
Patch 1 ("Delete unused...") for example. Other candidates are Patch 5
("Move run queue related..."), 13 ("Add helper for...").
A few patches might be mergeable even if the main idea with deadline
doesn't get approved, that's why I'm suggesting that.
Philipp
>
> drivers/dma-buf/dma-fence-unwrap.c | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 27 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 5 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 8 +-
> drivers/gpu/drm/scheduler/Makefile | 2 +-
> drivers/gpu/drm/scheduler/sched_entity.c | 316 ++++++-----
> drivers/gpu/drm/scheduler/sched_fence.c | 5 +-
> drivers/gpu/drm/scheduler/sched_main.c | 587 +++++-------------
> --
> drivers/gpu/drm/scheduler/sched_rq.c | 199 +++++++
> include/drm/gpu_scheduler.h | 74 ++-
> include/linux/dma-fence-unwrap.h | 31 +-
> 14 files changed, 606 insertions(+), 678 deletions(-)
> create mode 100644 drivers/gpu/drm/scheduler/sched_rq.c
>
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-02 13:09 ` [RFC 00/14] Deadline scheduler and other ideas Philipp Stanner
@ 2025-01-03 12:02 ` Tvrtko Ursulin
2025-01-03 12:31 ` Christian König
0 siblings, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-03 12:02 UTC (permalink / raw)
To: Philipp Stanner, Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Christian König, Danilo Krummrich, Matthew Brost
On 02/01/2025 13:09, Philipp Stanner wrote:
> On Mon, 2024-12-30 at 16:52 +0000, Tvrtko Ursulin wrote:
>> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>>
>> <tldr>
>> Replacing FIFO with a flavour of deadline driven scheduling and
>> removing round-
>> robin. Connecting the scheduler with dma-fence deadlines. First draft
>> and
>> testing by different drivers and feedback would be nice. I was only
>> able to test
>> it with amdgpu. Other drivers may not even compile.
>
> (on my machine I could build them all)
Kernel test robot reported that pvr does not build. I have fixed that
locally. (Matter of adding a proper interface for peeking into
job->dependencies.)
>
>> </tldr>
>>
>> If I remember correctly Christian mentioned recently (give or take)
>> that maybe
>> round-robin could be removed. That got me thinking how and what could
>> be
>> improved and simplified. So I played a bit in the scheduler code and
>> came up
>> with something which appears to not crash at least. Whether or not
>> there are
>> significant advantages apart from maybe code consolidation and
>> reduction is the
>> main thing to be determined.
>
> Hi,
>
> so first of all: Happy new year and thx for putting in all that effort
> :)
>
> I gave the series a first look; Since this is an RFC, let's abstain
> from doing deeper reviews of the exact code for now.
Ditto and thank you for taking a look!
>> One big question is whether round-robin can really be removed. Does
>> anyone use
>> it, rely on it, or what are even use cases where it is much better
>> than FIFO.
>
> So AFAICS Round Robin is not used anymore by anyone. And my
> understanding indeed is, too, that there is not really any use-case
> where one would like anything except for FIFO.
>
> Looking at 977d97f18b5b ("drm/scheduler: Set the FIFO scheduling policy
> as the default"), it seems to me that RR just was easy to implement and
> it had the disadvantage of systems under high load cause the oldest job
> to be starved to death, which is why FIFO was introduced.
>
> So my guess would be that RR just is a relict.
>
> If we agree on that, then we could remove RR in any case, and the
> subsequent question would be whether FIFO should be replaced with
> deadline (or: if there should be FIFO *and* deadline?), wouldn't it?
I am unsure about RR but I agree what is the second part of the question.
There may be nuances with different drivers depending on how much they
can queue to the hardware/firmware at once. Modern drivers which use 1:1
sched:entity I don't expect care about DRM scheduler scheduling mode.
The fewer jobs driver can queue to the backend the more it cares.
Question is FIFO ever better. Keeping in mind that for same priority
this deadline and FIFO are actually identical.
>> See "drm/sched: Add deadline policy" commit message for a short
>> description on
>> what flavour of deadline scheduling it is. But in essence it should a
>> more fair
>> FIFO where higher priority can not forever starve lower priorities.
>
> See my answer on that patch.
>
> As you can imagine I'm wondering if that "better FIFO" would be worth
> it considering that we are running into a certain risk of regressing
> stuff through this rework.
I will reply to that part there then.
>> "drm/sched: Connect with dma-fence deadlines" wires up dma-fence
>> deadlines to
>> the scheduler because it is easy and makes logical sense with this.
>> And I
>> noticed userspace already uses it so why not wire it up fully.
>
> Userspace uses the dma-fence deadlines you mean? Do you have a pointer
> for us?
I've noticed it empirically and the one I could fine is this:
https://invent.kde.org/plasma/kwin/-/commit/4ad5670ddfcd7400c8b84c12cbf8bd97a0590f43
>> Otherwise the series is a bit of progression from consolidating RR
>> into FIFO
>> code paths and going from there to deadline and then to a change in
>> how
>> dependencies are handled. And code simplification to 1:1 run queue to
>> scheduler
>> relationship, because deadline does not need per priority run queues.
>>
>> There is quite a bit of code to go throught here so I think it could
>> be even
>> better if other drivers could give it a spin as is and see if some
>> improvements
>> can be detected. Or at least no regressions.
>
> I hope I can dive deeper into the Nouveau side soon.
Fantastic!
>>
>> Cc: Christian König <christian.koenig@amd.com>
>> Cc: Danilo Krummrich <dakr@redhat.com>
>> Cc: Matthew Brost <matthew.brost@intel.com>
>> Cc: Philipp Stanner <pstanner@redhat.com>
>>
>> Tvrtko Ursulin (14):
>> drm/sched: Delete unused update_job_credits
>> drm/sched: Remove idle entity from tree
>> drm/sched: Implement RR via FIFO
>> drm/sched: Consolidate entity run queue management
>> drm/sched: Move run queue related code into a separate file
>> drm/sched: Ignore own fence earlier
>> drm/sched: Resolve same scheduler dependencies earlier
>> drm/sched: Add deadline policy
>> drm/sched: Remove FIFO and RR and simplify to a single run queue
>> drm/sched: Queue all free credits in one worker invocation
>> drm/sched: Connect with dma-fence deadlines
>> drm/sched: Embed run queue singleton into the scheduler
>> dma-fence: Add helper for custom fence context when merging fences
>> drm/sched: Resolve all job dependencies in one go
>
> It seems to me that this series is a "port RR and FIFO to deadline"-
> series with some additional patches that could be branched out and be
> reviewed through a separate series?
>
> Patch 1 ("Delete unused...") for example. Other candidates are Patch 5
> ("Move run queue related..."), 13 ("Add helper for...").
>
> A few patches might be mergeable even if the main idea with deadline
> doesn't get approved, that's why I'm suggesting that.
Yes some of those could be possible and I am happy to extract and rebase
in principle. But not yet I think. If and when something gets a positive
nod.
Regards,
Tvrtko
>>
>> drivers/dma-buf/dma-fence-unwrap.c | 8 +-
>> drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +-
>> drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 27 +-
>> drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 5 +-
>> drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 8 +-
>> drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 8 +-
>> drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 8 +-
>> drivers/gpu/drm/scheduler/Makefile | 2 +-
>> drivers/gpu/drm/scheduler/sched_entity.c | 316 ++++++-----
>> drivers/gpu/drm/scheduler/sched_fence.c | 5 +-
>> drivers/gpu/drm/scheduler/sched_main.c | 587 +++++-------------
>> --
>> drivers/gpu/drm/scheduler/sched_rq.c | 199 +++++++
>> include/drm/gpu_scheduler.h | 74 ++-
>> include/linux/dma-fence-unwrap.h | 31 +-
>> 14 files changed, 606 insertions(+), 678 deletions(-)
>> create mode 100644 drivers/gpu/drm/scheduler/sched_rq.c
>>
>
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-03 12:02 ` Tvrtko Ursulin
@ 2025-01-03 12:31 ` Christian König
2025-01-03 13:45 ` Philipp Stanner
` (2 more replies)
0 siblings, 3 replies; 61+ messages in thread
From: Christian König @ 2025-01-03 12:31 UTC (permalink / raw)
To: Tvrtko Ursulin, Philipp Stanner, Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Danilo Krummrich, Matthew Brost
Am 03.01.25 um 13:02 schrieb Tvrtko Ursulin:
>>> </tldr>
>>>
>>> If I remember correctly Christian mentioned recently (give or take)
>>> that maybe
>>> round-robin could be removed. That got me thinking how and what could
>>> be
>>> improved and simplified. So I played a bit in the scheduler code and
>>> came up
>>> with something which appears to not crash at least. Whether or not
>>> there are
>>> significant advantages apart from maybe code consolidation and
>>> reduction is the
>>> main thing to be determined.
>>
>> Hi,
>>
>> so first of all: Happy new year and thx for putting in all that effort
>> :)
>>
>> I gave the series a first look; Since this is an RFC, let's abstain
>> from doing deeper reviews of the exact code for now.
>
> Ditto and thank you for taking a look!
Ah, yes. Happy new year guys :)
>
>>> One big question is whether round-robin can really be removed. Does
>>> anyone use
>>> it, rely on it, or what are even use cases where it is much better
>>> than FIFO.
>>
>> So AFAICS Round Robin is not used anymore by anyone. And my
>> understanding indeed is, too, that there is not really any use-case
>> where one would like anything except for FIFO.
>>
>> Looking at 977d97f18b5b ("drm/scheduler: Set the FIFO scheduling policy
>> as the default"), it seems to me that RR just was easy to implement and
>> it had the disadvantage of systems under high load cause the oldest job
>> to be starved to death, which is why FIFO was introduced.
>>
>> So my guess would be that RR just is a relict.
>>
>> If we agree on that, then we could remove RR in any case, and the
>> subsequent question would be whether FIFO should be replaced with
>> deadline (or: if there should be FIFO *and* deadline?), wouldn't it?
>
> I am unsure about RR but I agree what is the second part of the question.
Well we came up with FIFO because we found that RR performed quite badly
when you have a huge number of submitting applications.
E.g. one of our cloud test cases ran 100 instances of a single game and
the worst response time improved massively by switching from RR to FIFO.
Different priorities on the other hand were originally invented to make
sure the kernel has precedence over userspace. But later we also exposed
the priorities to userspace which results in the problem that higher
priority queues can starve low priority ones.
That's the other reason why I said that RR should probably be removed
and FIFO changed in a way that the priority is basically just a bonus to
the score used for sorting the FIFO. I haven't taken a deeper look yet,
but I think that this is more or less what this patch set here does.
What FIFO is still missing compared to RR is some sort of fairness
between queues. E.g. a queues which hasn't submitted something in a
while might get a bonus for their submissions compared to a queue which
submits stuff all the time (or something like that).
Regards,
Christian.
> There may be nuances with different drivers depending on how much they
> can queue to the hardware/firmware at once. Modern drivers which use
> 1:1 sched:entity I don't expect care about DRM scheduler scheduling
> mode. The fewer jobs driver can queue to the backend the more it
> cares. Question is FIFO ever better. Keeping in mind that for same
> priority this deadline and FIFO are actually identical.
>
>>> See "drm/sched: Add deadline policy" commit message for a short
>>> description on
>>> what flavour of deadline scheduling it is. But in essence it should a
>>> more fair
>>> FIFO where higher priority can not forever starve lower priorities.
>>
>> See my answer on that patch.
>>
>> As you can imagine I'm wondering if that "better FIFO" would be worth
>> it considering that we are running into a certain risk of regressing
>> stuff through this rework.
>
> I will reply to that part there then.
>>> "drm/sched: Connect with dma-fence deadlines" wires up dma-fence
>>> deadlines to
>>> the scheduler because it is easy and makes logical sense with this.
>>> And I
>>> noticed userspace already uses it so why not wire it up fully.
>>
>> Userspace uses the dma-fence deadlines you mean? Do you have a pointer
>> for us?
>
> I've noticed it empirically and the one I could fine is this:
>
> https://invent.kde.org/plasma/kwin/-/commit/4ad5670ddfcd7400c8b84c12cbf8bd97a0590f43
>
>
>>> Otherwise the series is a bit of progression from consolidating RR
>>> into FIFO
>>> code paths and going from there to deadline and then to a change in
>>> how
>>> dependencies are handled. And code simplification to 1:1 run queue to
>>> scheduler
>>> relationship, because deadline does not need per priority run queues.
>>>
>>> There is quite a bit of code to go throught here so I think it could
>>> be even
>>> better if other drivers could give it a spin as is and see if some
>>> improvements
>>> can be detected. Or at least no regressions.
>>
>> I hope I can dive deeper into the Nouveau side soon.
>
> Fantastic!
>>>
>>> Cc: Christian König <christian.koenig@amd.com>
>>> Cc: Danilo Krummrich <dakr@redhat.com>
>>> Cc: Matthew Brost <matthew.brost@intel.com>
>>> Cc: Philipp Stanner <pstanner@redhat.com>
>>>
>>> Tvrtko Ursulin (14):
>>> drm/sched: Delete unused update_job_credits
>>> drm/sched: Remove idle entity from tree
>>> drm/sched: Implement RR via FIFO
>>> drm/sched: Consolidate entity run queue management
>>> drm/sched: Move run queue related code into a separate file
>>> drm/sched: Ignore own fence earlier
>>> drm/sched: Resolve same scheduler dependencies earlier
>>> drm/sched: Add deadline policy
>>> drm/sched: Remove FIFO and RR and simplify to a single run queue
>>> drm/sched: Queue all free credits in one worker invocation
>>> drm/sched: Connect with dma-fence deadlines
>>> drm/sched: Embed run queue singleton into the scheduler
>>> dma-fence: Add helper for custom fence context when merging fences
>>> drm/sched: Resolve all job dependencies in one go
>>
>> It seems to me that this series is a "port RR and FIFO to deadline"-
>> series with some additional patches that could be branched out and be
>> reviewed through a separate series?
>>
>> Patch 1 ("Delete unused...") for example. Other candidates are Patch 5
>> ("Move run queue related..."), 13 ("Add helper for...").
>>
>> A few patches might be mergeable even if the main idea with deadline
>> doesn't get approved, that's why I'm suggesting that.
>
> Yes some of those could be possible and I am happy to extract and
> rebase in principle. But not yet I think. If and when something gets a
> positive nod.
>
> Regards,
>
> Tvrtko
>
>>>
>>> drivers/dma-buf/dma-fence-unwrap.c | 8 +-
>>> drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +-
>>> drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 27 +-
>>> drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 5 +-
>>> drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 8 +-
>>> drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 8 +-
>>> drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 8 +-
>>> drivers/gpu/drm/scheduler/Makefile | 2 +-
>>> drivers/gpu/drm/scheduler/sched_entity.c | 316 ++++++-----
>>> drivers/gpu/drm/scheduler/sched_fence.c | 5 +-
>>> drivers/gpu/drm/scheduler/sched_main.c | 587 +++++-------------
>>> --
>>> drivers/gpu/drm/scheduler/sched_rq.c | 199 +++++++
>>> include/drm/gpu_scheduler.h | 74 ++-
>>> include/linux/dma-fence-unwrap.h | 31 +-
>>> 14 files changed, 606 insertions(+), 678 deletions(-)
>>> create mode 100644 drivers/gpu/drm/scheduler/sched_rq.c
>>>
>>
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-03 12:31 ` Christian König
@ 2025-01-03 13:45 ` Philipp Stanner
2025-01-03 15:17 ` Tvrtko Ursulin
2025-01-09 15:08 ` Michel Dänzer
2 siblings, 0 replies; 61+ messages in thread
From: Philipp Stanner @ 2025-01-03 13:45 UTC (permalink / raw)
To: Christian König, Tvrtko Ursulin, Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Danilo Krummrich, Matthew Brost
On Fri, 2025-01-03 at 13:31 +0100, Christian König wrote:
> Am 03.01.25 um 13:02 schrieb Tvrtko Ursulin:
> > > > </tldr>
> > > >
> > > > If I remember correctly Christian mentioned recently (give or
> > > > take)
> > > > that maybe
> > > > round-robin could be removed. That got me thinking how and what
> > > > could
> > > > be
> > > > improved and simplified. So I played a bit in the scheduler
> > > > code and
> > > > came up
> > > > with something which appears to not crash at least. Whether or
> > > > not
> > > > there are
> > > > significant advantages apart from maybe code consolidation and
> > > > reduction is the
> > > > main thing to be determined.
> > >
> > > Hi,
> > >
> > > so first of all: Happy new year and thx for putting in all that
> > > effort
> > > :)
> > >
> > > I gave the series a first look; Since this is an RFC, let's
> > > abstain
> > > from doing deeper reviews of the exact code for now.
> >
> > Ditto and thank you for taking a look!
>
> Ah, yes. Happy new year guys :)
>
> >
> > > > One big question is whether round-robin can really be removed.
> > > > Does
> > > > anyone use
> > > > it, rely on it, or what are even use cases where it is much
> > > > better
> > > > than FIFO.
> > >
> > > So AFAICS Round Robin is not used anymore by anyone. And my
> > > understanding indeed is, too, that there is not really any use-
> > > case
> > > where one would like anything except for FIFO.
> > >
> > > Looking at 977d97f18b5b ("drm/scheduler: Set the FIFO scheduling
> > > policy
> > > as the default"), it seems to me that RR just was easy to
> > > implement and
> > > it had the disadvantage of systems under high load cause the
> > > oldest job
> > > to be starved to death, which is why FIFO was introduced.
> > >
> > > So my guess would be that RR just is a relict.
> > >
> > > If we agree on that, then we could remove RR in any case, and the
> > > subsequent question would be whether FIFO should be replaced with
> > > deadline (or: if there should be FIFO *and* deadline?), wouldn't
> > > it?
> >
> > I am unsure about RR but I agree what is the second part of the
> > question.
>
> Well we came up with FIFO because we found that RR performed quite
> badly
> when you have a huge number of submitting applications.
>
> E.g. one of our cloud test cases ran 100 instances of a single game
> and
> the worst response time improved massively by switching from RR to
> FIFO.
>
> Different priorities on the other hand were originally invented to
> make
> sure the kernel has precedence over userspace.
Should it, in your opinion, be *guaranteed* that the kernel always
takes precedence, or is a "kernel takes precedence almost always"
enough?
Because this patchset does seem to do the latter
> But later we also exposed
> the priorities to userspace which results in the problem that higher
> priority queues can starve low priority ones.
>
> That's the other reason why I said that RR should probably be removed
> and FIFO changed in a way that the priority is basically just a bonus
> to
> the score used for sorting the FIFO. I haven't taken a deeper look
> yet,
> but I think that this is more or less what this patch set here does.
>
> What FIFO is still missing compared to RR is some sort of fairness
> between queues.
Before I forget it I note it right away:
If we go for such a thing we should set our terminology straight. A
FIFO that suddenly takes deadlines into account is not a FIFO anymore.
So we shouldn't call it that.
However, a deadline scheduler with priority levels also doesn't seem to
be a deadline scheduler.
I think, no matter what we do, we should aim for strict congruency
between the GPU scheduler and the CPU scheduler in regards with terms
and naming. The CPU scheduler has SCHED_FIFO, which is pure FIFO with
priorities (behaving exactly like the GPU schedulers FIFO, currently)
and SCHED_DEADLINE, which is purely based on deadlines (not like in
this patch set).
So we should find a new suitable term if we go for that to avoid any
misunderstandings.
P.
> E.g. a queues which hasn't submitted something in a
> while might get a bonus for their submissions compared to a queue
> which
> submits stuff all the time (or something like that).
>
> Regards,
> Christian.
>
>
> > There may be nuances with different drivers depending on how much
> > they
> > can queue to the hardware/firmware at once. Modern drivers which
> > use
> > 1:1 sched:entity I don't expect care about DRM scheduler scheduling
> > mode. The fewer jobs driver can queue to the backend the more it
> > cares. Question is FIFO ever better. Keeping in mind that for same
> > priority this deadline and FIFO are actually identical.
> >
> > > > See "drm/sched: Add deadline policy" commit message for a short
> > > > description on
> > > > what flavour of deadline scheduling it is. But in essence it
> > > > should a
> > > > more fair
> > > > FIFO where higher priority can not forever starve lower
> > > > priorities.
> > >
> > > See my answer on that patch.
> > >
> > > As you can imagine I'm wondering if that "better FIFO" would be
> > > worth
> > > it considering that we are running into a certain risk of
> > > regressing
> > > stuff through this rework.
> >
> > I will reply to that part there then.
> > > > "drm/sched: Connect with dma-fence deadlines" wires up dma-
> > > > fence
> > > > deadlines to
> > > > the scheduler because it is easy and makes logical sense with
> > > > this.
> > > > And I
> > > > noticed userspace already uses it so why not wire it up fully.
> > >
> > > Userspace uses the dma-fence deadlines you mean? Do you have a
> > > pointer
> > > for us?
> >
> > I've noticed it empirically and the one I could fine is this:
> >
> > https://invent.kde.org/plasma/kwin/-/commit/4ad5670ddfcd7400c8b84c12cbf8bd97a0590f43
> >
> >
> >
> > > > Otherwise the series is a bit of progression from consolidating
> > > > RR
> > > > into FIFO
> > > > code paths and going from there to deadline and then to a
> > > > change in
> > > > how
> > > > dependencies are handled. And code simplification to 1:1 run
> > > > queue to
> > > > scheduler
> > > > relationship, because deadline does not need per priority run
> > > > queues.
> > > >
> > > > There is quite a bit of code to go throught here so I think it
> > > > could
> > > > be even
> > > > better if other drivers could give it a spin as is and see if
> > > > some
> > > > improvements
> > > > can be detected. Or at least no regressions.
> > >
> > > I hope I can dive deeper into the Nouveau side soon.
> >
> > Fantastic!
> > > >
> > > > Cc: Christian König <christian.koenig@amd.com>
> > > > Cc: Danilo Krummrich <dakr@redhat.com>
> > > > Cc: Matthew Brost <matthew.brost@intel.com>
> > > > Cc: Philipp Stanner <pstanner@redhat.com>
> > > >
> > > > Tvrtko Ursulin (14):
> > > > drm/sched: Delete unused update_job_credits
> > > > drm/sched: Remove idle entity from tree
> > > > drm/sched: Implement RR via FIFO
> > > > drm/sched: Consolidate entity run queue management
> > > > drm/sched: Move run queue related code into a separate file
> > > > drm/sched: Ignore own fence earlier
> > > > drm/sched: Resolve same scheduler dependencies earlier
> > > > drm/sched: Add deadline policy
> > > > drm/sched: Remove FIFO and RR and simplify to a single run
> > > > queue
> > > > drm/sched: Queue all free credits in one worker invocation
> > > > drm/sched: Connect with dma-fence deadlines
> > > > drm/sched: Embed run queue singleton into the scheduler
> > > > dma-fence: Add helper for custom fence context when merging
> > > > fences
> > > > drm/sched: Resolve all job dependencies in one go
> > >
> > > It seems to me that this series is a "port RR and FIFO to
> > > deadline"-
> > > series with some additional patches that could be branched out
> > > and be
> > > reviewed through a separate series?
> > >
> > > Patch 1 ("Delete unused...") for example. Other candidates are
> > > Patch 5
> > > ("Move run queue related..."), 13 ("Add helper for...").
> > >
> > > A few patches might be mergeable even if the main idea with
> > > deadline
> > > doesn't get approved, that's why I'm suggesting that.
> >
> > Yes some of those could be possible and I am happy to extract and
> > rebase in principle. But not yet I think. If and when something
> > gets a
> > positive nod.
> >
> > Regards,
> >
> > Tvrtko
> >
> > > >
> > > > drivers/dma-buf/dma-fence-unwrap.c | 8 +-
> > > > drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +-
> > > > drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 27 +-
> > > > drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 5 +-
> > > > drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 8 +-
> > > > drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 8 +-
> > > > drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 8 +-
> > > > drivers/gpu/drm/scheduler/Makefile | 2 +-
> > > > drivers/gpu/drm/scheduler/sched_entity.c | 316 ++++++-----
> > > > drivers/gpu/drm/scheduler/sched_fence.c | 5 +-
> > > > drivers/gpu/drm/scheduler/sched_main.c | 587 +++++------
> > > > -------
> > > > --
> > > > drivers/gpu/drm/scheduler/sched_rq.c | 199 +++++++
> > > > include/drm/gpu_scheduler.h | 74 ++-
> > > > include/linux/dma-fence-unwrap.h | 31 +-
> > > > 14 files changed, 606 insertions(+), 678 deletions(-)
> > > > create mode 100644 drivers/gpu/drm/scheduler/sched_rq.c
> > > >
> > >
>
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-03 12:31 ` Christian König
2025-01-03 13:45 ` Philipp Stanner
@ 2025-01-03 15:17 ` Tvrtko Ursulin
2025-01-09 15:08 ` Michel Dänzer
2 siblings, 0 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-03 15:17 UTC (permalink / raw)
To: Christian König, Philipp Stanner, Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Danilo Krummrich, Matthew Brost
On 03/01/2025 12:31, Christian König wrote:
> Am 03.01.25 um 13:02 schrieb Tvrtko Ursulin:
>>>> </tldr>
>>>>
>>>> If I remember correctly Christian mentioned recently (give or take)
>>>> that maybe
>>>> round-robin could be removed. That got me thinking how and what could
>>>> be
>>>> improved and simplified. So I played a bit in the scheduler code and
>>>> came up
>>>> with something which appears to not crash at least. Whether or not
>>>> there are
>>>> significant advantages apart from maybe code consolidation and
>>>> reduction is the
>>>> main thing to be determined.
>>>
>>> Hi,
>>>
>>> so first of all: Happy new year and thx for putting in all that effort
>>> :)
>>>
>>> I gave the series a first look; Since this is an RFC, let's abstain
>>> from doing deeper reviews of the exact code for now.
>>
>> Ditto and thank you for taking a look!
>
> Ah, yes. Happy new year guys :)
>
>>
>>>> One big question is whether round-robin can really be removed. Does
>>>> anyone use
>>>> it, rely on it, or what are even use cases where it is much better
>>>> than FIFO.
>>>
>>> So AFAICS Round Robin is not used anymore by anyone. And my
>>> understanding indeed is, too, that there is not really any use-case
>>> where one would like anything except for FIFO.
>>>
>>> Looking at 977d97f18b5b ("drm/scheduler: Set the FIFO scheduling policy
>>> as the default"), it seems to me that RR just was easy to implement and
>>> it had the disadvantage of systems under high load cause the oldest job
>>> to be starved to death, which is why FIFO was introduced.
>>>
>>> So my guess would be that RR just is a relict.
>>>
>>> If we agree on that, then we could remove RR in any case, and the
>>> subsequent question would be whether FIFO should be replaced with
>>> deadline (or: if there should be FIFO *and* deadline?), wouldn't it?
>>
>> I am unsure about RR but I agree what is the second part of the question.
>
> Well we came up with FIFO because we found that RR performed quite badly
> when you have a huge number of submitting applications.
>
> E.g. one of our cloud test cases ran 100 instances of a single game and
> the worst response time improved massively by switching from RR to FIFO.
>
> Different priorities on the other hand were originally invented to make
> sure the kernel has precedence over userspace. But later we also exposed
> the priorities to userspace which results in the problem that higher
> priority queues can starve low priority ones.
>
> That's the other reason why I said that RR should probably be removed
> and FIFO changed in a way that the priority is basically just a bonus to
> the score used for sorting the FIFO. I haven't taken a deeper look yet,
> but I think that this is more or less what this patch set here does.
>
> What FIFO is still missing compared to RR is some sort of fairness
> between queues. E.g. a queues which hasn't submitted something in a
> while might get a bonus for their submissions compared to a queue which
> submits stuff all the time (or something like that).
I can try to add something along these lines. Like dynamically scale the
relative deadlines based on entity queue depth so infrequent short
bursts compete better with persistent hogs. I'll wait for some more
feedback and then see where to go.
Regards,
Tvrtko
>> There may be nuances with different drivers depending on how much they
>> can queue to the hardware/firmware at once. Modern drivers which use
>> 1:1 sched:entity I don't expect care about DRM scheduler scheduling
>> mode. The fewer jobs driver can queue to the backend the more it
>> cares. Question is FIFO ever better. Keeping in mind that for same
>> priority this deadline and FIFO are actually identical.
>>
>>>> See "drm/sched: Add deadline policy" commit message for a short
>>>> description on
>>>> what flavour of deadline scheduling it is. But in essence it should a
>>>> more fair
>>>> FIFO where higher priority can not forever starve lower priorities.
>>>
>>> See my answer on that patch.
>>>
>>> As you can imagine I'm wondering if that "better FIFO" would be worth
>>> it considering that we are running into a certain risk of regressing
>>> stuff through this rework.
>>
>> I will reply to that part there then.
>>>> "drm/sched: Connect with dma-fence deadlines" wires up dma-fence
>>>> deadlines to
>>>> the scheduler because it is easy and makes logical sense with this.
>>>> And I
>>>> noticed userspace already uses it so why not wire it up fully.
>>>
>>> Userspace uses the dma-fence deadlines you mean? Do you have a pointer
>>> for us?
>>
>> I've noticed it empirically and the one I could fine is this:
>>
>> https://invent.kde.org/plasma/kwin/-/commit/4ad5670ddfcd7400c8b84c12cbf8bd97a0590f43
>>
>>>> Otherwise the series is a bit of progression from consolidating RR
>>>> into FIFO
>>>> code paths and going from there to deadline and then to a change in
>>>> how
>>>> dependencies are handled. And code simplification to 1:1 run queue to
>>>> scheduler
>>>> relationship, because deadline does not need per priority run queues.
>>>>
>>>> There is quite a bit of code to go throught here so I think it could
>>>> be even
>>>> better if other drivers could give it a spin as is and see if some
>>>> improvements
>>>> can be detected. Or at least no regressions.
>>>
>>> I hope I can dive deeper into the Nouveau side soon.
>>
>> Fantastic!
>>>>
>>>> Cc: Christian König <christian.koenig@amd.com>
>>>> Cc: Danilo Krummrich <dakr@redhat.com>
>>>> Cc: Matthew Brost <matthew.brost@intel.com>
>>>> Cc: Philipp Stanner <pstanner@redhat.com>
>>>>
>>>> Tvrtko Ursulin (14):
>>>> drm/sched: Delete unused update_job_credits
>>>> drm/sched: Remove idle entity from tree
>>>> drm/sched: Implement RR via FIFO
>>>> drm/sched: Consolidate entity run queue management
>>>> drm/sched: Move run queue related code into a separate file
>>>> drm/sched: Ignore own fence earlier
>>>> drm/sched: Resolve same scheduler dependencies earlier
>>>> drm/sched: Add deadline policy
>>>> drm/sched: Remove FIFO and RR and simplify to a single run queue
>>>> drm/sched: Queue all free credits in one worker invocation
>>>> drm/sched: Connect with dma-fence deadlines
>>>> drm/sched: Embed run queue singleton into the scheduler
>>>> dma-fence: Add helper for custom fence context when merging fences
>>>> drm/sched: Resolve all job dependencies in one go
>>>
>>> It seems to me that this series is a "port RR and FIFO to deadline"-
>>> series with some additional patches that could be branched out and be
>>> reviewed through a separate series?
>>>
>>> Patch 1 ("Delete unused...") for example. Other candidates are Patch 5
>>> ("Move run queue related..."), 13 ("Add helper for...").
>>>
>>> A few patches might be mergeable even if the main idea with deadline
>>> doesn't get approved, that's why I'm suggesting that.
>>
>> Yes some of those could be possible and I am happy to extract and
>> rebase in principle. But not yet I think. If and when something gets a
>> positive nod.
>>
>> Regards,
>>
>> Tvrtko
>>
>>>>
>>>> drivers/dma-buf/dma-fence-unwrap.c | 8 +-
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +-
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 27 +-
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 5 +-
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 8 +-
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 8 +-
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 8 +-
>>>> drivers/gpu/drm/scheduler/Makefile | 2 +-
>>>> drivers/gpu/drm/scheduler/sched_entity.c | 316 ++++++-----
>>>> drivers/gpu/drm/scheduler/sched_fence.c | 5 +-
>>>> drivers/gpu/drm/scheduler/sched_main.c | 587 +++++-------------
>>>> --
>>>> drivers/gpu/drm/scheduler/sched_rq.c | 199 +++++++
>>>> include/drm/gpu_scheduler.h | 74 ++-
>>>> include/linux/dma-fence-unwrap.h | 31 +-
>>>> 14 files changed, 606 insertions(+), 678 deletions(-)
>>>> create mode 100644 drivers/gpu/drm/scheduler/sched_rq.c
>>>>
>>>
>
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-03 12:31 ` Christian König
2025-01-03 13:45 ` Philipp Stanner
2025-01-03 15:17 ` Tvrtko Ursulin
@ 2025-01-09 15:08 ` Michel Dänzer
2025-01-09 16:55 ` Tvrtko Ursulin
2 siblings, 1 reply; 61+ messages in thread
From: Michel Dänzer @ 2025-01-09 15:08 UTC (permalink / raw)
To: Christian König, Tvrtko Ursulin, Philipp Stanner,
Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Danilo Krummrich, Matthew Brost
On 2025-01-03 13:31, Christian König wrote:
> Am 03.01.25 um 13:02 schrieb Tvrtko Ursulin:
>>>>
>>>> One big question is whether round-robin can really be removed. Does
>>>> anyone use
>>>> it, rely on it, or what are even use cases where it is much better
>>>> than FIFO.
>>>
>>> So AFAICS Round Robin is not used anymore by anyone. And my
>>> understanding indeed is, too, that there is not really any use-case
>>> where one would like anything except for FIFO.
>>>
>>> Looking at 977d97f18b5b ("drm/scheduler: Set the FIFO scheduling policy
>>> as the default"), it seems to me that RR just was easy to implement and
>>> it had the disadvantage of systems under high load cause the oldest job
>>> to be starved to death, which is why FIFO was introduced.
>>>
>>> So my guess would be that RR just is a relict.
>>>
>>> If we agree on that, then we could remove RR in any case, and the
>>> subsequent question would be whether FIFO should be replaced with
>>> deadline (or: if there should be FIFO *and* deadline?), wouldn't it?
>>
>> I am unsure about RR but I agree what is the second part of the question.
>
> Well we came up with FIFO because we found that RR performed quite badly when you have a huge number of submitting applications.
>
> E.g. one of our cloud test cases ran 100 instances of a single game and the worst response time improved massively by switching from RR to FIFO.
>
> Different priorities on the other hand were originally invented to make sure the kernel has precedence over userspace. But later we also exposed the priorities to userspace which results in the problem that higher priority queues can starve low priority ones.
FWIW, that can't explain why RR worked better in the scenario I described in https://gitlab.freedesktop.org/drm/amd/-/issues/2516#note_2119750, Xwayland uses normal GPU scheduling priority, just like the game.
> That's the other reason why I said that RR should probably be removed and FIFO changed in a way that the priority is basically just a bonus to the score used for sorting the FIFO. I haven't taken a deeper look yet, but I think that this is more or less what this patch set here does.
FWIW, people are saying RR works better than FIFO for some gaming scenarios even with current Xwayland, which shouldn't do any GPU copies for presentation of fullscreen windows. There seem to be other interactions which work better with RR than FIFO from the user PoV. If RR is to be removed, I'd recommend making sure deadline works at least as well as RR for those.
> What FIFO is still missing compared to RR is some sort of fairness between queues. E.g. a queues which hasn't submitted something in a while might get a bonus for their submissions compared to a queue which submits stuff all the time (or something like that).
The lack of that could indeed explain the scenario above, if the game submits its GPU job for frame n+1 before Xwayland submits its GPU job for presenting frame n.
--
Earthling Michel Dänzer \ GNOME / Xwayland / Mesa developer
https://redhat.com \ Libre software enthusiast
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-09 15:08 ` Michel Dänzer
@ 2025-01-09 16:55 ` Tvrtko Ursulin
2025-01-10 9:14 ` Michel Dänzer
0 siblings, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-09 16:55 UTC (permalink / raw)
To: Michel Dänzer, Christian König, Philipp Stanner,
Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Danilo Krummrich, Matthew Brost
On 09/01/2025 15:08, Michel Dänzer wrote:
> On 2025-01-03 13:31, Christian König wrote:
>> Am 03.01.25 um 13:02 schrieb Tvrtko Ursulin:
>>>>>
>>>>> One big question is whether round-robin can really be removed. Does
>>>>> anyone use
>>>>> it, rely on it, or what are even use cases where it is much better
>>>>> than FIFO.
>>>>
>>>> So AFAICS Round Robin is not used anymore by anyone. And my
>>>> understanding indeed is, too, that there is not really any use-case
>>>> where one would like anything except for FIFO.
>>>>
>>>> Looking at 977d97f18b5b ("drm/scheduler: Set the FIFO scheduling policy
>>>> as the default"), it seems to me that RR just was easy to implement and
>>>> it had the disadvantage of systems under high load cause the oldest job
>>>> to be starved to death, which is why FIFO was introduced.
>>>>
>>>> So my guess would be that RR just is a relict.
>>>>
>>>> If we agree on that, then we could remove RR in any case, and the
>>>> subsequent question would be whether FIFO should be replaced with
>>>> deadline (or: if there should be FIFO *and* deadline?), wouldn't it?
>>>
>>> I am unsure about RR but I agree what is the second part of the question.
>>
>> Well we came up with FIFO because we found that RR performed quite badly when you have a huge number of submitting applications.
>>
>> E.g. one of our cloud test cases ran 100 instances of a single game and the worst response time improved massively by switching from RR to FIFO.
>>
>> Different priorities on the other hand were originally invented to make sure the kernel has precedence over userspace. But later we also exposed the priorities to userspace which results in the problem that higher priority queues can starve low priority ones.
>
> FWIW, that can't explain why RR worked better in the scenario I described in https://gitlab.freedesktop.org/drm/amd/-/issues/2516#note_2119750, Xwayland uses normal GPU scheduling priority, just like the game.
>
>
>> That's the other reason why I said that RR should probably be removed and FIFO changed in a way that the priority is basically just a bonus to the score used for sorting the FIFO. I haven't taken a deeper look yet, but I think that this is more or less what this patch set here does.
>
> FWIW, people are saying RR works better than FIFO for some gaming scenarios even with current Xwayland, which shouldn't do any GPU copies for presentation of fullscreen windows. There seem to be other interactions which work better with RR than FIFO from the user PoV. If RR is to be removed, I'd recommend making sure deadline works at least as well as RR for those.
>
>
>> What FIFO is still missing compared to RR is some sort of fairness between queues. E.g. a queues which hasn't submitted something in a while might get a bonus for their submissions compared to a queue which submits stuff all the time (or something like that).
>
> The lack of that could indeed explain the scenario above, if the game submits its GPU job for frame n+1 before Xwayland submits its GPU job for presenting frame n.
I would be keen to experiment with this. There is that last patch in v2
of my series which scales the deadlines based on queue depth. So for a
client which submits two frames it could be enough (in principle, not
the actually posted version) to push out the deadline at qd=2 so a
client which never breaks qd=1 can reliably overtake it.
What would really be great if you could suggest me as easy to set up as
possible test case with objective measuring criteria. And it would have
to run on AMD. Quake II RTX under XWayland as the GitLab issue suggest
or there is more to it? Does it has to be GNOME? Any way to run it
programmatically and get a performance number out?
Regards,
Tvrtko
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-09 16:55 ` Tvrtko Ursulin
@ 2025-01-10 9:14 ` Michel Dänzer
2025-01-13 11:40 ` Tvrtko Ursulin
0 siblings, 1 reply; 61+ messages in thread
From: Michel Dänzer @ 2025-01-10 9:14 UTC (permalink / raw)
To: Tvrtko Ursulin, Christian König, Philipp Stanner,
Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Danilo Krummrich, Matthew Brost
On 2025-01-09 17:55, Tvrtko Ursulin wrote:
> On 09/01/2025 15:08, Michel Dänzer wrote:
>> On 2025-01-03 13:31, Christian König wrote:
>>> Am 03.01.25 um 13:02 schrieb Tvrtko Ursulin:
>>>>>>
>>>>>> One big question is whether round-robin can really be removed. Does
>>>>>> anyone use
>>>>>> it, rely on it, or what are even use cases where it is much better
>>>>>> than FIFO.
>>>>>
>>>>> So AFAICS Round Robin is not used anymore by anyone. And my
>>>>> understanding indeed is, too, that there is not really any use-case
>>>>> where one would like anything except for FIFO.
>>>>>
>>>>> Looking at 977d97f18b5b ("drm/scheduler: Set the FIFO scheduling policy
>>>>> as the default"), it seems to me that RR just was easy to implement and
>>>>> it had the disadvantage of systems under high load cause the oldest job
>>>>> to be starved to death, which is why FIFO was introduced.
>>>>>
>>>>> So my guess would be that RR just is a relict.
>>>>>
>>>>> If we agree on that, then we could remove RR in any case, and the
>>>>> subsequent question would be whether FIFO should be replaced with
>>>>> deadline (or: if there should be FIFO *and* deadline?), wouldn't it?
>>>>
>>>> I am unsure about RR but I agree what is the second part of the question.
>>>
>>> Well we came up with FIFO because we found that RR performed quite badly when you have a huge number of submitting applications.
>>>
>>> E.g. one of our cloud test cases ran 100 instances of a single game and the worst response time improved massively by switching from RR to FIFO.
>>>
>>> Different priorities on the other hand were originally invented to make sure the kernel has precedence over userspace. But later we also exposed the priorities to userspace which results in the problem that higher priority queues can starve low priority ones.
>>
>> FWIW, that can't explain why RR worked better in the scenario I described in https://gitlab.freedesktop.org/drm/amd/-/issues/2516#note_2119750, Xwayland uses normal GPU scheduling priority, just like the game.
>>
>>
>>> That's the other reason why I said that RR should probably be removed and FIFO changed in a way that the priority is basically just a bonus to the score used for sorting the FIFO. I haven't taken a deeper look yet, but I think that this is more or less what this patch set here does.
>>
>> FWIW, people are saying RR works better than FIFO for some gaming scenarios even with current Xwayland, which shouldn't do any GPU copies for presentation of fullscreen windows. There seem to be other interactions which work better with RR than FIFO from the user PoV. If RR is to be removed, I'd recommend making sure deadline works at least as well as RR for those.
>>
>>
>>> What FIFO is still missing compared to RR is some sort of fairness between queues. E.g. a queues which hasn't submitted something in a while might get a bonus for their submissions compared to a queue which submits stuff all the time (or something like that).
>>
>> The lack of that could indeed explain the scenario above, if the game submits its GPU job for frame n+1 before Xwayland submits its GPU job for presenting frame n.
>
> I would be keen to experiment with this. There is that last patch in v2 of my series which scales the deadlines based on queue depth. So for a client which submits two frames it could be enough (in principle, not the actually posted version) to push out the deadline at qd=2 so a client which never breaks qd=1 can reliably overtake it.
>
> What would really be great if you could suggest me as easy to set up as possible test case with objective measuring criteria. And it would have to run on AMD. Quake II RTX under XWayland as the GitLab issue suggest or there is more to it? Does it has to be GNOME?
Don't think it has to be.
> Any way to run it programmatically and get a performance number out?
This could be tricky, since the game itself reports the same frame rate in both cases. You'd have to compare the frame times in the compositor instead.
Also, the issue might no longer be reproducible in this particular scenario with current Xwayland, because it should no longer do any GPU copies for presentation but just forward the client buffers to the compositor.
--
Earthling Michel Dänzer \ GNOME / Xwayland / Mesa developer
https://redhat.com \ Libre software enthusiast
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-10 9:14 ` Michel Dänzer
@ 2025-01-13 11:40 ` Tvrtko Ursulin
2025-01-13 15:29 ` Michel Dänzer
0 siblings, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-13 11:40 UTC (permalink / raw)
To: Michel Dänzer, Christian König, Philipp Stanner,
Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Danilo Krummrich, Matthew Brost
On 10/01/2025 09:14, Michel Dänzer wrote:
> On 2025-01-09 17:55, Tvrtko Ursulin wrote:
>> On 09/01/2025 15:08, Michel Dänzer wrote:
>>> On 2025-01-03 13:31, Christian König wrote:
>>>> Am 03.01.25 um 13:02 schrieb Tvrtko Ursulin:
>>>>>>>
>>>>>>> One big question is whether round-robin can really be removed. Does
>>>>>>> anyone use
>>>>>>> it, rely on it, or what are even use cases where it is much better
>>>>>>> than FIFO.
>>>>>>
>>>>>> So AFAICS Round Robin is not used anymore by anyone. And my
>>>>>> understanding indeed is, too, that there is not really any use-case
>>>>>> where one would like anything except for FIFO.
>>>>>>
>>>>>> Looking at 977d97f18b5b ("drm/scheduler: Set the FIFO scheduling policy
>>>>>> as the default"), it seems to me that RR just was easy to implement and
>>>>>> it had the disadvantage of systems under high load cause the oldest job
>>>>>> to be starved to death, which is why FIFO was introduced.
>>>>>>
>>>>>> So my guess would be that RR just is a relict.
>>>>>>
>>>>>> If we agree on that, then we could remove RR in any case, and the
>>>>>> subsequent question would be whether FIFO should be replaced with
>>>>>> deadline (or: if there should be FIFO *and* deadline?), wouldn't it?
>>>>>
>>>>> I am unsure about RR but I agree what is the second part of the question.
>>>>
>>>> Well we came up with FIFO because we found that RR performed quite badly when you have a huge number of submitting applications.
>>>>
>>>> E.g. one of our cloud test cases ran 100 instances of a single game and the worst response time improved massively by switching from RR to FIFO.
>>>>
>>>> Different priorities on the other hand were originally invented to make sure the kernel has precedence over userspace. But later we also exposed the priorities to userspace which results in the problem that higher priority queues can starve low priority ones.
>>>
>>> FWIW, that can't explain why RR worked better in the scenario I described in https://gitlab.freedesktop.org/drm/amd/-/issues/2516#note_2119750, Xwayland uses normal GPU scheduling priority, just like the game.
>>>
>>>
>>>> That's the other reason why I said that RR should probably be removed and FIFO changed in a way that the priority is basically just a bonus to the score used for sorting the FIFO. I haven't taken a deeper look yet, but I think that this is more or less what this patch set here does.
>>>
>>> FWIW, people are saying RR works better than FIFO for some gaming scenarios even with current Xwayland, which shouldn't do any GPU copies for presentation of fullscreen windows. There seem to be other interactions which work better with RR than FIFO from the user PoV. If RR is to be removed, I'd recommend making sure deadline works at least as well as RR for those.
>>>
>>>
>>>> What FIFO is still missing compared to RR is some sort of fairness between queues. E.g. a queues which hasn't submitted something in a while might get a bonus for their submissions compared to a queue which submits stuff all the time (or something like that).
>>>
>>> The lack of that could indeed explain the scenario above, if the game submits its GPU job for frame n+1 before Xwayland submits its GPU job for presenting frame n.
>>
>> I would be keen to experiment with this. There is that last patch in v2 of my series which scales the deadlines based on queue depth. So for a client which submits two frames it could be enough (in principle, not the actually posted version) to push out the deadline at qd=2 so a client which never breaks qd=1 can reliably overtake it.
>>
>> What would really be great if you could suggest me as easy to set up as possible test case with objective measuring criteria. And it would have to run on AMD. Quake II RTX under XWayland as the GitLab issue suggest or there is more to it? Does it has to be GNOME?
>
> Don't think it has to be.
>
>> Any way to run it programmatically and get a performance number out?
>
> This could be tricky, since the game itself reports the same frame rate in both cases. You'd have to compare the frame times in the compositor instead.
So missed frames in the compositor?
> Also, the issue might no longer be reproducible in this particular scenario with current Xwayland, because it should no longer do any GPU copies for presentation but just forward the client buffers to the compositor.
Do you have an idea how could we find out more about that what you said:
"people are saying RR works better than FIFO for some gaming scenarios
even with current Xwayland, which shouldn't do any GPU copies for
presentation of fullscreen windows"?
Regards,
Tvrtko
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-13 11:40 ` Tvrtko Ursulin
@ 2025-01-13 15:29 ` Michel Dänzer
2025-01-15 13:38 ` Tvrtko Ursulin
0 siblings, 1 reply; 61+ messages in thread
From: Michel Dänzer @ 2025-01-13 15:29 UTC (permalink / raw)
To: Tvrtko Ursulin, Christian König, Philipp Stanner,
Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Danilo Krummrich, Matthew Brost
On 2025-01-13 12:40, Tvrtko Ursulin wrote:
> On 10/01/2025 09:14, Michel Dänzer wrote:
>> On 2025-01-09 17:55, Tvrtko Ursulin wrote:
>>> On 09/01/2025 15:08, Michel Dänzer wrote:
>>>> On 2025-01-03 13:31, Christian König wrote:
>>>>
>>>>> What FIFO is still missing compared to RR is some sort of fairness between queues. E.g. a queues which hasn't submitted something in a while might get a bonus for their submissions compared to a queue which submits stuff all the time (or something like that).
>>>>
>>>> The lack of that could indeed explain the scenario above, if the game submits its GPU job for frame n+1 before Xwayland submits its GPU job for presenting frame n.
>>>
>>> I would be keen to experiment with this. There is that last patch in v2 of my series which scales the deadlines based on queue depth. So for a client which submits two frames it could be enough (in principle, not the actually posted version) to push out the deadline at qd=2 so a client which never breaks qd=1 can reliably overtake it.
>>>
>>> What would really be great if you could suggest me as easy to set up as possible test case with objective measuring criteria. And it would have to run on AMD. Quake II RTX under XWayland as the GitLab issue suggest or there is more to it? Does it has to be GNOME?
>>
>> Don't think it has to be.
>>
>>> Any way to run it programmatically and get a performance number out?
>>
>> This could be tricky, since the game itself reports the same frame rate in both cases. You'd have to compare the frame times in the compositor instead.
>
> So missed frames in the compositor?
Rather in Xwayland, the compositor is where it's visible to the user.
>> Also, the issue might no longer be reproducible in this particular scenario with current Xwayland, because it should no longer do any GPU copies for presentation but just forward the client buffers to the compositor.
> Do you have an idea how could we find out more about that what you said: "people are saying RR works better than FIFO for some gaming scenarios even with current Xwayland, which shouldn't do any GPU copies for presentation of fullscreen windows"?
Other than asking affected users for more information, not offhand.
--
Earthling Michel Dänzer \ GNOME / Xwayland / Mesa developer
https://redhat.com \ Libre software enthusiast
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-13 15:29 ` Michel Dänzer
@ 2025-01-15 13:38 ` Tvrtko Ursulin
2025-01-15 14:46 ` Michel Dänzer
0 siblings, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-15 13:38 UTC (permalink / raw)
To: Michel Dänzer, Christian König, Philipp Stanner,
Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Danilo Krummrich, Matthew Brost
On 13/01/2025 15:29, Michel Dänzer wrote:
> On 2025-01-13 12:40, Tvrtko Ursulin wrote:
>> On 10/01/2025 09:14, Michel Dänzer wrote:
>>> On 2025-01-09 17:55, Tvrtko Ursulin wrote:
>>>> On 09/01/2025 15:08, Michel Dänzer wrote:
>>>>> On 2025-01-03 13:31, Christian König wrote:
>>>>>
>>>>>> What FIFO is still missing compared to RR is some sort of fairness between queues. E.g. a queues which hasn't submitted something in a while might get a bonus for their submissions compared to a queue which submits stuff all the time (or something like that).
>>>>>
>>>>> The lack of that could indeed explain the scenario above, if the game submits its GPU job for frame n+1 before Xwayland submits its GPU job for presenting frame n.
>>>>
>>>> I would be keen to experiment with this. There is that last patch in v2 of my series which scales the deadlines based on queue depth. So for a client which submits two frames it could be enough (in principle, not the actually posted version) to push out the deadline at qd=2 so a client which never breaks qd=1 can reliably overtake it.
>>>>
>>>> What would really be great if you could suggest me as easy to set up as possible test case with objective measuring criteria. And it would have to run on AMD. Quake II RTX under XWayland as the GitLab issue suggest or there is more to it? Does it has to be GNOME?
>>>
>>> Don't think it has to be.
>>>
>>>> Any way to run it programmatically and get a performance number out?
>>>
>>> This could be tricky, since the game itself reports the same frame rate in both cases. You'd have to compare the frame times in the compositor instead.
>>
>> So missed frames in the compositor?
>
> Rather in Xwayland, the compositor is where it's visible to the user.
How would you suggest to instrument this, or what debug/logs to enable
to see it?
>>> Also, the issue might no longer be reproducible in this particular scenario with current Xwayland, because it should no longer do any GPU copies for presentation but just forward the client buffers to the compositor.
>> Do you have an idea how could we find out more about that what you said: "people are saying RR works better than FIFO for some gaming scenarios even with current Xwayland, which shouldn't do any GPU copies for presentation of fullscreen windows"?
>
> Other than asking affected users for more information, not offhand.
Could you find out more?
I currently don't have an idea how, with direct scanout ie. single
rendering client, FIFO vs RR would make a difference.
For scenarios where copying is involved, experimenting/tweaking the
frontend/DRM scheduler is not trivial. In the sense that for some
approaches involving looking at the submission queue depth, such I
mentioned before, it would require non-trivial refactoring. Which does
not seem to be popular. And the resulting change in behaviour would be
driver dependant too.
Btw what is the situation with context priority and compositors? Are
they requesting high or sticking with the defaults?
Regards,
Tvrtko
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-15 13:38 ` Tvrtko Ursulin
@ 2025-01-15 14:46 ` Michel Dänzer
0 siblings, 0 replies; 61+ messages in thread
From: Michel Dänzer @ 2025-01-15 14:46 UTC (permalink / raw)
To: Tvrtko Ursulin, Christian König, Philipp Stanner,
Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Danilo Krummrich, Matthew Brost
On 2025-01-15 14:38, Tvrtko Ursulin wrote:
> On 13/01/2025 15:29, Michel Dänzer wrote:
>> On 2025-01-13 12:40, Tvrtko Ursulin wrote:
>>> On 10/01/2025 09:14, Michel Dänzer wrote:
>>>> On 2025-01-09 17:55, Tvrtko Ursulin wrote:
>>>>> On 09/01/2025 15:08, Michel Dänzer wrote:
>>>>>> On 2025-01-03 13:31, Christian König wrote:
>>>>>>
>>>>>>> What FIFO is still missing compared to RR is some sort of fairness between queues. E.g. a queues which hasn't submitted something in a while might get a bonus for their submissions compared to a queue which submits stuff all the time (or something like that).
>>>>>>
>>>>>> The lack of that could indeed explain the scenario above, if the game submits its GPU job for frame n+1 before Xwayland submits its GPU job for presenting frame n.
>>>>>
>>>>> I would be keen to experiment with this. There is that last patch in v2 of my series which scales the deadlines based on queue depth. So for a client which submits two frames it could be enough (in principle, not the actually posted version) to push out the deadline at qd=2 so a client which never breaks qd=1 can reliably overtake it.
>>>>>
>>>>> What would really be great if you could suggest me as easy to set up as possible test case with objective measuring criteria. And it would have to run on AMD. Quake II RTX under XWayland as the GitLab issue suggest or there is more to it? Does it has to be GNOME?
>>>>
>>>> Don't think it has to be.
>>>>
>>>>> Any way to run it programmatically and get a performance number out?
>>>>
>>>> This could be tricky, since the game itself reports the same frame rate in both cases. You'd have to compare the frame times in the compositor instead.
>>>
>>> So missed frames in the compositor?
>>
>> Rather in Xwayland, the compositor is where it's visible to the user.
>
> How would you suggest to instrument this, or what debug/logs to enable to see it?
>>>> Also, the issue might no longer be reproducible in this particular scenario with current Xwayland, because it should no longer do any GPU copies for presentation but just forward the client buffers to the compositor.
>>> Do you have an idea how could we find out more about that what you said: "people are saying RR works better than FIFO for some gaming scenarios even with current Xwayland, which shouldn't do any GPU copies for presentation of fullscreen windows"?
>>
>> Other than asking affected users for more information, not offhand.
>
> Could you find out more?
Sorry, I don't have any particular personal interest or stake in this. I'm just pointing out that "FIFO is better than RR" isn't universally true.
Reaching out to affected users on https://gitlab.freedesktop.org/drm/amd/-/issues/2516 would seem like a possible start.
> I currently don't have an idea how, with direct scanout ie. single rendering client, FIFO vs RR would make a difference.
I saw one user mentioning they have "many background tasks", maybe some of those are using the GPU as well.
> Btw what is the situation with context priority and compositors? Are they requesting high or sticking with the defaults?
Requesting high. (Not that it makes much difference in practice if higher-priority jobs can't preempt lower-priority ones already in flight, as is the case with amdgpu without user-mode queues)
--
Earthling Michel Dänzer \ GNOME / Xwayland / Mesa developer
https://redhat.com \ Libre software enthusiast
^ permalink raw reply [flat|nested] 61+ messages in thread
* AW: [RFC 00/14] Deadline scheduler and other ideas
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
` (14 preceding siblings ...)
2025-01-02 13:09 ` [RFC 00/14] Deadline scheduler and other ideas Philipp Stanner
@ 2025-01-03 15:16 ` Koenig, Christian
2025-01-03 15:32 ` Tvrtko Ursulin
2025-01-06 13:47 ` Simona Vetter
2025-01-08 8:31 ` Danilo Krummrich
2025-01-17 12:12 ` Philipp Stanner
17 siblings, 2 replies; 61+ messages in thread
From: Koenig, Christian @ 2025-01-03 15:16 UTC (permalink / raw)
To: Tvrtko Ursulin, dri-devel@lists.freedesktop.org
Cc: kernel-dev@igalia.com, Tvrtko Ursulin, Danilo Krummrich,
Matthew Brost, Philipp Stanner
[AMD Official Use Only - AMD Internal Distribution Only]
Could you send that whole patch set to me once more?
The AMD mails servers seem to have had a hickup over the holidays and all mails received between ~25.12.2024 and 1.1.2025 are somehow mangled.
Thanks in advance,
Christian.
________________________________________
Von: Tvrtko Ursulin <tursulin@igalia.com>
Gesendet: Montag, 30. Dezember 2024 17:52
An: dri-devel@lists.freedesktop.org
Cc: kernel-dev@igalia.com; Tvrtko Ursulin; Koenig, Christian; Danilo Krummrich; Matthew Brost; Philipp Stanner
Betreff: [RFC 00/14] Deadline scheduler and other ideas
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
<tldr>
Replacing FIFO with a flavour of deadline driven scheduling and removing round-
robin. Connecting the scheduler with dma-fence deadlines. First draft and
testing by different drivers and feedback would be nice. I was only able to test
it with amdgpu. Other drivers may not even compile.
</tldr>
If I remember correctly Christian mentioned recently (give or take) that maybe
round-robin could be removed. That got me thinking how and what could be
improved and simplified. So I played a bit in the scheduler code and came up
with something which appears to not crash at least. Whether or not there are
significant advantages apart from maybe code consolidation and reduction is the
main thing to be determined.
One big question is whether round-robin can really be removed. Does anyone use
it, rely on it, or what are even use cases where it is much better than FIFO.
See "drm/sched: Add deadline policy" commit message for a short description on
what flavour of deadline scheduling it is. But in essence it should a more fair
FIFO where higher priority can not forever starve lower priorities.
"drm/sched: Connect with dma-fence deadlines" wires up dma-fence deadlines to
the scheduler because it is easy and makes logical sense with this. And I
noticed userspace already uses it so why not wire it up fully.
Otherwise the series is a bit of progression from consolidating RR into FIFO
code paths and going from there to deadline and then to a change in how
dependencies are handled. And code simplification to 1:1 run queue to scheduler
relationship, because deadline does not need per priority run queues.
There is quite a bit of code to go throught here so I think it could be even
better if other drivers could give it a spin as is and see if some improvements
can be detected. Or at least no regressions.
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <pstanner@redhat.com>
Tvrtko Ursulin (14):
drm/sched: Delete unused update_job_credits
drm/sched: Remove idle entity from tree
drm/sched: Implement RR via FIFO
drm/sched: Consolidate entity run queue management
drm/sched: Move run queue related code into a separate file
drm/sched: Ignore own fence earlier
drm/sched: Resolve same scheduler dependencies earlier
drm/sched: Add deadline policy
drm/sched: Remove FIFO and RR and simplify to a single run queue
drm/sched: Queue all free credits in one worker invocation
drm/sched: Connect with dma-fence deadlines
drm/sched: Embed run queue singleton into the scheduler
dma-fence: Add helper for custom fence context when merging fences
drm/sched: Resolve all job dependencies in one go
drivers/dma-buf/dma-fence-unwrap.c | 8 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 27 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 5 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 8 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 8 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 8 +-
drivers/gpu/drm/scheduler/Makefile | 2 +-
drivers/gpu/drm/scheduler/sched_entity.c | 316 ++++++-----
drivers/gpu/drm/scheduler/sched_fence.c | 5 +-
drivers/gpu/drm/scheduler/sched_main.c | 587 +++++---------------
drivers/gpu/drm/scheduler/sched_rq.c | 199 +++++++
include/drm/gpu_scheduler.h | 74 ++-
include/linux/dma-fence-unwrap.h | 31 +-
14 files changed, 606 insertions(+), 678 deletions(-)
create mode 100644 drivers/gpu/drm/scheduler/sched_rq.c
--
2.47.1
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: AW: [RFC 00/14] Deadline scheduler and other ideas
2025-01-03 15:16 ` AW: " Koenig, Christian
@ 2025-01-03 15:32 ` Tvrtko Ursulin
2025-01-06 13:47 ` Simona Vetter
1 sibling, 0 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-03 15:32 UTC (permalink / raw)
To: Koenig, Christian, Tvrtko Ursulin,
dri-devel@lists.freedesktop.org
Cc: kernel-dev@igalia.com, Danilo Krummrich, Matthew Brost,
Philipp Stanner
On 03/01/2025 15:16, Koenig, Christian wrote:
> [AMD Official Use Only - AMD Internal Distribution Only]
>
> Could you send that whole patch set to me once more?
No problem - I've pushed it to
https://gitlab.freedesktop.org/tursulin/kernel/-/commits/drm-sched-deadline?ref_type=heads,
that's probably even easier, right?
Regards,
Tvrtko
> The AMD mails servers seem to have had a hickup over the holidays and all mails received between ~25.12.2024 and 1.1.2025 are somehow mangled.
>
> Thanks in advance,
> Christian.
>
> ________________________________________
> Von: Tvrtko Ursulin <tursulin@igalia.com>
> Gesendet: Montag, 30. Dezember 2024 17:52
> An: dri-devel@lists.freedesktop.org
> Cc: kernel-dev@igalia.com; Tvrtko Ursulin; Koenig, Christian; Danilo Krummrich; Matthew Brost; Philipp Stanner
> Betreff: [RFC 00/14] Deadline scheduler and other ideas
>
> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>
> <tldr>
> Replacing FIFO with a flavour of deadline driven scheduling and removing round-
> robin. Connecting the scheduler with dma-fence deadlines. First draft and
> testing by different drivers and feedback would be nice. I was only able to test
> it with amdgpu. Other drivers may not even compile.
> </tldr>
>
> If I remember correctly Christian mentioned recently (give or take) that maybe
> round-robin could be removed. That got me thinking how and what could be
> improved and simplified. So I played a bit in the scheduler code and came up
> with something which appears to not crash at least. Whether or not there are
> significant advantages apart from maybe code consolidation and reduction is the
> main thing to be determined.
>
> One big question is whether round-robin can really be removed. Does anyone use
> it, rely on it, or what are even use cases where it is much better than FIFO.
>
> See "drm/sched: Add deadline policy" commit message for a short description on
> what flavour of deadline scheduling it is. But in essence it should a more fair
> FIFO where higher priority can not forever starve lower priorities.
>
> "drm/sched: Connect with dma-fence deadlines" wires up dma-fence deadlines to
> the scheduler because it is easy and makes logical sense with this. And I
> noticed userspace already uses it so why not wire it up fully.
>
> Otherwise the series is a bit of progression from consolidating RR into FIFO
> code paths and going from there to deadline and then to a change in how
> dependencies are handled. And code simplification to 1:1 run queue to scheduler
> relationship, because deadline does not need per priority run queues.
>
> There is quite a bit of code to go throught here so I think it could be even
> better if other drivers could give it a spin as is and see if some improvements
> can be detected. Or at least no regressions.
>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: Danilo Krummrich <dakr@redhat.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Philipp Stanner <pstanner@redhat.com>
>
> Tvrtko Ursulin (14):
> drm/sched: Delete unused update_job_credits
> drm/sched: Remove idle entity from tree
> drm/sched: Implement RR via FIFO
> drm/sched: Consolidate entity run queue management
> drm/sched: Move run queue related code into a separate file
> drm/sched: Ignore own fence earlier
> drm/sched: Resolve same scheduler dependencies earlier
> drm/sched: Add deadline policy
> drm/sched: Remove FIFO and RR and simplify to a single run queue
> drm/sched: Queue all free credits in one worker invocation
> drm/sched: Connect with dma-fence deadlines
> drm/sched: Embed run queue singleton into the scheduler
> dma-fence: Add helper for custom fence context when merging fences
> drm/sched: Resolve all job dependencies in one go
>
> drivers/dma-buf/dma-fence-unwrap.c | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 27 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 5 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 8 +-
> drivers/gpu/drm/scheduler/Makefile | 2 +-
> drivers/gpu/drm/scheduler/sched_entity.c | 316 ++++++-----
> drivers/gpu/drm/scheduler/sched_fence.c | 5 +-
> drivers/gpu/drm/scheduler/sched_main.c | 587 +++++---------------
> drivers/gpu/drm/scheduler/sched_rq.c | 199 +++++++
> include/drm/gpu_scheduler.h | 74 ++-
> include/linux/dma-fence-unwrap.h | 31 +-
> 14 files changed, 606 insertions(+), 678 deletions(-)
> create mode 100644 drivers/gpu/drm/scheduler/sched_rq.c
>
> --
> 2.47.1
>
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: AW: [RFC 00/14] Deadline scheduler and other ideas
2025-01-03 15:16 ` AW: " Koenig, Christian
2025-01-03 15:32 ` Tvrtko Ursulin
@ 2025-01-06 13:47 ` Simona Vetter
2025-01-08 8:07 ` Philipp Stanner
1 sibling, 1 reply; 61+ messages in thread
From: Simona Vetter @ 2025-01-06 13:47 UTC (permalink / raw)
To: Koenig, Christian
Cc: Tvrtko Ursulin, dri-devel@lists.freedesktop.org,
kernel-dev@igalia.com, Tvrtko Ursulin, Danilo Krummrich,
Matthew Brost, Philipp Stanner
On Fri, Jan 03, 2025 at 03:16:56PM +0000, Koenig, Christian wrote:
> [AMD Official Use Only - AMD Internal Distribution Only]
>
> Could you send that whole patch set to me once more?
>
> The AMD mails servers seem to have had a hickup over the holidays and
> all mails received between ~25.12.2024 and 1.1.2025 are somehow mangled.
I seem to have the same issue with fetching from lore.o.k, despite that
the archives seem to be complete. No idea what's happened.
-Sima
>
> Thanks in advance,
> Christian.
>
> ________________________________________
> Von: Tvrtko Ursulin <tursulin@igalia.com>
> Gesendet: Montag, 30. Dezember 2024 17:52
> An: dri-devel@lists.freedesktop.org
> Cc: kernel-dev@igalia.com; Tvrtko Ursulin; Koenig, Christian; Danilo Krummrich; Matthew Brost; Philipp Stanner
> Betreff: [RFC 00/14] Deadline scheduler and other ideas
>
> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>
> <tldr>
> Replacing FIFO with a flavour of deadline driven scheduling and removing round-
> robin. Connecting the scheduler with dma-fence deadlines. First draft and
> testing by different drivers and feedback would be nice. I was only able to test
> it with amdgpu. Other drivers may not even compile.
> </tldr>
>
> If I remember correctly Christian mentioned recently (give or take) that maybe
> round-robin could be removed. That got me thinking how and what could be
> improved and simplified. So I played a bit in the scheduler code and came up
> with something which appears to not crash at least. Whether or not there are
> significant advantages apart from maybe code consolidation and reduction is the
> main thing to be determined.
>
> One big question is whether round-robin can really be removed. Does anyone use
> it, rely on it, or what are even use cases where it is much better than FIFO.
>
> See "drm/sched: Add deadline policy" commit message for a short description on
> what flavour of deadline scheduling it is. But in essence it should a more fair
> FIFO where higher priority can not forever starve lower priorities.
>
> "drm/sched: Connect with dma-fence deadlines" wires up dma-fence deadlines to
> the scheduler because it is easy and makes logical sense with this. And I
> noticed userspace already uses it so why not wire it up fully.
>
> Otherwise the series is a bit of progression from consolidating RR into FIFO
> code paths and going from there to deadline and then to a change in how
> dependencies are handled. And code simplification to 1:1 run queue to scheduler
> relationship, because deadline does not need per priority run queues.
>
> There is quite a bit of code to go throught here so I think it could be even
> better if other drivers could give it a spin as is and see if some improvements
> can be detected. Or at least no regressions.
>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: Danilo Krummrich <dakr@redhat.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Philipp Stanner <pstanner@redhat.com>
>
> Tvrtko Ursulin (14):
> drm/sched: Delete unused update_job_credits
> drm/sched: Remove idle entity from tree
> drm/sched: Implement RR via FIFO
> drm/sched: Consolidate entity run queue management
> drm/sched: Move run queue related code into a separate file
> drm/sched: Ignore own fence earlier
> drm/sched: Resolve same scheduler dependencies earlier
> drm/sched: Add deadline policy
> drm/sched: Remove FIFO and RR and simplify to a single run queue
> drm/sched: Queue all free credits in one worker invocation
> drm/sched: Connect with dma-fence deadlines
> drm/sched: Embed run queue singleton into the scheduler
> dma-fence: Add helper for custom fence context when merging fences
> drm/sched: Resolve all job dependencies in one go
>
> drivers/dma-buf/dma-fence-unwrap.c | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 27 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 5 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 8 +-
> drivers/gpu/drm/scheduler/Makefile | 2 +-
> drivers/gpu/drm/scheduler/sched_entity.c | 316 ++++++-----
> drivers/gpu/drm/scheduler/sched_fence.c | 5 +-
> drivers/gpu/drm/scheduler/sched_main.c | 587 +++++---------------
> drivers/gpu/drm/scheduler/sched_rq.c | 199 +++++++
> include/drm/gpu_scheduler.h | 74 ++-
> include/linux/dma-fence-unwrap.h | 31 +-
> 14 files changed, 606 insertions(+), 678 deletions(-)
> create mode 100644 drivers/gpu/drm/scheduler/sched_rq.c
>
> --
> 2.47.1
>
--
Simona Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: AW: [RFC 00/14] Deadline scheduler and other ideas
2025-01-06 13:47 ` Simona Vetter
@ 2025-01-08 8:07 ` Philipp Stanner
2025-01-08 17:59 ` Simona Vetter
0 siblings, 1 reply; 61+ messages in thread
From: Philipp Stanner @ 2025-01-08 8:07 UTC (permalink / raw)
To: Simona Vetter, Koenig, Christian
Cc: Tvrtko Ursulin, dri-devel@lists.freedesktop.org,
kernel-dev@igalia.com, Tvrtko Ursulin, Danilo Krummrich,
Matthew Brost
On Mon, 2025-01-06 at 14:47 +0100, Simona Vetter wrote:
> On Fri, Jan 03, 2025 at 03:16:56PM +0000, Koenig, Christian wrote:
> > [AMD Official Use Only - AMD Internal Distribution Only]
> >
> > Could you send that whole patch set to me once more?
> >
> > The AMD mails servers seem to have had a hickup over the holidays
> > and
> > all mails received between ~25.12.2024 and 1.1.2025 are somehow
> > mangled.
>
> I seem to have the same issue with fetching from lore.o.k, despite
> that
> the archives seem to be complete. No idea what's happened.
I could pull it just fine with b4
P.
> -Sima
>
> >
> > Thanks in advance,
> > Christian.
> >
> > ________________________________________
> > Von: Tvrtko Ursulin <tursulin@igalia.com>
> > Gesendet: Montag, 30. Dezember 2024 17:52
> > An: dri-devel@lists.freedesktop.org
> > Cc: kernel-dev@igalia.com; Tvrtko Ursulin; Koenig, Christian;
> > Danilo Krummrich; Matthew Brost; Philipp Stanner
> > Betreff: [RFC 00/14] Deadline scheduler and other ideas
> >
> > From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> >
> > <tldr>
> > Replacing FIFO with a flavour of deadline driven scheduling and
> > removing round-
> > robin. Connecting the scheduler with dma-fence deadlines. First
> > draft and
> > testing by different drivers and feedback would be nice. I was only
> > able to test
> > it with amdgpu. Other drivers may not even compile.
> > </tldr>
> >
> > If I remember correctly Christian mentioned recently (give or take)
> > that maybe
> > round-robin could be removed. That got me thinking how and what
> > could be
> > improved and simplified. So I played a bit in the scheduler code
> > and came up
> > with something which appears to not crash at least. Whether or not
> > there are
> > significant advantages apart from maybe code consolidation and
> > reduction is the
> > main thing to be determined.
> >
> > One big question is whether round-robin can really be removed. Does
> > anyone use
> > it, rely on it, or what are even use cases where it is much better
> > than FIFO.
> >
> > See "drm/sched: Add deadline policy" commit message for a short
> > description on
> > what flavour of deadline scheduling it is. But in essence it should
> > a more fair
> > FIFO where higher priority can not forever starve lower priorities.
> >
> > "drm/sched: Connect with dma-fence deadlines" wires up dma-fence
> > deadlines to
> > the scheduler because it is easy and makes logical sense with this.
> > And I
> > noticed userspace already uses it so why not wire it up fully.
> >
> > Otherwise the series is a bit of progression from consolidating RR
> > into FIFO
> > code paths and going from there to deadline and then to a change in
> > how
> > dependencies are handled. And code simplification to 1:1 run queue
> > to scheduler
> > relationship, because deadline does not need per priority run
> > queues.
> >
> > There is quite a bit of code to go throught here so I think it
> > could be even
> > better if other drivers could give it a spin as is and see if some
> > improvements
> > can be detected. Or at least no regressions.
> >
> > Cc: Christian König <christian.koenig@amd.com>
> > Cc: Danilo Krummrich <dakr@redhat.com>
> > Cc: Matthew Brost <matthew.brost@intel.com>
> > Cc: Philipp Stanner <pstanner@redhat.com>
> >
> > Tvrtko Ursulin (14):
> > drm/sched: Delete unused update_job_credits
> > drm/sched: Remove idle entity from tree
> > drm/sched: Implement RR via FIFO
> > drm/sched: Consolidate entity run queue management
> > drm/sched: Move run queue related code into a separate file
> > drm/sched: Ignore own fence earlier
> > drm/sched: Resolve same scheduler dependencies earlier
> > drm/sched: Add deadline policy
> > drm/sched: Remove FIFO and RR and simplify to a single run queue
> > drm/sched: Queue all free credits in one worker invocation
> > drm/sched: Connect with dma-fence deadlines
> > drm/sched: Embed run queue singleton into the scheduler
> > dma-fence: Add helper for custom fence context when merging
> > fences
> > drm/sched: Resolve all job dependencies in one go
> >
> > drivers/dma-buf/dma-fence-unwrap.c | 8 +-
> > drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +-
> > drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 27 +-
> > drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 5 +-
> > drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 8 +-
> > drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 8 +-
> > drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 8 +-
> > drivers/gpu/drm/scheduler/Makefile | 2 +-
> > drivers/gpu/drm/scheduler/sched_entity.c | 316 ++++++-----
> > drivers/gpu/drm/scheduler/sched_fence.c | 5 +-
> > drivers/gpu/drm/scheduler/sched_main.c | 587 +++++-----------
> > ----
> > drivers/gpu/drm/scheduler/sched_rq.c | 199 +++++++
> > include/drm/gpu_scheduler.h | 74 ++-
> > include/linux/dma-fence-unwrap.h | 31 +-
> > 14 files changed, 606 insertions(+), 678 deletions(-)
> > create mode 100644 drivers/gpu/drm/scheduler/sched_rq.c
> >
> > --
> > 2.47.1
> >
>
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: AW: [RFC 00/14] Deadline scheduler and other ideas
2025-01-08 8:07 ` Philipp Stanner
@ 2025-01-08 17:59 ` Simona Vetter
2025-01-08 18:06 ` Tvrtko Ursulin
0 siblings, 1 reply; 61+ messages in thread
From: Simona Vetter @ 2025-01-08 17:59 UTC (permalink / raw)
To: Philipp Stanner
Cc: Simona Vetter, Koenig, Christian, Tvrtko Ursulin,
dri-devel@lists.freedesktop.org, kernel-dev@igalia.com,
Tvrtko Ursulin, Danilo Krummrich, Matthew Brost
On Wed, Jan 08, 2025 at 09:07:44AM +0100, Philipp Stanner wrote:
> On Mon, 2025-01-06 at 14:47 +0100, Simona Vetter wrote:
> > On Fri, Jan 03, 2025 at 03:16:56PM +0000, Koenig, Christian wrote:
> > > [AMD Official Use Only - AMD Internal Distribution Only]
> > >
> > > Could you send that whole patch set to me once more?
> > >
> > > The AMD mails servers seem to have had a hickup over the holidays
> > > and
> > > all mails received between ~25.12.2024 and 1.1.2025 are somehow
> > > mangled.
> >
> > I seem to have the same issue with fetching from lore.o.k, despite
> > that
> > the archives seem to be complete. No idea what's happened.
>
> I could pull it just fine with b4
Yeah now they all just magically showed up. No idea what happened.
-Sima
>
> P.
>
> > -Sima
> >
> > >
> > > Thanks in advance,
> > > Christian.
> > >
> > > ________________________________________
> > > Von: Tvrtko Ursulin <tursulin@igalia.com>
> > > Gesendet: Montag, 30. Dezember 2024 17:52
> > > An: dri-devel@lists.freedesktop.org
> > > Cc: kernel-dev@igalia.com; Tvrtko Ursulin; Koenig, Christian;
> > > Danilo Krummrich; Matthew Brost; Philipp Stanner
> > > Betreff: [RFC 00/14] Deadline scheduler and other ideas
> > >
> > > From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> > >
> > > <tldr>
> > > Replacing FIFO with a flavour of deadline driven scheduling and
> > > removing round-
> > > robin. Connecting the scheduler with dma-fence deadlines. First
> > > draft and
> > > testing by different drivers and feedback would be nice. I was only
> > > able to test
> > > it with amdgpu. Other drivers may not even compile.
> > > </tldr>
> > >
> > > If I remember correctly Christian mentioned recently (give or take)
> > > that maybe
> > > round-robin could be removed. That got me thinking how and what
> > > could be
> > > improved and simplified. So I played a bit in the scheduler code
> > > and came up
> > > with something which appears to not crash at least. Whether or not
> > > there are
> > > significant advantages apart from maybe code consolidation and
> > > reduction is the
> > > main thing to be determined.
> > >
> > > One big question is whether round-robin can really be removed. Does
> > > anyone use
> > > it, rely on it, or what are even use cases where it is much better
> > > than FIFO.
> > >
> > > See "drm/sched: Add deadline policy" commit message for a short
> > > description on
> > > what flavour of deadline scheduling it is. But in essence it should
> > > a more fair
> > > FIFO where higher priority can not forever starve lower priorities.
> > >
> > > "drm/sched: Connect with dma-fence deadlines" wires up dma-fence
> > > deadlines to
> > > the scheduler because it is easy and makes logical sense with this.
> > > And I
> > > noticed userspace already uses it so why not wire it up fully.
> > >
> > > Otherwise the series is a bit of progression from consolidating RR
> > > into FIFO
> > > code paths and going from there to deadline and then to a change in
> > > how
> > > dependencies are handled. And code simplification to 1:1 run queue
> > > to scheduler
> > > relationship, because deadline does not need per priority run
> > > queues.
> > >
> > > There is quite a bit of code to go throught here so I think it
> > > could be even
> > > better if other drivers could give it a spin as is and see if some
> > > improvements
> > > can be detected. Or at least no regressions.
> > >
> > > Cc: Christian König <christian.koenig@amd.com>
> > > Cc: Danilo Krummrich <dakr@redhat.com>
> > > Cc: Matthew Brost <matthew.brost@intel.com>
> > > Cc: Philipp Stanner <pstanner@redhat.com>
> > >
> > > Tvrtko Ursulin (14):
> > > drm/sched: Delete unused update_job_credits
> > > drm/sched: Remove idle entity from tree
> > > drm/sched: Implement RR via FIFO
> > > drm/sched: Consolidate entity run queue management
> > > drm/sched: Move run queue related code into a separate file
> > > drm/sched: Ignore own fence earlier
> > > drm/sched: Resolve same scheduler dependencies earlier
> > > drm/sched: Add deadline policy
> > > drm/sched: Remove FIFO and RR and simplify to a single run queue
> > > drm/sched: Queue all free credits in one worker invocation
> > > drm/sched: Connect with dma-fence deadlines
> > > drm/sched: Embed run queue singleton into the scheduler
> > > dma-fence: Add helper for custom fence context when merging
> > > fences
> > > drm/sched: Resolve all job dependencies in one go
> > >
> > > drivers/dma-buf/dma-fence-unwrap.c | 8 +-
> > > drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +-
> > > drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 27 +-
> > > drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 5 +-
> > > drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 8 +-
> > > drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 8 +-
> > > drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 8 +-
> > > drivers/gpu/drm/scheduler/Makefile | 2 +-
> > > drivers/gpu/drm/scheduler/sched_entity.c | 316 ++++++-----
> > > drivers/gpu/drm/scheduler/sched_fence.c | 5 +-
> > > drivers/gpu/drm/scheduler/sched_main.c | 587 +++++-----------
> > > ----
> > > drivers/gpu/drm/scheduler/sched_rq.c | 199 +++++++
> > > include/drm/gpu_scheduler.h | 74 ++-
> > > include/linux/dma-fence-unwrap.h | 31 +-
> > > 14 files changed, 606 insertions(+), 678 deletions(-)
> > > create mode 100644 drivers/gpu/drm/scheduler/sched_rq.c
> > >
> > > --
> > > 2.47.1
> > >
> >
>
--
Simona Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: AW: [RFC 00/14] Deadline scheduler and other ideas
2025-01-08 17:59 ` Simona Vetter
@ 2025-01-08 18:06 ` Tvrtko Ursulin
0 siblings, 0 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-08 18:06 UTC (permalink / raw)
To: Simona Vetter, Philipp Stanner
Cc: Koenig, Christian, Tvrtko Ursulin,
dri-devel@lists.freedesktop.org, kernel-dev@igalia.com,
Danilo Krummrich, Matthew Brost
On 08/01/2025 17:59, Simona Vetter wrote:
> On Wed, Jan 08, 2025 at 09:07:44AM +0100, Philipp Stanner wrote:
>> On Mon, 2025-01-06 at 14:47 +0100, Simona Vetter wrote:
>>> On Fri, Jan 03, 2025 at 03:16:56PM +0000, Koenig, Christian wrote:
>>>> [AMD Official Use Only - AMD Internal Distribution Only]
>>>>
>>>> Could you send that whole patch set to me once more?
>>>>
>>>> The AMD mails servers seem to have had a hickup over the holidays
>>>> and
>>>> all mails received between ~25.12.2024 and 1.1.2025 are somehow
>>>> mangled.
>>>
>>> I seem to have the same issue with fetching from lore.o.k, despite
>>> that
>>> the archives seem to be complete. No idea what's happened.
>>
>> I could pull it just fine with b4
>
> Yeah now they all just magically showed up. No idea what happened.
You can hold off reading until v2 of the series.
Or if you really want some reading material for a cold winter's evening
you could have a look at the syncobj optimisation series. ;)
Regards,
Tvrtko
>>>> Thanks in advance,
>>>> Christian.
>>>>
>>>> ________________________________________
>>>> Von: Tvrtko Ursulin <tursulin@igalia.com>
>>>> Gesendet: Montag, 30. Dezember 2024 17:52
>>>> An: dri-devel@lists.freedesktop.org
>>>> Cc: kernel-dev@igalia.com; Tvrtko Ursulin; Koenig, Christian;
>>>> Danilo Krummrich; Matthew Brost; Philipp Stanner
>>>> Betreff: [RFC 00/14] Deadline scheduler and other ideas
>>>>
>>>> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>>>>
>>>> <tldr>
>>>> Replacing FIFO with a flavour of deadline driven scheduling and
>>>> removing round-
>>>> robin. Connecting the scheduler with dma-fence deadlines. First
>>>> draft and
>>>> testing by different drivers and feedback would be nice. I was only
>>>> able to test
>>>> it with amdgpu. Other drivers may not even compile.
>>>> </tldr>
>>>>
>>>> If I remember correctly Christian mentioned recently (give or take)
>>>> that maybe
>>>> round-robin could be removed. That got me thinking how and what
>>>> could be
>>>> improved and simplified. So I played a bit in the scheduler code
>>>> and came up
>>>> with something which appears to not crash at least. Whether or not
>>>> there are
>>>> significant advantages apart from maybe code consolidation and
>>>> reduction is the
>>>> main thing to be determined.
>>>>
>>>> One big question is whether round-robin can really be removed. Does
>>>> anyone use
>>>> it, rely on it, or what are even use cases where it is much better
>>>> than FIFO.
>>>>
>>>> See "drm/sched: Add deadline policy" commit message for a short
>>>> description on
>>>> what flavour of deadline scheduling it is. But in essence it should
>>>> a more fair
>>>> FIFO where higher priority can not forever starve lower priorities.
>>>>
>>>> "drm/sched: Connect with dma-fence deadlines" wires up dma-fence
>>>> deadlines to
>>>> the scheduler because it is easy and makes logical sense with this.
>>>> And I
>>>> noticed userspace already uses it so why not wire it up fully.
>>>>
>>>> Otherwise the series is a bit of progression from consolidating RR
>>>> into FIFO
>>>> code paths and going from there to deadline and then to a change in
>>>> how
>>>> dependencies are handled. And code simplification to 1:1 run queue
>>>> to scheduler
>>>> relationship, because deadline does not need per priority run
>>>> queues.
>>>>
>>>> There is quite a bit of code to go throught here so I think it
>>>> could be even
>>>> better if other drivers could give it a spin as is and see if some
>>>> improvements
>>>> can be detected. Or at least no regressions.
>>>>
>>>> Cc: Christian König <christian.koenig@amd.com>
>>>> Cc: Danilo Krummrich <dakr@redhat.com>
>>>> Cc: Matthew Brost <matthew.brost@intel.com>
>>>> Cc: Philipp Stanner <pstanner@redhat.com>
>>>>
>>>> Tvrtko Ursulin (14):
>>>> drm/sched: Delete unused update_job_credits
>>>> drm/sched: Remove idle entity from tree
>>>> drm/sched: Implement RR via FIFO
>>>> drm/sched: Consolidate entity run queue management
>>>> drm/sched: Move run queue related code into a separate file
>>>> drm/sched: Ignore own fence earlier
>>>> drm/sched: Resolve same scheduler dependencies earlier
>>>> drm/sched: Add deadline policy
>>>> drm/sched: Remove FIFO and RR and simplify to a single run queue
>>>> drm/sched: Queue all free credits in one worker invocation
>>>> drm/sched: Connect with dma-fence deadlines
>>>> drm/sched: Embed run queue singleton into the scheduler
>>>> dma-fence: Add helper for custom fence context when merging
>>>> fences
>>>> drm/sched: Resolve all job dependencies in one go
>>>>
>>>> drivers/dma-buf/dma-fence-unwrap.c | 8 +-
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +-
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 27 +-
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 5 +-
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 8 +-
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 8 +-
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 8 +-
>>>> drivers/gpu/drm/scheduler/Makefile | 2 +-
>>>> drivers/gpu/drm/scheduler/sched_entity.c | 316 ++++++-----
>>>> drivers/gpu/drm/scheduler/sched_fence.c | 5 +-
>>>> drivers/gpu/drm/scheduler/sched_main.c | 587 +++++-----------
>>>> ----
>>>> drivers/gpu/drm/scheduler/sched_rq.c | 199 +++++++
>>>> include/drm/gpu_scheduler.h | 74 ++-
>>>> include/linux/dma-fence-unwrap.h | 31 +-
>>>> 14 files changed, 606 insertions(+), 678 deletions(-)
>>>> create mode 100644 drivers/gpu/drm/scheduler/sched_rq.c
>>>>
>>>> --
>>>> 2.47.1
>>>>
>>>
>>
>
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [RFC 00/14] Deadline scheduler and other ideas
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
` (15 preceding siblings ...)
2025-01-03 15:16 ` AW: " Koenig, Christian
@ 2025-01-08 8:31 ` Danilo Krummrich
2025-01-08 15:13 ` Tvrtko Ursulin
2025-01-17 12:12 ` Philipp Stanner
17 siblings, 1 reply; 61+ messages in thread
From: Danilo Krummrich @ 2025-01-08 8:31 UTC (permalink / raw)
To: Tvrtko Ursulin
Cc: dri-devel, kernel-dev, Tvrtko Ursulin, Christian König,
Matthew Brost, Philipp Stanner
On Mon, Dec 30, 2024 at 04:52:45PM +0000, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
"Deadline scheduler and other ideas"
There's a few patches that could be sent outside the scope of this series, e.g.
the first one.
I think it would make sense to do so.
>
> <tldr>
> Replacing FIFO with a flavour of deadline driven scheduling and removing round-
> robin. Connecting the scheduler with dma-fence deadlines. First draft and
> testing by different drivers and feedback would be nice. I was only able to test
> it with amdgpu. Other drivers may not even compile.
What are the results from your tests with amdgpu? Do you have some measurements?
> </tldr>
>
> If I remember correctly Christian mentioned recently (give or take) that maybe
> round-robin could be removed. That got me thinking how and what could be
> improved and simplified. So I played a bit in the scheduler code and came up
> with something which appears to not crash at least. Whether or not there are
> significant advantages apart from maybe code consolidation and reduction is the
> main thing to be determined.
>
> One big question is whether round-robin can really be removed. Does anyone use
> it, rely on it, or what are even use cases where it is much better than FIFO.
>
> See "drm/sched: Add deadline policy" commit message for a short description on
> what flavour of deadline scheduling it is. But in essence it should a more fair
> FIFO where higher priority can not forever starve lower priorities.
>
> "drm/sched: Connect with dma-fence deadlines" wires up dma-fence deadlines to
> the scheduler because it is easy and makes logical sense with this. And I
> noticed userspace already uses it so why not wire it up fully.
>
> Otherwise the series is a bit of progression from consolidating RR into FIFO
> code paths and going from there to deadline and then to a change in how
> dependencies are handled. And code simplification to 1:1 run queue to scheduler
> relationship, because deadline does not need per priority run queues.
>
> There is quite a bit of code to go throught here so I think it could be even
> better if other drivers could give it a spin as is and see if some improvements
> can be detected. Or at least no regressions.
Are there improvements with amdgpu?
>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: Danilo Krummrich <dakr@redhat.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Philipp Stanner <pstanner@redhat.com>
>
> Tvrtko Ursulin (14):
> drm/sched: Delete unused update_job_credits
> drm/sched: Remove idle entity from tree
> drm/sched: Implement RR via FIFO
> drm/sched: Consolidate entity run queue management
> drm/sched: Move run queue related code into a separate file
> drm/sched: Ignore own fence earlier
> drm/sched: Resolve same scheduler dependencies earlier
> drm/sched: Add deadline policy
> drm/sched: Remove FIFO and RR and simplify to a single run queue
> drm/sched: Queue all free credits in one worker invocation
> drm/sched: Connect with dma-fence deadlines
> drm/sched: Embed run queue singleton into the scheduler
> dma-fence: Add helper for custom fence context when merging fences
> drm/sched: Resolve all job dependencies in one go
>
> drivers/dma-buf/dma-fence-unwrap.c | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 27 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 5 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 8 +-
> drivers/gpu/drm/scheduler/Makefile | 2 +-
> drivers/gpu/drm/scheduler/sched_entity.c | 316 ++++++-----
> drivers/gpu/drm/scheduler/sched_fence.c | 5 +-
> drivers/gpu/drm/scheduler/sched_main.c | 587 +++++---------------
> drivers/gpu/drm/scheduler/sched_rq.c | 199 +++++++
> include/drm/gpu_scheduler.h | 74 ++-
> include/linux/dma-fence-unwrap.h | 31 +-
> 14 files changed, 606 insertions(+), 678 deletions(-)
> create mode 100644 drivers/gpu/drm/scheduler/sched_rq.c
>
> --
> 2.47.1
>
^ permalink raw reply [flat|nested] 61+ messages in thread* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-08 8:31 ` Danilo Krummrich
@ 2025-01-08 15:13 ` Tvrtko Ursulin
2025-01-08 16:57 ` Danilo Krummrich
0 siblings, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-08 15:13 UTC (permalink / raw)
To: Danilo Krummrich, Tvrtko Ursulin
Cc: dri-devel, kernel-dev, Christian König, Matthew Brost,
Philipp Stanner
On 08/01/2025 08:31, Danilo Krummrich wrote:
> On Mon, Dec 30, 2024 at 04:52:45PM +0000, Tvrtko Ursulin wrote:
>> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>
> "Deadline scheduler and other ideas"
>
> There's a few patches that could be sent outside the scope of this series, e.g.
> the first one.
>
> I think it would make sense to do so.
For now I'll keep them at the head of this RFC and as they get acked or
r-b-ed I can easily send them standalone or re-ordered. Until then
having the series separate would make the RFC not standalone.
>> <tldr>
>> Replacing FIFO with a flavour of deadline driven scheduling and removing round-
>> robin. Connecting the scheduler with dma-fence deadlines. First draft and
>> testing by different drivers and feedback would be nice. I was only able to test
>> it with amdgpu. Other drivers may not even compile.
>
> What are the results from your tests with amdgpu? Do you have some measurements?
We already covered this in the thread with Philipp to a degree. Tl;dr;
the main idea is whether we simplify the code and at least not regress.
I don't expect improvements on the amdgpu side with the workloads like
games and benchmarks. I did not measure anything significant apart that
priorities seem to work with the run queues removed.
Where something could show is if someone is aware of a workload where
normal prio starves low. Since one part of the idea is that with the
"deadline" scheme those should work a little bit more balanced.
Also again, feedback (including testing feedback from other drivers)
would be great, and ideas of which workloads to test.
Btw I will send a respin in a day or so which will clean up some things
and adds some more tiny bits.
Regards,
Tvrtko
>> </tldr>
>>
>> If I remember correctly Christian mentioned recently (give or take) that maybe
>> round-robin could be removed. That got me thinking how and what could be
>> improved and simplified. So I played a bit in the scheduler code and came up
>> with something which appears to not crash at least. Whether or not there are
>> significant advantages apart from maybe code consolidation and reduction is the
>> main thing to be determined.
>>
>> One big question is whether round-robin can really be removed. Does anyone use
>> it, rely on it, or what are even use cases where it is much better than FIFO.
>>
>> See "drm/sched: Add deadline policy" commit message for a short description on
>> what flavour of deadline scheduling it is. But in essence it should a more fair
>> FIFO where higher priority can not forever starve lower priorities.
>>
>> "drm/sched: Connect with dma-fence deadlines" wires up dma-fence deadlines to
>> the scheduler because it is easy and makes logical sense with this. And I
>> noticed userspace already uses it so why not wire it up fully.
>>
>> Otherwise the series is a bit of progression from consolidating RR into FIFO
>> code paths and going from there to deadline and then to a change in how
>> dependencies are handled. And code simplification to 1:1 run queue to scheduler
>> relationship, because deadline does not need per priority run queues.
>>
>> There is quite a bit of code to go throught here so I think it could be even
>> better if other drivers could give it a spin as is and see if some improvements
>> can be detected. Or at least no regressions.
>
> Are there improvements with amdgpu?
>
>>
>> Cc: Christian König <christian.koenig@amd.com>
>> Cc: Danilo Krummrich <dakr@redhat.com>
>> Cc: Matthew Brost <matthew.brost@intel.com>
>> Cc: Philipp Stanner <pstanner@redhat.com>
>>
>> Tvrtko Ursulin (14):
>> drm/sched: Delete unused update_job_credits
>> drm/sched: Remove idle entity from tree
>> drm/sched: Implement RR via FIFO
>> drm/sched: Consolidate entity run queue management
>> drm/sched: Move run queue related code into a separate file
>> drm/sched: Ignore own fence earlier
>> drm/sched: Resolve same scheduler dependencies earlier
>> drm/sched: Add deadline policy
>> drm/sched: Remove FIFO and RR and simplify to a single run queue
>> drm/sched: Queue all free credits in one worker invocation
>> drm/sched: Connect with dma-fence deadlines
>> drm/sched: Embed run queue singleton into the scheduler
>> dma-fence: Add helper for custom fence context when merging fences
>> drm/sched: Resolve all job dependencies in one go
>>
>> drivers/dma-buf/dma-fence-unwrap.c | 8 +-
>> drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +-
>> drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 27 +-
>> drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 5 +-
>> drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 8 +-
>> drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 8 +-
>> drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 8 +-
>> drivers/gpu/drm/scheduler/Makefile | 2 +-
>> drivers/gpu/drm/scheduler/sched_entity.c | 316 ++++++-----
>> drivers/gpu/drm/scheduler/sched_fence.c | 5 +-
>> drivers/gpu/drm/scheduler/sched_main.c | 587 +++++---------------
>> drivers/gpu/drm/scheduler/sched_rq.c | 199 +++++++
>> include/drm/gpu_scheduler.h | 74 ++-
>> include/linux/dma-fence-unwrap.h | 31 +-
>> 14 files changed, 606 insertions(+), 678 deletions(-)
>> create mode 100644 drivers/gpu/drm/scheduler/sched_rq.c
>>
>> --
>> 2.47.1
>>
>
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-08 15:13 ` Tvrtko Ursulin
@ 2025-01-08 16:57 ` Danilo Krummrich
2025-01-08 18:55 ` Tvrtko Ursulin
2025-01-09 19:50 ` Matthew Brost
0 siblings, 2 replies; 61+ messages in thread
From: Danilo Krummrich @ 2025-01-08 16:57 UTC (permalink / raw)
To: Tvrtko Ursulin
Cc: Tvrtko Ursulin, dri-devel, kernel-dev, Christian König,
Matthew Brost, Philipp Stanner
On Wed, Jan 08, 2025 at 03:13:39PM +0000, Tvrtko Ursulin wrote:
>
> On 08/01/2025 08:31, Danilo Krummrich wrote:
> > On Mon, Dec 30, 2024 at 04:52:45PM +0000, Tvrtko Ursulin wrote:
> > > From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> >
> > "Deadline scheduler and other ideas"
> >
> > There's a few patches that could be sent outside the scope of this series, e.g.
> > the first one.
> >
> > I think it would make sense to do so.
>
> For now I'll keep them at the head of this RFC and as they get acked or
> r-b-ed I can easily send them standalone or re-ordered. Until then having
> the series separate would make the RFC not standalone.
>
> > > <tldr>
> > > Replacing FIFO with a flavour of deadline driven scheduling and removing round-
> > > robin. Connecting the scheduler with dma-fence deadlines. First draft and
> > > testing by different drivers and feedback would be nice. I was only able to test
> > > it with amdgpu. Other drivers may not even compile.
> >
> > What are the results from your tests with amdgpu? Do you have some measurements?
>
> We already covered this in the thread with Philipp to a degree. Tl;dr; the
> main idea is whether we simplify the code and at least not regress.
>
> I don't expect improvements on the amdgpu side with the workloads like games
> and benchmarks. I did not measure anything significant apart that priorities
> seem to work with the run queues removed.
I appreaciate the effort, and generally I like the idea, but I also must admit
that this isn't the most convincing motiviation for such an integral change
(especially the "at least not regress" part).
I'd still like to encourage you to send the small cleanups separately, get them
in soon and leave the deadline scheduler as a separate RFC.
Meanwhile, Philipp is working on getting documentation straight and digging into
all the FIXMEs of the scheduler getting to a cleaner baseline. And with your
cleanups you're already helping with that.
For now, I'd prefer to leave the deadline scheduler stuff for when things are a
bit more settled and / or drivers declare the need.
>
> Where something could show is if someone is aware of a workload where normal
> prio starves low. Since one part of the idea is that with the "deadline"
> scheme those should work a little bit more balanced.
>
> Also again, feedback (including testing feedback from other drivers) would
> be great, and ideas of which workloads to test.
Unfortunately, there's not much I can tell from the Nouveau side of things,
since we're using the firmware scheduler scheme (one entity per scheduler) and
hence the scheduling strategy isn't that relevant.
>
> Btw I will send a respin in a day or so which will clean up some things and
> adds some more tiny bits.
>
> Regards,
>
> Tvrtko
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-08 16:57 ` Danilo Krummrich
@ 2025-01-08 18:55 ` Tvrtko Ursulin
2025-01-09 19:59 ` Matthew Brost
2025-01-09 19:50 ` Matthew Brost
1 sibling, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-08 18:55 UTC (permalink / raw)
To: Danilo Krummrich
Cc: Tvrtko Ursulin, dri-devel, kernel-dev, Christian König,
Matthew Brost, Philipp Stanner
On 08/01/2025 16:57, Danilo Krummrich wrote:
> On Wed, Jan 08, 2025 at 03:13:39PM +0000, Tvrtko Ursulin wrote:
>>
>> On 08/01/2025 08:31, Danilo Krummrich wrote:
>>> On Mon, Dec 30, 2024 at 04:52:45PM +0000, Tvrtko Ursulin wrote:
>>>> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>>>
>>> "Deadline scheduler and other ideas"
>>>
>>> There's a few patches that could be sent outside the scope of this series, e.g.
>>> the first one.
>>>
>>> I think it would make sense to do so.
>>
>> For now I'll keep them at the head of this RFC and as they get acked or
>> r-b-ed I can easily send them standalone or re-ordered. Until then having
>> the series separate would make the RFC not standalone.
>>
>>>> <tldr>
>>>> Replacing FIFO with a flavour of deadline driven scheduling and removing round-
>>>> robin. Connecting the scheduler with dma-fence deadlines. First draft and
>>>> testing by different drivers and feedback would be nice. I was only able to test
>>>> it with amdgpu. Other drivers may not even compile.
>>>
>>> What are the results from your tests with amdgpu? Do you have some measurements?
>>
>> We already covered this in the thread with Philipp to a degree. Tl;dr; the
>> main idea is whether we simplify the code and at least not regress.
>>
>> I don't expect improvements on the amdgpu side with the workloads like games
>> and benchmarks. I did not measure anything significant apart that priorities
>> seem to work with the run queues removed.
>
> I appreaciate the effort, and generally I like the idea, but I also must admit
> that this isn't the most convincing motiviation for such an integral change
> (especially the "at least not regress" part).
It is challenging yes. But for completeness the full context of what you
quoted (if you also read my replies to Philipp) was *if* we can shrink
the code base, add some fairness to FIFO, *and* not regress then those
three added together would IMHO not be bad. We shouldn't be scared to
touch it because only touching it you can truly understand the gotchas
which any amount of kerneldoc will not help with.
> I'd still like to encourage you to send the small cleanups separately, get them
> in soon and leave the deadline scheduler as a separate RFC.
>
> Meanwhile, Philipp is working on getting documentation straight and digging into
> all the FIXMEs of the scheduler getting to a cleaner baseline. And with your
> cleanups you're already helping with that.
>
> For now, I'd prefer to leave the deadline scheduler stuff for when things are a
> bit more settled and / or drivers declare the need.
I just sent v2:
About motivation for the documenting efforts:
13 files changed, 424 insertions(+), 576 deletions(-)
Fewer lines to document. ;)
On a serious note, I ordered the series (mostly*) so you can read it in
order and for patches/ideas you like please say and I can extract and
send separately if you want. I am reluctant to extract things
beforehand, before knowing which ones people will like and so far there
is only one with acks.
*)
Mostly because perhaps "drm/sched: Queue all free credits in one worker
invocation" could be interesting to move before the most.
>> Where something could show is if someone is aware of a workload where normal
>> prio starves low. Since one part of the idea is that with the "deadline"
>> scheme those should work a little bit more balanced.
>>
>> Also again, feedback (including testing feedback from other drivers) would
>> be great, and ideas of which workloads to test.
>
> Unfortunately, there's not much I can tell from the Nouveau side of things,
> since we're using the firmware scheduler scheme (one entity per scheduler) and
> hence the scheduling strategy isn't that relevant.
Yeah. Hopefully someone with more appropriate hardware gets intrigued to
try it out, or to suggest interesting workloads.
Until then I happy to keep it alive in the background and as said you
can pick and choose the parts you like.
Regards,
Tvrtko
>
>>
>> Btw I will send a respin in a day or so which will clean up some things and
>> adds some more tiny bits.
>>
>> Regards,
>>
>> Tvrtko
>
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-08 18:55 ` Tvrtko Ursulin
@ 2025-01-09 19:59 ` Matthew Brost
2025-01-10 9:16 ` Tvrtko Ursulin
0 siblings, 1 reply; 61+ messages in thread
From: Matthew Brost @ 2025-01-09 19:59 UTC (permalink / raw)
To: Tvrtko Ursulin
Cc: Danilo Krummrich, Tvrtko Ursulin, dri-devel, kernel-dev,
Christian König, Philipp Stanner
On Wed, Jan 08, 2025 at 06:55:16PM +0000, Tvrtko Ursulin wrote:
>
> On 08/01/2025 16:57, Danilo Krummrich wrote:
> > On Wed, Jan 08, 2025 at 03:13:39PM +0000, Tvrtko Ursulin wrote:
> > >
> > > On 08/01/2025 08:31, Danilo Krummrich wrote:
> > > > On Mon, Dec 30, 2024 at 04:52:45PM +0000, Tvrtko Ursulin wrote:
> > > > > From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> > > >
> > > > "Deadline scheduler and other ideas"
> > > >
> > > > There's a few patches that could be sent outside the scope of this series, e.g.
> > > > the first one.
> > > >
> > > > I think it would make sense to do so.
> > >
> > > For now I'll keep them at the head of this RFC and as they get acked or
> > > r-b-ed I can easily send them standalone or re-ordered. Until then having
> > > the series separate would make the RFC not standalone.
> > >
> > > > > <tldr>
> > > > > Replacing FIFO with a flavour of deadline driven scheduling and removing round-
> > > > > robin. Connecting the scheduler with dma-fence deadlines. First draft and
> > > > > testing by different drivers and feedback would be nice. I was only able to test
> > > > > it with amdgpu. Other drivers may not even compile.
> > > >
> > > > What are the results from your tests with amdgpu? Do you have some measurements?
> > >
> > > We already covered this in the thread with Philipp to a degree. Tl;dr; the
> > > main idea is whether we simplify the code and at least not regress.
> > >
> > > I don't expect improvements on the amdgpu side with the workloads like games
> > > and benchmarks. I did not measure anything significant apart that priorities
> > > seem to work with the run queues removed.
> >
> > I appreaciate the effort, and generally I like the idea, but I also must admit
> > that this isn't the most convincing motiviation for such an integral change
> > (especially the "at least not regress" part).
>
> It is challenging yes. But for completeness the full context of what you
> quoted (if you also read my replies to Philipp) was *if* we can shrink the
> code base, add some fairness to FIFO, *and* not regress then those three
> added together would IMHO not be bad. We shouldn't be scared to touch it
> because only touching it you can truly understand the gotchas which any
> amount of kerneldoc will not help with.
> > I'd still like to encourage you to send the small cleanups separately, get them
> > in soon and leave the deadline scheduler as a separate RFC.
> >
> > Meanwhile, Philipp is working on getting documentation straight and digging into
> > all the FIXMEs of the scheduler getting to a cleaner baseline. And with your
> > cleanups you're already helping with that.
> >
> > For now, I'd prefer to leave the deadline scheduler stuff for when things are a
> > bit more settled and / or drivers declare the need.
>
> I just sent v2:
>
> About motivation for the documenting efforts:
>
> 13 files changed, 424 insertions(+), 576 deletions(-)
>
> Fewer lines to document. ;)
>
> On a serious note, I ordered the series (mostly*) so you can read it in
> order and for patches/ideas you like please say and I can extract and send
> separately if you want. I am reluctant to extract things beforehand, before
> knowing which ones people will like and so far there is only one with acks.
>
> *)
> Mostly because perhaps "drm/sched: Queue all free credits in one worker
> invocation" could be interesting to move before the most.
>
I looked into this. When I originally changed the scheduler from a
kthread to a worker, I designed it the way your patch implements it:
looping in the worker until credits run out or no jobs are available.
If I recall correctly, the feedback from Christian (or Luben?) was to
rely on the work queue's requeuing mechanism to submit more than one
job. From a latency perspective, there might be a small benefit, but
it's more likely that if you queue two jobs back-to-back, even when
relying on the work queue's rescheduling, the first job will still be
running on the hardware, nullifying any potential latency improvement.
From a fairness perspective, multiplexing across multiple work queues
one job at a time makes a bit more sense, in my opinion.
Matt
> > > Where something could show is if someone is aware of a workload where normal
> > > prio starves low. Since one part of the idea is that with the "deadline"
> > > scheme those should work a little bit more balanced.
> > >
> > > Also again, feedback (including testing feedback from other drivers) would
> > > be great, and ideas of which workloads to test.
> >
> > Unfortunately, there's not much I can tell from the Nouveau side of things,
> > since we're using the firmware scheduler scheme (one entity per scheduler) and
> > hence the scheduling strategy isn't that relevant.
>
> Yeah. Hopefully someone with more appropriate hardware gets intrigued to try
> it out, or to suggest interesting workloads.
>
> Until then I happy to keep it alive in the background and as said you can
> pick and choose the parts you like.
>
> Regards,
>
> Tvrtko
>
> >
> > >
> > > Btw I will send a respin in a day or so which will clean up some things and
> > > adds some more tiny bits.
> > >
> > > Regards,
> > >
> > > Tvrtko
> >
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-09 19:59 ` Matthew Brost
@ 2025-01-10 9:16 ` Tvrtko Ursulin
2025-01-10 17:28 ` Matthew Brost
0 siblings, 1 reply; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-10 9:16 UTC (permalink / raw)
To: Matthew Brost
Cc: Danilo Krummrich, Tvrtko Ursulin, dri-devel, kernel-dev,
Christian König, Philipp Stanner
On 09/01/2025 19:59, Matthew Brost wrote:
> On Wed, Jan 08, 2025 at 06:55:16PM +0000, Tvrtko Ursulin wrote:
>>
>> On 08/01/2025 16:57, Danilo Krummrich wrote:
>>> On Wed, Jan 08, 2025 at 03:13:39PM +0000, Tvrtko Ursulin wrote:
>>>>
>>>> On 08/01/2025 08:31, Danilo Krummrich wrote:
>>>>> On Mon, Dec 30, 2024 at 04:52:45PM +0000, Tvrtko Ursulin wrote:
>>>>>> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>>>>>
>>>>> "Deadline scheduler and other ideas"
>>>>>
>>>>> There's a few patches that could be sent outside the scope of this series, e.g.
>>>>> the first one.
>>>>>
>>>>> I think it would make sense to do so.
>>>>
>>>> For now I'll keep them at the head of this RFC and as they get acked or
>>>> r-b-ed I can easily send them standalone or re-ordered. Until then having
>>>> the series separate would make the RFC not standalone.
>>>>
>>>>>> <tldr>
>>>>>> Replacing FIFO with a flavour of deadline driven scheduling and removing round-
>>>>>> robin. Connecting the scheduler with dma-fence deadlines. First draft and
>>>>>> testing by different drivers and feedback would be nice. I was only able to test
>>>>>> it with amdgpu. Other drivers may not even compile.
>>>>>
>>>>> What are the results from your tests with amdgpu? Do you have some measurements?
>>>>
>>>> We already covered this in the thread with Philipp to a degree. Tl;dr; the
>>>> main idea is whether we simplify the code and at least not regress.
>>>>
>>>> I don't expect improvements on the amdgpu side with the workloads like games
>>>> and benchmarks. I did not measure anything significant apart that priorities
>>>> seem to work with the run queues removed.
>>>
>>> I appreaciate the effort, and generally I like the idea, but I also must admit
>>> that this isn't the most convincing motiviation for such an integral change
>>> (especially the "at least not regress" part).
>>
>> It is challenging yes. But for completeness the full context of what you
>> quoted (if you also read my replies to Philipp) was *if* we can shrink the
>> code base, add some fairness to FIFO, *and* not regress then those three
>> added together would IMHO not be bad. We shouldn't be scared to touch it
>> because only touching it you can truly understand the gotchas which any
>> amount of kerneldoc will not help with.
>>> I'd still like to encourage you to send the small cleanups separately, get them
>>> in soon and leave the deadline scheduler as a separate RFC.
>>>
>>> Meanwhile, Philipp is working on getting documentation straight and digging into
>>> all the FIXMEs of the scheduler getting to a cleaner baseline. And with your
>>> cleanups you're already helping with that.
>>>
>>> For now, I'd prefer to leave the deadline scheduler stuff for when things are a
>>> bit more settled and / or drivers declare the need.
>>
>> I just sent v2:
>>
>> About motivation for the documenting efforts:
>>
>> 13 files changed, 424 insertions(+), 576 deletions(-)
>>
>> Fewer lines to document. ;)
>>
>> On a serious note, I ordered the series (mostly*) so you can read it in
>> order and for patches/ideas you like please say and I can extract and send
>> separately if you want. I am reluctant to extract things beforehand, before
>> knowing which ones people will like and so far there is only one with acks.
>>
>> *)
>> Mostly because perhaps "drm/sched: Queue all free credits in one worker
>> invocation" could be interesting to move before the most.
>>
>
> I looked into this. When I originally changed the scheduler from a
> kthread to a worker, I designed it the way your patch implements it:
> looping in the worker until credits run out or no jobs are available.
>
> If I recall correctly, the feedback from Christian (or Luben?) was to
> rely on the work queue's requeuing mechanism to submit more than one
> job. From a latency perspective, there might be a small benefit, but
> it's more likely that if you queue two jobs back-to-back, even when
> relying on the work queue's rescheduling, the first job will still be
> running on the hardware, nullifying any potential latency improvement.
>
> From a fairness perspective, multiplexing across multiple work queues
> one job at a time makes a bit more sense, in my opinion.
You mean multiplexing across multiple _entities_? Because work queue is
only one. That it unchanged with my patch. Ie. it is not changing to
pick jobs from a single entity but still picks a job at a time from the
top entity. And top entity can change as jobs are popped. What remains
is the question of why burn CPU cycles and do it in a roundabout way if
it is very easy to do it directly and at the same time avoid that
unconditional final wakeup when queues are empty.
Regards,
Tvrtko
>>>> Where something could show is if someone is aware of a workload where normal
>>>> prio starves low. Since one part of the idea is that with the "deadline"
>>>> scheme those should work a little bit more balanced.
>>>>
>>>> Also again, feedback (including testing feedback from other drivers) would
>>>> be great, and ideas of which workloads to test.
>>>
>>> Unfortunately, there's not much I can tell from the Nouveau side of things,
>>> since we're using the firmware scheduler scheme (one entity per scheduler) and
>>> hence the scheduling strategy isn't that relevant.
>>
>> Yeah. Hopefully someone with more appropriate hardware gets intrigued to try
>> it out, or to suggest interesting workloads.
>>
>> Until then I happy to keep it alive in the background and as said you can
>> pick and choose the parts you like.
>>
>> Regards,
>>
>> Tvrtko
>>
>>>
>>>>
>>>> Btw I will send a respin in a day or so which will clean up some things and
>>>> adds some more tiny bits.
>>>>
>>>> Regards,
>>>>
>>>> Tvrtko
>>>
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-10 9:16 ` Tvrtko Ursulin
@ 2025-01-10 17:28 ` Matthew Brost
2025-01-13 12:59 ` Tvrtko Ursulin
0 siblings, 1 reply; 61+ messages in thread
From: Matthew Brost @ 2025-01-10 17:28 UTC (permalink / raw)
To: Tvrtko Ursulin
Cc: Danilo Krummrich, Tvrtko Ursulin, dri-devel, kernel-dev,
Christian König, Philipp Stanner
On Fri, Jan 10, 2025 at 09:16:44AM +0000, Tvrtko Ursulin wrote:
>
> On 09/01/2025 19:59, Matthew Brost wrote:
> > On Wed, Jan 08, 2025 at 06:55:16PM +0000, Tvrtko Ursulin wrote:
> > >
> > > On 08/01/2025 16:57, Danilo Krummrich wrote:
> > > > On Wed, Jan 08, 2025 at 03:13:39PM +0000, Tvrtko Ursulin wrote:
> > > > >
> > > > > On 08/01/2025 08:31, Danilo Krummrich wrote:
> > > > > > On Mon, Dec 30, 2024 at 04:52:45PM +0000, Tvrtko Ursulin wrote:
> > > > > > > From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> > > > > >
> > > > > > "Deadline scheduler and other ideas"
> > > > > >
> > > > > > There's a few patches that could be sent outside the scope of this series, e.g.
> > > > > > the first one.
> > > > > >
> > > > > > I think it would make sense to do so.
> > > > >
> > > > > For now I'll keep them at the head of this RFC and as they get acked or
> > > > > r-b-ed I can easily send them standalone or re-ordered. Until then having
> > > > > the series separate would make the RFC not standalone.
> > > > >
> > > > > > > <tldr>
> > > > > > > Replacing FIFO with a flavour of deadline driven scheduling and removing round-
> > > > > > > robin. Connecting the scheduler with dma-fence deadlines. First draft and
> > > > > > > testing by different drivers and feedback would be nice. I was only able to test
> > > > > > > it with amdgpu. Other drivers may not even compile.
> > > > > >
> > > > > > What are the results from your tests with amdgpu? Do you have some measurements?
> > > > >
> > > > > We already covered this in the thread with Philipp to a degree. Tl;dr; the
> > > > > main idea is whether we simplify the code and at least not regress.
> > > > >
> > > > > I don't expect improvements on the amdgpu side with the workloads like games
> > > > > and benchmarks. I did not measure anything significant apart that priorities
> > > > > seem to work with the run queues removed.
> > > >
> > > > I appreaciate the effort, and generally I like the idea, but I also must admit
> > > > that this isn't the most convincing motiviation for such an integral change
> > > > (especially the "at least not regress" part).
> > >
> > > It is challenging yes. But for completeness the full context of what you
> > > quoted (if you also read my replies to Philipp) was *if* we can shrink the
> > > code base, add some fairness to FIFO, *and* not regress then those three
> > > added together would IMHO not be bad. We shouldn't be scared to touch it
> > > because only touching it you can truly understand the gotchas which any
> > > amount of kerneldoc will not help with.
> > > > I'd still like to encourage you to send the small cleanups separately, get them
> > > > in soon and leave the deadline scheduler as a separate RFC.
> > > >
> > > > Meanwhile, Philipp is working on getting documentation straight and digging into
> > > > all the FIXMEs of the scheduler getting to a cleaner baseline. And with your
> > > > cleanups you're already helping with that.
> > > >
> > > > For now, I'd prefer to leave the deadline scheduler stuff for when things are a
> > > > bit more settled and / or drivers declare the need.
> > >
> > > I just sent v2:
> > >
> > > About motivation for the documenting efforts:
> > >
> > > 13 files changed, 424 insertions(+), 576 deletions(-)
> > >
> > > Fewer lines to document. ;)
> > >
> > > On a serious note, I ordered the series (mostly*) so you can read it in
> > > order and for patches/ideas you like please say and I can extract and send
> > > separately if you want. I am reluctant to extract things beforehand, before
> > > knowing which ones people will like and so far there is only one with acks.
> > >
> > > *)
> > > Mostly because perhaps "drm/sched: Queue all free credits in one worker
> > > invocation" could be interesting to move before the most.
> > >
> >
> > I looked into this. When I originally changed the scheduler from a
> > kthread to a worker, I designed it the way your patch implements it:
> > looping in the worker until credits run out or no jobs are available.
> >
> > If I recall correctly, the feedback from Christian (or Luben?) was to
> > rely on the work queue's requeuing mechanism to submit more than one
> > job. From a latency perspective, there might be a small benefit, but
> > it's more likely that if you queue two jobs back-to-back, even when
> > relying on the work queue's rescheduling, the first job will still be
> > running on the hardware, nullifying any potential latency improvement.
> >
> > From a fairness perspective, multiplexing across multiple work queues
> > one job at a time makes a bit more sense, in my opinion.
>
> You mean multiplexing across multiple _entities_? Because work queue is only
No, I mean if you have multiple schedulers (work queues) with jobs that
are to run dequeuing a job a time per scheduler would let the core work
queue scheduling give a level of fairness.
> one. That it unchanged with my patch. Ie. it is not changing to pick jobs
> from a single entity but still picks a job at a time from the top entity.
> And top entity can change as jobs are popped. What remains is the question
> of why burn CPU cycles and do it in a roundabout way if it is very easy to
> do it directly and at the same time avoid that unconditional final wakeup
> when queues are empty.
Like I said, I had this way initially but the feedback I recieved was to
dequeue 1 job at time and kick the work queue to reschedule itself.
Unless everyone opinion has changed, I don't think this is change we
should make.
Here are the some references...
[1] https://patchwork.freedesktop.org/patch/530652/?series=116055&rev=1
[2] https://patchwork.freedesktop.org/patch/575874/?series=129143&rev=1
[3] https://patchwork.freedesktop.org/patch/576334/?series=129286&rev=1
Matt
>
> Regards,
>
> Tvrtko
>
> > > > > Where something could show is if someone is aware of a workload where normal
> > > > > prio starves low. Since one part of the idea is that with the "deadline"
> > > > > scheme those should work a little bit more balanced.
> > > > >
> > > > > Also again, feedback (including testing feedback from other drivers) would
> > > > > be great, and ideas of which workloads to test.
> > > >
> > > > Unfortunately, there's not much I can tell from the Nouveau side of things,
> > > > since we're using the firmware scheduler scheme (one entity per scheduler) and
> > > > hence the scheduling strategy isn't that relevant.
> > >
> > > Yeah. Hopefully someone with more appropriate hardware gets intrigued to try
> > > it out, or to suggest interesting workloads.
> > >
> > > Until then I happy to keep it alive in the background and as said you can
> > > pick and choose the parts you like.
> > >
> > > Regards,
> > >
> > > Tvrtko
> > >
> > > >
> > > > >
> > > > > Btw I will send a respin in a day or so which will clean up some things and
> > > > > adds some more tiny bits.
> > > > >
> > > > > Regards,
> > > > >
> > > > > Tvrtko
> > > >
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-10 17:28 ` Matthew Brost
@ 2025-01-13 12:59 ` Tvrtko Ursulin
0 siblings, 0 replies; 61+ messages in thread
From: Tvrtko Ursulin @ 2025-01-13 12:59 UTC (permalink / raw)
To: Matthew Brost
Cc: Danilo Krummrich, Tvrtko Ursulin, dri-devel, kernel-dev,
Christian König, Philipp Stanner
On 10/01/2025 17:28, Matthew Brost wrote:
> On Fri, Jan 10, 2025 at 09:16:44AM +0000, Tvrtko Ursulin wrote:
>>
>> On 09/01/2025 19:59, Matthew Brost wrote:
>>> On Wed, Jan 08, 2025 at 06:55:16PM +0000, Tvrtko Ursulin wrote:
>>>>
>>>> On 08/01/2025 16:57, Danilo Krummrich wrote:
>>>>> On Wed, Jan 08, 2025 at 03:13:39PM +0000, Tvrtko Ursulin wrote:
>>>>>>
>>>>>> On 08/01/2025 08:31, Danilo Krummrich wrote:
>>>>>>> On Mon, Dec 30, 2024 at 04:52:45PM +0000, Tvrtko Ursulin wrote:
>>>>>>>> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>>>>>>>
>>>>>>> "Deadline scheduler and other ideas"
>>>>>>>
>>>>>>> There's a few patches that could be sent outside the scope of this series, e.g.
>>>>>>> the first one.
>>>>>>>
>>>>>>> I think it would make sense to do so.
>>>>>>
>>>>>> For now I'll keep them at the head of this RFC and as they get acked or
>>>>>> r-b-ed I can easily send them standalone or re-ordered. Until then having
>>>>>> the series separate would make the RFC not standalone.
>>>>>>
>>>>>>>> <tldr>
>>>>>>>> Replacing FIFO with a flavour of deadline driven scheduling and removing round-
>>>>>>>> robin. Connecting the scheduler with dma-fence deadlines. First draft and
>>>>>>>> testing by different drivers and feedback would be nice. I was only able to test
>>>>>>>> it with amdgpu. Other drivers may not even compile.
>>>>>>>
>>>>>>> What are the results from your tests with amdgpu? Do you have some measurements?
>>>>>>
>>>>>> We already covered this in the thread with Philipp to a degree. Tl;dr; the
>>>>>> main idea is whether we simplify the code and at least not regress.
>>>>>>
>>>>>> I don't expect improvements on the amdgpu side with the workloads like games
>>>>>> and benchmarks. I did not measure anything significant apart that priorities
>>>>>> seem to work with the run queues removed.
>>>>>
>>>>> I appreaciate the effort, and generally I like the idea, but I also must admit
>>>>> that this isn't the most convincing motiviation for such an integral change
>>>>> (especially the "at least not regress" part).
>>>>
>>>> It is challenging yes. But for completeness the full context of what you
>>>> quoted (if you also read my replies to Philipp) was *if* we can shrink the
>>>> code base, add some fairness to FIFO, *and* not regress then those three
>>>> added together would IMHO not be bad. We shouldn't be scared to touch it
>>>> because only touching it you can truly understand the gotchas which any
>>>> amount of kerneldoc will not help with.
>>>>> I'd still like to encourage you to send the small cleanups separately, get them
>>>>> in soon and leave the deadline scheduler as a separate RFC.
>>>>>
>>>>> Meanwhile, Philipp is working on getting documentation straight and digging into
>>>>> all the FIXMEs of the scheduler getting to a cleaner baseline. And with your
>>>>> cleanups you're already helping with that.
>>>>>
>>>>> For now, I'd prefer to leave the deadline scheduler stuff for when things are a
>>>>> bit more settled and / or drivers declare the need.
>>>>
>>>> I just sent v2:
>>>>
>>>> About motivation for the documenting efforts:
>>>>
>>>> 13 files changed, 424 insertions(+), 576 deletions(-)
>>>>
>>>> Fewer lines to document. ;)
>>>>
>>>> On a serious note, I ordered the series (mostly*) so you can read it in
>>>> order and for patches/ideas you like please say and I can extract and send
>>>> separately if you want. I am reluctant to extract things beforehand, before
>>>> knowing which ones people will like and so far there is only one with acks.
>>>>
>>>> *)
>>>> Mostly because perhaps "drm/sched: Queue all free credits in one worker
>>>> invocation" could be interesting to move before the most.
>>>>
>>>
>>> I looked into this. When I originally changed the scheduler from a
>>> kthread to a worker, I designed it the way your patch implements it:
>>> looping in the worker until credits run out or no jobs are available.
>>>
>>> If I recall correctly, the feedback from Christian (or Luben?) was to
>>> rely on the work queue's requeuing mechanism to submit more than one
>>> job. From a latency perspective, there might be a small benefit, but
>>> it's more likely that if you queue two jobs back-to-back, even when
>>> relying on the work queue's rescheduling, the first job will still be
>>> running on the hardware, nullifying any potential latency improvement.
>>>
>>> From a fairness perspective, multiplexing across multiple work queues
>>> one job at a time makes a bit more sense, in my opinion.
>>
>> You mean multiplexing across multiple _entities_? Because work queue is only
>
> No, I mean if you have multiple schedulers (work queues) with jobs that
> are to run dequeuing a job a time per scheduler would let the core work
> queue scheduling give a level of fairness.
That doesn't work in the current implementation because entity->rq (ie.
picked scheduler) cannot change when jobs are queued.
>> one. That it unchanged with my patch. Ie. it is not changing to pick jobs
>> from a single entity but still picks a job at a time from the top entity.
>> And top entity can change as jobs are popped. What remains is the question
>> of why burn CPU cycles and do it in a roundabout way if it is very easy to
>> do it directly and at the same time avoid that unconditional final wakeup
>> when queues are empty.
>
> Like I said, I had this way initially but the feedback I recieved was to
> dequeue 1 job at time and kick the work queue to reschedule itself.
> Unless everyone opinion has changed, I don't think this is change we
> should make.
>
> Here are the some references...
>
> [1] https://patchwork.freedesktop.org/patch/530652/?series=116055&rev=1
> [2] https://patchwork.freedesktop.org/patch/575874/?series=129143&rev=1
> [3] https://patchwork.freedesktop.org/patch/576334/?series=129286&rev=1
Thanks. Aside that the referenced discussion were also about fixing some
regressions, on the topic of the high level design I spotted two arguments.
One was about the supposed need to "interleave" one-at-a-time run work
and the same for free work. I don't see why would that be the case and
besides it is already not universally true when unordered workqueues are
used.
Second was to bail soone(-er) is scheduler is paused. That's a good
point and I added it to my local version.
In summary it feels this area should be clarified further.
Regards,
Tvrtko
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [RFC 00/14] Deadline scheduler and other ideas
2025-01-08 16:57 ` Danilo Krummrich
2025-01-08 18:55 ` Tvrtko Ursulin
@ 2025-01-09 19:50 ` Matthew Brost
1 sibling, 0 replies; 61+ messages in thread
From: Matthew Brost @ 2025-01-09 19:50 UTC (permalink / raw)
To: Danilo Krummrich
Cc: Tvrtko Ursulin, Tvrtko Ursulin, dri-devel, kernel-dev,
Christian König, Philipp Stanner
On Wed, Jan 08, 2025 at 05:57:25PM +0100, Danilo Krummrich wrote:
> On Wed, Jan 08, 2025 at 03:13:39PM +0000, Tvrtko Ursulin wrote:
Hi, all.
Just catching up on this post holidays. A few thoughts below.
> >
> > On 08/01/2025 08:31, Danilo Krummrich wrote:
> > > On Mon, Dec 30, 2024 at 04:52:45PM +0000, Tvrtko Ursulin wrote:
> > > > From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> > >
> > > "Deadline scheduler and other ideas"
> > >
> > > There's a few patches that could be sent outside the scope of this series, e.g.
> > > the first one.
> > >
> > > I think it would make sense to do so.
> >
> > For now I'll keep them at the head of this RFC and as they get acked or
> > r-b-ed I can easily send them standalone or re-ordered. Until then having
> > the series separate would make the RFC not standalone.
> >
> > > > <tldr>
> > > > Replacing FIFO with a flavour of deadline driven scheduling and removing round-
> > > > robin. Connecting the scheduler with dma-fence deadlines. First draft and
> > > > testing by different drivers and feedback would be nice. I was only able to test
> > > > it with amdgpu. Other drivers may not even compile.
> > >
> > > What are the results from your tests with amdgpu? Do you have some measurements?
> >
> > We already covered this in the thread with Philipp to a degree. Tl;dr; the
> > main idea is whether we simplify the code and at least not regress.
> >
> > I don't expect improvements on the amdgpu side with the workloads like games
> > and benchmarks. I did not measure anything significant apart that priorities
> > seem to work with the run queues removed.
>
> I appreaciate the effort, and generally I like the idea, but I also must admit
> that this isn't the most convincing motiviation for such an integral change
> (especially the "at least not regress" part).
>
> I'd still like to encourage you to send the small cleanups separately, get them
> in soon and leave the deadline scheduler as a separate RFC.
>
> Meanwhile, Philipp is working on getting documentation straight and digging into
> all the FIXMEs of the scheduler getting to a cleaner baseline. And with your
> cleanups you're already helping with that.
>
> For now, I'd prefer to leave the deadline scheduler stuff for when things are a
> bit more settled and / or drivers declare the need.
>
I have to agree with Danilo here. Unless there is a clear motivation for
deadline scheduler changes, I'm not sure it's worth a rewrite and the
potential headaches of things breaking.
> >
> > Where something could show is if someone is aware of a workload where normal
> > prio starves low. Since one part of the idea is that with the "deadline"
> > scheme those should work a little bit more balanced.
> >
> > Also again, feedback (including testing feedback from other drivers) would
> > be great, and ideas of which workloads to test.
>
> Unfortunately, there's not much I can tell from the Nouveau side of things,
> since we're using the firmware scheduler scheme (one entity per scheduler) and
> hence the scheduling strategy isn't that relevant.
>
I also agree here. From a Xe perspective, we don’t really have a stake
in this since we use a firmware scheduler scheme.
Matt
> >
> > Btw I will send a respin in a day or so which will clean up some things and
> > adds some more tiny bits.
> >
> > Regards,
> >
> > Tvrtko
>
^ permalink raw reply [flat|nested] 61+ messages in thread
* Re: [RFC 00/14] Deadline scheduler and other ideas
2024-12-30 16:52 [RFC 00/14] Deadline scheduler and other ideas Tvrtko Ursulin
` (16 preceding siblings ...)
2025-01-08 8:31 ` Danilo Krummrich
@ 2025-01-17 12:12 ` Philipp Stanner
17 siblings, 0 replies; 61+ messages in thread
From: Philipp Stanner @ 2025-01-17 12:12 UTC (permalink / raw)
To: Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost
On Mon, 2024-12-30 at 16:52 +0000, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
>
> <tldr>
> Replacing FIFO with a flavour of deadline driven scheduling and
> removing round-
> robin. Connecting the scheduler with dma-fence deadlines. First draft
> and
> testing by different drivers and feedback would be nice. I was only
> able to test
> it with amdgpu. Other drivers may not even compile.
> </tldr>
>
> If I remember correctly Christian mentioned recently (give or take)
> that maybe
> round-robin could be removed. That got me thinking how and what could
> be
> improved and simplified. So I played a bit in the scheduler code and
> came up
> with something which appears to not crash at least. Whether or not
> there are
> significant advantages apart from maybe code consolidation and
> reduction is the
> main thing to be determined.
>
> One big question is whether round-robin can really be removed. Does
> anyone use
> it, rely on it, or what are even use cases where it is much better
> than FIFO.
>
> See "drm/sched: Add deadline policy" commit message for a short
> description on
> what flavour of deadline scheduling it is. But in essence it should a
> more fair
> FIFO where higher priority can not forever starve lower priorities.
>
> "drm/sched: Connect with dma-fence deadlines" wires up dma-fence
> deadlines to
> the scheduler because it is easy and makes logical sense with this.
> And I
> noticed userspace already uses it so why not wire it up fully.
>
> Otherwise the series is a bit of progression from consolidating RR
> into FIFO
> code paths and going from there to deadline and then to a change in
> how
> dependencies are handled. And code simplification to 1:1 run queue to
> scheduler
> relationship, because deadline does not need per priority run queues.
>
> There is quite a bit of code to go throught here so I think it could
> be even
> better if other drivers could give it a spin as is and see if some
> improvements
> can be detected. Or at least no regressions.
Soooo – I have thought about this series a bit more and also read a bit
about the issues Michel recently mentioned.
As Danilo also pointed out, going for an experiment like that at the
current time is not a good idea. Not with the scheduler being in that
shape still and not without having powerful tools for regression
testing.
That said, we are slowly moving into the right direction. I think one
of the things we're lacking is good testing infrastructure. In fact,
it's on my list for a while now to write kunit tests for the scheduler
(beginning with the basics, submit a number of jobs and all that), so
that we get a better mechanism for detecting regressions.
Once we have more infrastructure for systematic testing, we could
consequently also slowly become more open to looking into more daring
changes.
I unfortunately so far couldn't manage to free up some time to dedicate
to that effort. In case you, Tvrtko, should have capacity for that, I
of course wouldn't mind at all; that could help greatly
Regards,
Philipp
>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: Danilo Krummrich <dakr@redhat.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Philipp Stanner <pstanner@redhat.com>
>
> Tvrtko Ursulin (14):
> drm/sched: Delete unused update_job_credits
> drm/sched: Remove idle entity from tree
> drm/sched: Implement RR via FIFO
> drm/sched: Consolidate entity run queue management
> drm/sched: Move run queue related code into a separate file
> drm/sched: Ignore own fence earlier
> drm/sched: Resolve same scheduler dependencies earlier
> drm/sched: Add deadline policy
> drm/sched: Remove FIFO and RR and simplify to a single run queue
> drm/sched: Queue all free credits in one worker invocation
> drm/sched: Connect with dma-fence deadlines
> drm/sched: Embed run queue singleton into the scheduler
> dma-fence: Add helper for custom fence context when merging fences
> drm/sched: Resolve all job dependencies in one go
>
> drivers/dma-buf/dma-fence-unwrap.c | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 27 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 5 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c | 8 +-
> drivers/gpu/drm/scheduler/Makefile | 2 +-
> drivers/gpu/drm/scheduler/sched_entity.c | 316 ++++++-----
> drivers/gpu/drm/scheduler/sched_fence.c | 5 +-
> drivers/gpu/drm/scheduler/sched_main.c | 587 +++++-------------
> --
> drivers/gpu/drm/scheduler/sched_rq.c | 199 +++++++
> include/drm/gpu_scheduler.h | 74 ++-
> include/linux/dma-fence-unwrap.h | 31 +-
> 14 files changed, 606 insertions(+), 678 deletions(-)
> create mode 100644 drivers/gpu/drm/scheduler/sched_rq.c
>
^ permalink raw reply [flat|nested] 61+ messages in thread