[PATCH 2/2] drm/amd/sched: add schuduling policy

Christian König deathsimple at vodafone.de
Thu Mar 16 16:01:56 UTC 2017


Am 16.03.2017 um 16:31 schrieb Andres Rodriguez:
>
>
> 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.

Thanks for the quick response, and yes that's what I was expecting as 
requirement for that feature as well.

>>
>> 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.

What David is perfectly right with is that this has the potential for 
undesired side effects.

But I completely agree that deadline or fair queue scheduling is tricky 
to implement even when it is desired.

So letting a submission dominate all other is perfectly ok for me as 
long as it is limited to a certain set of processes somehow.

Christian.

>
> 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 {
>>>>
>>>>
>>>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx




More information about the amd-gfx mailing list