From: "Christian König" <christian.koenig@amd.com>
To: jiadong.zhu@amd.com, amd-gfx@lists.freedesktop.org
Cc: "Michel Dänzer" <michel@daenzer.net>
Subject: Re: [PATCH 5/5] drm/amdgpu: Improve the software ring priority scheduler
Date: Tue, 18 Oct 2022 13:24:56 +0200 [thread overview]
Message-ID: <6cde0148-b829-cc7e-ebf7-288b74ba8147@amd.com> (raw)
In-Reply-To: <20221018090815.2662321-5-jiadong.zhu@amd.com>
Am 18.10.22 um 11:08 schrieb jiadong.zhu@amd.com:
> From: Jiadong Zhu <Jiadong.Zhu@amd.com>
>
> Using the drm scheduler, the software rings' scheduling threads with different
> priorities have the same opportunity to get the spinlock and copy its packages
> into the real ring. Though preemption may happen for the low priority ring, it
> will catch up with the high priority ring by copying more data (the resubmit
> package and the current ibs) on the next calling of set_wptr. As a result, the
> priority is not quite effective.
>
> Here are some details to improve the priority of software rings at the bottom
> of drm scheduler by slowing down the low priority thread with following
> strategy.
> 1. If all the high priority fences are signaled which indicates gpu is idle
> while there are low priority packages to submit, no delay happens.
> 2. When there are unsignaled fences on high priority rings, we account for the
> portion of the ibs sent from the low priority ring. If the portion exceeds
> a certain threshold(eg, 30%), a timeout wait happens on low priority
> threads till more high priority ibs submitted.
> 3. The mechanism is started when the first time mcbp triggered, ended when all
> the high priority fences are signaled.
This is a really big NAK for this approach since it will break GPU reset
and can lead to deadlocks. You can't sleep in any of the callbacks
waiting for the hardware to do something.
What we could do instead is to insert a dependency for the low priority
ring. E.g. in amdgpu_job_dependency() return the latest high priority
fence whenever a low priority job is about to be scheduled.
Regards,
Christian.
>
> Cc: Christian Koenig <Christian.Koenig@amd.com>
> Cc: Michel Dänzer <michel@daenzer.net>
> Signed-off-by: Jiadong Zhu <Jiadong.Zhu@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c | 93 ++++++++++++++++++--
> drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.h | 3 +
> 2 files changed, 90 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c
> index 41b057b9358e..eac89094f1d1 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c
> @@ -27,7 +27,13 @@
> #include "amdgpu_ring.h"
> #include "amdgpu.h"
>
> +/* The jiffies fallback resubmission happens */
> #define AMDGPU_MUX_RESUBMIT_JIFFIES_TIMEOUT (HZ / 2)
> +
> +/* Maximum waiting jiffies on low priority ring thread */
> +#define AMDGPU_MUX_DELAY_JIFFIES_TIMEOUT (HZ / 10)
> +
> +/* The time threshold of unsignaled fence that trigger mcbp */
> #define AMDGPU_MAX_LAST_UNSIGNALED_THRESHOLD_US 10000
>
> static const struct ring_info {
> @@ -47,6 +53,69 @@ static inline struct amdgpu_mux_entry *amdgpu_ring_mux_sw_entry(struct amdgpu_ri
> &mux->ring_entry[ring->entry_index] : NULL;
> }
>
> +static uint32_t ring_priority_to_ratio_pct(unsigned int hw_prio)
> +{
> + uint32_t ratio;
> +
> + switch (hw_prio) {
> + case AMDGPU_RING_PRIO_DEFAULT:
> + ratio = 30;
> + break;
> + case AMDGPU_RING_PRIO_2:
> + ratio = 100;
> + break;
> + default:
> + ratio = 100;
> + }
> + return ratio;
> +}
> +
> +static void reset_wcnt_on_all_rings(struct amdgpu_ring_mux *mux)
> +{
> + int i;
> +
> + for (i = 0; i < mux->num_ring_entries; i++)
> + mux->ring_entry[i].w_cnt = 0;
> +}
> +
> +/**
> + * Decide if the low priority ring task should be delayed when there are high
> + * priority ibs ongoing. If all the high priority fences are signaled at that
> + * time, gpu is idle, we do not need to wait. Otherwise we calculate the
> + * percentage of portions copying ibs on the current ring and compare with the
> + * threshold according to the priority.
> + */
> +static bool proceed_on_ring(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring)
> +{
> + struct amdgpu_ring *high_prio_ring;
> + u64 current_cnt, total_cnt = 0;
> + int i;
> +
> + for (i = 0; i < mux->num_ring_entries; i++) {
> + if (mux->ring_entry[i].ring->hw_prio > AMDGPU_RING_PRIO_DEFAULT) {
> + high_prio_ring = mux->ring_entry[i].ring;
> + break;
> + }
> + }
> +
> + /*All high priority fences signaled indicates gpu is idle.*/
> + if (amdgpu_fence_count_emitted(high_prio_ring) == 0) {
> + reset_wcnt_on_all_rings(mux);
> + return true;
> + }
> +
> + for (i = 0; i < mux->num_ring_entries; i++) {
> + if (mux->ring_entry[i].ring->hw_prio == ring->hw_prio)
> + current_cnt = mux->ring_entry[i].w_cnt;
> + total_cnt += mux->ring_entry[i].w_cnt;
> + }
> +
> + if (total_cnt == 0)
> + return true;
> +
> + return ring_priority_to_ratio_pct(ring->hw_prio) > current_cnt * 100 / total_cnt;
> +}
> +
> /* copy packages on sw ring range[begin, end) */
> static void amdgpu_ring_mux_copy_pkt_from_sw_ring(struct amdgpu_ring_mux *mux,
> struct amdgpu_ring *ring,
> @@ -73,6 +142,13 @@ static void amdgpu_ring_mux_copy_pkt_from_sw_ring(struct amdgpu_ring_mux *mux,
> }
> }
>
> +/* delay low priotiry task depending on high priority rings fence signal condition*/
> +static void wait_on_ring(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring)
> +{
> + wait_event_interruptible_timeout(mux->wait, proceed_on_ring(mux, ring),
> + AMDGPU_MUX_DELAY_JIFFIES_TIMEOUT);
> +}
> +
> static void amdgpu_mux_resubmit_chunks(struct amdgpu_ring_mux *mux)
> {
> struct amdgpu_mux_entry *e = NULL;
> @@ -126,7 +202,6 @@ static void amdgpu_ring_mux_schedule_resubmit(struct amdgpu_ring_mux *mux)
> static void amdgpu_mux_resubmit_fallback(struct timer_list *t)
> {
> struct amdgpu_ring_mux *mux = from_timer(mux, t, resubmit_timer);
> -
> if (!spin_trylock(&mux->lock)) {
> amdgpu_ring_mux_schedule_resubmit(mux);
> DRM_ERROR("reschedule resubmit\n");
> @@ -158,6 +233,7 @@ int amdgpu_ring_mux_init(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring,
> }
>
> spin_lock_init(&mux->lock);
> + init_waitqueue_head(&mux->wait);
> timer_setup(&mux->resubmit_timer, amdgpu_mux_resubmit_fallback, 0);
>
> return 0;
> @@ -205,8 +281,10 @@ void amdgpu_ring_mux_set_wptr(struct amdgpu_ring_mux *mux, struct amdgpu_ring *r
> {
> struct amdgpu_mux_entry *e;
>
> - spin_lock(&mux->lock);
> + if (ring->hw_prio <= AMDGPU_RING_PRIO_DEFAULT && !proceed_on_ring(mux, ring))
> + wait_on_ring(mux, ring);
>
> + spin_lock(&mux->lock);
> if (ring->hw_prio <= AMDGPU_RING_PRIO_DEFAULT)
> amdgpu_mux_resubmit_chunks(mux);
>
> @@ -238,7 +316,12 @@ void amdgpu_ring_mux_set_wptr(struct amdgpu_ring_mux *mux, struct amdgpu_ring *r
> } else {
> e->end_ptr_in_hw_ring = mux->real_ring->wptr;
> }
> +
> + e->w_cnt++;
> spin_unlock(&mux->lock);
> +
> + if (ring->hw_prio > AMDGPU_RING_PRIO_DEFAULT)
> + wake_up_interruptible(&mux->wait);
> }
>
> u64 amdgpu_ring_mux_get_wptr(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring)
> @@ -373,7 +456,9 @@ int amdgpu_mcbp_trigger_preempt(struct amdgpu_ring_mux *mux)
> spin_lock(&mux->lock);
> mux->pending_trailing_fence_signaled = true;
> r = amdgpu_ring_preempt_ib(mux->real_ring);
> + reset_wcnt_on_all_rings(mux);
> spin_unlock(&mux->lock);
> +
> return r;
> }
>
> @@ -408,10 +493,6 @@ void amdgpu_ring_mux_start_ib(struct amdgpu_ring_mux *mux, struct amdgpu_ring *r
> struct amdgpu_mux_entry *e;
> struct amdgpu_mux_chunk *chunk;
>
> - spin_lock(&mux->lock);
> - amdgpu_mux_resubmit_chunks(mux);
> - spin_unlock(&mux->lock);
> -
> e = amdgpu_ring_mux_sw_entry(mux, ring);
> if (!e) {
> DRM_ERROR("cannot find entry!\n");
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.h
> index aa758ebc86ae..a99647e33c9e 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.h
> @@ -39,6 +39,7 @@ struct amdgpu_ring;
> * @sw_rptr: the read pointer in software ring.
> * @sw_wptr: the write pointer in software ring.
> * @list: list head for amdgpu_mux_chunk
> + * @w_cnt: the write count of the current ring.
> */
> struct amdgpu_mux_entry {
> struct amdgpu_ring *ring;
> @@ -48,6 +49,7 @@ struct amdgpu_mux_entry {
> u64 sw_rptr;
> u64 sw_wptr;
> struct list_head list;
> + u64 w_cnt;
> };
>
> struct amdgpu_ring_mux {
> @@ -64,6 +66,7 @@ struct amdgpu_ring_mux {
> struct timer_list resubmit_timer;
>
> bool pending_trailing_fence_signaled;
> + wait_queue_head_t wait;
> };
>
> /**
next prev parent reply other threads:[~2022-10-18 11:25 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-18 9:08 [PATCH 1/5] drm/amdgpu: Introduce gfx software ring (v8) jiadong.zhu
2022-10-18 9:08 ` [PATCH 2/5] drm/amdgpu: Add software ring callbacks for gfx9 (v8) jiadong.zhu
2022-10-18 9:08 ` [PATCH 3/5] drm/amdgpu: Modify unmap_queue format for gfx9 (v4) jiadong.zhu
2022-11-22 5:46 ` Luben Tuikov
2022-10-18 9:08 ` [PATCH 4/5] drm/amdgpu: MCBP based on DRM scheduler (v8) jiadong.zhu
2022-10-31 12:01 ` Michel Dänzer
2022-11-01 1:04 ` Zhu, Jiadong
2022-11-01 9:10 ` Michel Dänzer
2022-11-01 9:58 ` Zhu, Jiadong
2022-11-01 10:09 ` Michel Dänzer
2022-11-02 11:26 ` Michel Dänzer
2022-11-03 2:58 ` Zhu, Jiadong
2022-11-03 9:04 ` Michel Dänzer
2022-11-08 8:01 ` Zhu, Jiadong
2022-11-10 17:00 ` Michel Dänzer
2022-11-10 17:54 ` Alex Deucher
2022-11-11 6:15 ` Zhu, Jiadong
2022-11-14 17:15 ` Michel Dänzer
2022-11-17 3:34 ` Zhu, Jiadong
2022-11-10 19:27 ` Luben Tuikov
2022-10-18 9:08 ` [PATCH 5/5] drm/amdgpu: Improve the software ring priority scheduler jiadong.zhu
2022-10-18 11:24 ` Christian König [this message]
2022-10-19 15:14 ` [PATCH 1/5] drm/amdgpu: Introduce gfx software ring (v8) Luben Tuikov
2022-10-20 14:49 ` Michel Dänzer
2022-10-20 14:59 ` Christian König
2022-10-21 7:42 ` Michel Dänzer
2022-10-31 8:10 ` Zhu, Jiadong
2022-10-31 11:58 ` Michel Dänzer
2022-11-22 5:33 ` Luben Tuikov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6cde0148-b829-cc7e-ebf7-288b74ba8147@amd.com \
--to=christian.koenig@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=jiadong.zhu@amd.com \
--cc=michel@daenzer.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox