[PATCH 2/2] drm/amd/sched: add schuduling policy
Andres Rodriguez
andresx7 at gmail.com
Thu Mar 16 15:31:39 UTC 2017
On 2017-03-16 11:13 AM, Andres Rodriguez wrote:
>
>
> On 2017-03-16 05:15 AM, zhoucm1 wrote:
>>
>>
>> On 2017年03月16日 17:10, Christian König wrote:
>>> Am 16.03.2017 um 10:00 schrieb Chunming Zhou:
>>>> if high priority rq is full, then process with low priority could be
>>>> starve.
>>>> Add policy for this problem, the high proiority can ahead of next
>>>> priority queue,
>>>> the ratio is 2 : 1.
>>>>
>>>> Change-Id: I58f4a6b9cdce8689b18dd8e83dd6e2cf5f99d5fb
>>>> Signed-off-by: Chunming Zhou <David1.Zhou at amd.com>
>>>
>>> Well, the idea behind the high priority queues is to actually starve
>>> the low priority queues to a certain amount.
>>>
>>> At least for the kernel queue that is really desired.
>> Yes, agree, but we certainly don't want low priority queue is totally
>> dead, which doesn't have chance to run if high priority queue is always
>> full and busy.
>> If without Andres changes, it doesn't matter. But after Andres changes
>> upstream, we need scheduling policy.
>>
>> Regards,
>> David Zhou
>
> Hey David,
>
> The desired behavior is actually starvation. This is why allocating a
> high priority context is locked behind root privileges at the moment.
>
> High priority work includes many different features intended for the
> safety of the user wearing the headset. These include:
> - stopping the user from tripping over furniture
> - preventing motion sickness
>
> We cannot compromise these safety features in order to run non-critical
> tasks.
>
> The current approach also has the disadvantage of heavily interleaving
> work. This is going to have two undesired side effects. First, there
> will be a performance overhead from having the queue context switch so
> often.
>
> Second, this approach improves concurrency of work in a ring with mixed
> priority work, but actually decreases overall system concurrency. When a
> ring's HW queue has any high priority work committed, the whole ring
> will be executing at high priority. So interleaving the work will result
> in extending the time a ring spends in high priority mode. This
> effectively extends time that a ring might spend with CU's reserved
> which will have a performance impact on other rings.
>
> The best approach here is to make sure we don't map high priority work
> and regular priority work to the same ring. This is why the LRU policy
> for userspace ring ids to kernel ring ids was introduced. This policy
> provides the guarantee as a side effect.
Wanted to correct myself here. The LRU policy doesn't actually provide a
guarantee. It approximates it.
Regards,
Andres
> But further work there could be
> useful to actually check context priorities when doing the ring mapping.
>
> By placing work on different rings, we let the hardware actually
> dispatch work according to wave parameters like VGPR usage, etc. Trying
> to deduce all this information in the GPU scheduler will get very
> complicated.
>
> This is NAK'd by me.
>
> Regards,
> Andres
>
>
>>>
>>> Christian.
>>>
>>>> ---
>>>> drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | 26
>>>> +++++++++++++++++++++++---
>>>> drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 2 ++
>>>> 2 files changed, 25 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
>>>> b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
>>>> index 0f439dd..4637b6f 100644
>>>> --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
>>>> +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
>>>> @@ -35,11 +35,16 @@
>>>> static void amd_sched_process_job(struct fence *f, struct fence_cb
>>>> *cb);
>>>> /* Initialize a given run queue struct */
>>>> -static void amd_sched_rq_init(struct amd_sched_rq *rq)
>>>> +static void amd_sched_rq_init(struct amd_gpu_scheduler *sched, enum
>>>> + amd_sched_priority pri)
>>>> {
>>>> + struct amd_sched_rq *rq = &sched->sched_rq[pri];
>>>> +
>>>> spin_lock_init(&rq->lock);
>>>> INIT_LIST_HEAD(&rq->entities);
>>>> rq->current_entity = NULL;
>>>> + rq->wait_base = pri * 2;
>>>> + rq->wait = rq->wait_base;
>>>> }
>>>> static void amd_sched_rq_add_entity(struct amd_sched_rq *rq,
>>>> @@ -494,17 +499,32 @@ static void amd_sched_wakeup(struct
>>>> amd_gpu_scheduler *sched)
>>>> {
>>>> struct amd_sched_entity *entity;
>>>> int i;
>>>> + bool skip;
>>>> if (!amd_sched_ready(sched))
>>>> return NULL;
>>>> +retry:
>>>> + skip = false;
>>>> /* Kernel run queue has higher priority than normal run queue*/
>>>> for (i = AMD_SCHED_PRIORITY_MAX - 1; i >=
>>>> AMD_SCHED_PRIORITY_MIN; i--) {
>>>> + if ((i > AMD_SCHED_PRIORITY_MIN) &&
>>>> + (sched->sched_rq[i - 1].wait >=
>>>> sched->sched_rq[i].wait_base)) {
>>>> + sched->sched_rq[i - 1].wait = sched->sched_rq[i -
>>>> 1].wait_base;
>>>> + skip = true;
>>>> + continue;
>>>> + }
>>>> entity = amd_sched_rq_select_entity(&sched->sched_rq[i]);
>>>> - if (entity)
>>>> + if (entity) {
>>>> + if (i > AMD_SCHED_PRIORITY_MIN)
>>>> + sched->sched_rq[i - 1].wait++;
>>>> break;
>>>> + }
>>>> }
>>>> + if (!entity && skip)
>>>> + goto retry;
>>>> +
>>>> return entity;
>>>> }
>>>> @@ -608,7 +628,7 @@ int amd_sched_init(struct amd_gpu_scheduler
>>>> *sched,
>>>> sched->name = name;
>>>> sched->timeout = timeout;
>>>> for (i = AMD_SCHED_PRIORITY_MIN; i < AMD_SCHED_PRIORITY_MAX; i++)
>>>> - amd_sched_rq_init(&sched->sched_rq[i]);
>>>> + amd_sched_rq_init(sched, i);
>>>> init_waitqueue_head(&sched->wake_up_worker);
>>>> init_waitqueue_head(&sched->job_scheduled);
>>>> diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
>>>> b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
>>>> index 99f0240..4caed30 100644
>>>> --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
>>>> +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
>>>> @@ -64,6 +64,8 @@ struct amd_sched_rq {
>>>> spinlock_t lock;
>>>> struct list_head entities;
>>>> struct amd_sched_entity *current_entity;
>>>> + int wait_base;
>>>> + int wait;
>>>> };
>>>> struct amd_sched_fence {
>>>
>>>
>>
More information about the amd-gfx
mailing list