diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2017-04-25 15:12:50 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2017-05-09 15:53:02 +0100 |
commit | 9e55cca889cdadbd94f4ea658b41f4cb43ab3fcb (patch) | |
tree | bbc9a167e10d66b4dd1790fb4f06984f8be82df3 /benchmarks/gem_wsim.c | |
parent | 6e6ad40c61ae0a6526f726195549a1c9b62c533c (diff) |
wsim: Add rtavg balancer
An improved version of the rt balancer that tracks the average latency
on each engine, rather than the last instantaneous execution latency.
This makes it much less sensitive to rapid changes, which is both a
positive and a negative.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'benchmarks/gem_wsim.c')
-rw-r--r-- | benchmarks/gem_wsim.c | 133 |
1 files changed, 113 insertions, 20 deletions
diff --git a/benchmarks/gem_wsim.c b/benchmarks/gem_wsim.c index 47b070e2..9f690369 100644 --- a/benchmarks/gem_wsim.c +++ b/benchmarks/gem_wsim.c @@ -50,6 +50,8 @@ #include "igt_aux.h" #include "igt_rand.h" +#include "ewma.h" + enum intel_engine_id { RCS, BCS, @@ -103,6 +105,8 @@ struct w_step unsigned int mapped_len; }; +DECLARE_EWMA(uint64_t, rt, 4, 2) + struct workload { unsigned int nr_steps; @@ -127,6 +131,13 @@ struct workload struct igt_list requests[NUM_ENGINES]; unsigned int nrequest[NUM_ENGINES]; + + union { + struct rtavg { + struct ewma_rt avg[NUM_ENGINES]; + uint32_t last[NUM_ENGINES]; + } rt; + }; }; static const unsigned int nop_calibration_us = 1000; @@ -788,12 +799,31 @@ static const struct workload_balancer qd_balancer = { }; static enum intel_engine_id +__rt_select_engine(struct workload *wrk, unsigned long *qd, bool random) +{ + unsigned int n; + + qd[VCS1] >>= 10; + qd[VCS2] >>= 10; + + if (qd[VCS1] < qd[VCS2]) + n = 0; + else if (qd[VCS2] < qd[VCS1]) + n = 1; + else if (random) + n = hars_petruska_f54_1_random(&wrk->prng) & 1; + else + n = wrk->vcs_rr; + wrk->vcs_rr = n ^ 1; + + return get_vcs_engine(n); +} + +static enum intel_engine_id __rt_balance(const struct workload_balancer *balancer, struct workload *wrk, struct w_step *w, bool random) { - enum intel_engine_id engine; - long qd[NUM_ENGINES]; - unsigned int n; + unsigned long qd[NUM_ENGINES]; igt_assert(w->engine == VCS); @@ -827,22 +857,7 @@ __rt_balance(const struct workload_balancer *balancer, qd[VCS2]); #endif - qd[VCS1] >>= 10; - qd[VCS2] >>= 10; - - if (qd[VCS1] < qd[VCS2]) - n = 0; - else if (qd[VCS2] < qd[VCS1]) - n = 1; - else if (random) - n = hars_petruska_f54_1_random(&wrk->prng) & 1; - else - n = wrk->vcs_rr; - - engine = get_vcs_engine(n); - wrk->vcs_rr = n ^ 1; - - return engine; + return __rt_select_engine(wrk, qd, random); } static enum intel_engine_id @@ -870,6 +885,68 @@ static const struct workload_balancer rtr_balancer = { .balance = rtr_balance, }; +static enum intel_engine_id +rtavg_balance(const struct workload_balancer *balancer, + struct workload *wrk, struct w_step *w) +{ + unsigned long qd[NUM_ENGINES]; + + igt_assert(w->engine == VCS); + + /* Estimate the average "speed" of the most recent batches + * (finish time - submit time) + * and use that as an approximate for the total remaining time for + * all batches on that engine plus the time we expect to execute in. + * We try to keep the total remaining balanced between the engines. + */ + if (wrk->status_page[VCS_SEQNO_IDX(VCS1)] != wrk->rt.last[VCS1]) { + igt_assert((long)(wrk->status_page[2] - wrk->status_page[1]) > 0); + ewma_rt_add(&wrk->rt.avg[VCS1], + wrk->status_page[2] - wrk->status_page[1]); + wrk->rt.last[VCS1] = wrk->status_page[VCS_SEQNO_IDX(VCS1)]; + } + + qd[VCS1] = balancer->get_qd(balancer, wrk, VCS1); + wrk->qd_sum[VCS1] += qd[VCS1]; + qd[VCS1] = (qd[VCS1] + 1) * ewma_rt_read(&wrk->rt.avg[VCS1]); + +#ifdef DEBUG + printf("qd[0] = %d (%d - %d) x %ld (%d) = %ld\n", + wrk->seqno[VCS1] - wrk->status_page[0], + wrk->seqno[VCS1], wrk->status_page[0], + ewma_rt_read(&wrk->rt.avg[VCS1]), + wrk->status_page[2] - wrk->status_page[1], + qd[VCS1]); +#endif + + if (wrk->status_page[VCS_SEQNO_IDX(VCS2)] != wrk->rt.last[VCS2]) { + igt_assert((long)(wrk->status_page[2+16] - wrk->status_page[1+16]) > 0); + ewma_rt_add(&wrk->rt.avg[VCS2], + wrk->status_page[2+16] - wrk->status_page[1+16]); + wrk->rt.last[VCS2] = wrk->status_page[VCS_SEQNO_IDX(VCS2)]; + } + + qd[VCS2] = balancer->get_qd(balancer, wrk, VCS2); + wrk->qd_sum[VCS2] += qd[VCS2]; + qd[VCS2] = (qd[VCS2] + 1) * ewma_rt_read(&wrk->rt.avg[VCS2]); + +#ifdef DEBUG + printf("qd[1] = %d (%d - %d) x %ld (%d) = %ld\n", + wrk->seqno[VCS2] - wrk->status_page[16], + wrk->seqno[VCS2], wrk->status_page[16], + ewma_rt_read(&wrk->rt.avg[VCS2]), + wrk->status_page[18] - wrk->status_page[17], + qd[VCS2]); +#endif + + return __rt_select_engine(wrk, qd, false); +} + +static const struct workload_balancer rtavg_balancer = { + .get_qd = get_qd_depth, + .balance = rtavg_balance, +}; + static void update_bb_seqno(struct w_step *w, enum intel_engine_id engine, uint32_t seqno) { @@ -1277,7 +1354,7 @@ add_workload_arg(char **w_args, unsigned int nr_args, char *w_arg) static int parse_balancing_mode(char *str) { - const char *modes[] = { "rr", "qd", "rt", "rtr" }; + const char *modes[] = { "rr", "qd", "rt", "rtr" , "rtavg" }; int mode = -1; unsigned int i; @@ -1394,27 +1471,43 @@ int main(int argc, char **argv) } switch (i) { case 0: + if (!quiet) + printf("Using rr balancer\n"); balancer = &rr_balancer; flags |= BALANCE; break; case 1: + if (!quiet) + printf("Using qd balancer\n"); igt_assert(intel_gen(intel_get_drm_devid(fd)) >= 8); balancer = &qd_balancer; flags |= SEQNO | BALANCE; break; case 2: + if (!quiet) + printf("Using rt balancer\n"); igt_assert(intel_gen(intel_get_drm_devid(fd)) >= 8); balancer = &rt_balancer; flags |= SEQNO | BALANCE | RT; break; case 3: + if (!quiet) + printf("Using rtr balancer\n"); igt_assert(intel_gen(intel_get_drm_devid(fd)) >= 8); balancer = &rtr_balancer; flags |= SEQNO | BALANCE | RT; break; + case 4: + if (!quiet) + printf("Using rtavg balancer\n"); + igt_assert(intel_gen(intel_get_drm_devid(fd)) >= + 8); + balancer = &rtavg_balancer; + flags |= SEQNO | BALANCE | RT; + break; default: if (!quiet) fprintf(stderr, |