summaryrefslogtreecommitdiff
path: root/benchmarks/gem_wsim.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2017-04-25 15:12:50 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2017-05-09 15:53:02 +0100
commit9e55cca889cdadbd94f4ea658b41f4cb43ab3fcb (patch)
treebbc9a167e10d66b4dd1790fb4f06984f8be82df3 /benchmarks/gem_wsim.c
parent6e6ad40c61ae0a6526f726195549a1c9b62c533c (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.c133
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,