diff options
-rw-r--r-- | benchmarks/gem_wsim.c | 159 |
1 files changed, 135 insertions, 24 deletions
diff --git a/benchmarks/gem_wsim.c b/benchmarks/gem_wsim.c index ace06c15..b366a5d6 100644 --- a/benchmarks/gem_wsim.c +++ b/benchmarks/gem_wsim.c @@ -172,6 +172,10 @@ struct workload struct igt_list requests[NUM_ENGINES]; unsigned int nrequest[NUM_ENGINES]; + struct workload *global_wrk; + const struct workload_balancer *global_balancer; + pthread_mutex_t mutex; + union { struct rtavg { struct ewma_rt avg[NUM_ENGINES]; @@ -194,6 +198,7 @@ static int fd; #define INITVCSRR (1<<5) #define SYNCEDCLIENTS (1<<6) #define HEARTBEAT (1<<7) +#define GLOBAL_BALANCE (1<<8) #define SEQNO_IDX(engine) ((engine) * 16) #define SEQNO_OFFSET(engine) (SEQNO_IDX(engine) * sizeof(uint32_t)) @@ -729,7 +734,10 @@ eb_update_flags(struct w_step *w, enum intel_engine_id engine, static struct drm_i915_gem_exec_object2 * get_status_objects(struct workload *wrk) { - return wrk->status_object; + if (wrk->flags & GLOBAL_BALANCE) + return wrk->global_wrk->status_object; + else + return wrk->status_object; } static void @@ -809,22 +817,31 @@ prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags) wrk->id = id; wrk->prng = rand(); + wrk->run = true; if (flags & INITVCSRR) wrk->vcs_rr = id & 1; - if (flags & SEQNO) { - uint32_t handle = gem_create(fd, 4096); - - gem_set_caching(fd, handle, I915_CACHING_CACHED); - wrk->status_object[0].handle = handle; - wrk->status_page = gem_mmap__cpu(fd, handle, 0, 4096, - PROT_READ); + if (flags & GLOBAL_BALANCE) { + int ret = pthread_mutex_init(&wrk->mutex, NULL); + igt_assert(ret == 0); + } - handle = gem_create(fd, 4096); - wrk->status_object[1].handle = handle; - wrk->status_cs = gem_mmap__wc(fd, handle, - 0, 4096, PROT_WRITE); + if (flags & SEQNO) { + if (!(flags & GLOBAL_BALANCE) || id == 0) { + uint32_t handle; + + handle = gem_create(fd, 4096); + gem_set_caching(fd, handle, I915_CACHING_CACHED); + wrk->status_object[0].handle = handle; + wrk->status_page = gem_mmap__cpu(fd, handle, 0, 4096, + PROT_READ); + + handle = gem_create(fd, 4096); + wrk->status_object[1].handle = handle; + wrk->status_cs = gem_mmap__wc(fd, handle, + 0, 4096, PROT_WRITE); + } } for (i = 0, w = wrk->steps; i < wrk->nr_steps; i++, w++) { @@ -895,13 +912,34 @@ static enum intel_engine_id get_vcs_engine(unsigned int n) static uint32_t new_seqno(struct workload *wrk, enum intel_engine_id engine) { - return ++wrk->seqno[engine]; + uint32_t seqno; + int ret; + + if (wrk->flags & GLOBAL_BALANCE) { + igt_assert(wrk->global_wrk); + wrk = wrk->global_wrk; + + ret = pthread_mutex_lock(&wrk->mutex); + igt_assert(ret == 0); + } + + seqno = ++wrk->seqno[engine]; + + if (wrk->flags & GLOBAL_BALANCE) { + ret = pthread_mutex_unlock(&wrk->mutex); + igt_assert(ret == 0); + } + + return seqno; } static uint32_t current_seqno(struct workload *wrk, enum intel_engine_id engine) { - return wrk->seqno[engine]; + if (wrk->flags & GLOBAL_BALANCE) + return wrk->global_wrk->seqno[engine]; + else + return wrk->seqno[engine]; } #define READ_ONCE(x) (*(volatile typeof(x) *)(&(x))) @@ -909,7 +947,10 @@ current_seqno(struct workload *wrk, enum intel_engine_id engine) static uint32_t read_status_page(struct workload *wrk, unsigned int idx) { - return READ_ONCE(wrk->status_page[idx]); + if (wrk->flags & GLOBAL_BALANCE) + return READ_ONCE(wrk->global_wrk->status_page[idx]); + else + return READ_ONCE(wrk->status_page[idx]); } static uint32_t @@ -994,8 +1035,8 @@ __qd_balance(const struct workload_balancer *balancer, engine = __qd_select_engine(wrk, qd, random); #ifdef DEBUG - printf("qd_balance: 1:%ld 2:%ld rr:%u = %u\t(%lu - %u) (%lu - %u)\n", - qd[VCS1], qd[VCS2], wrk->vcs_rr, engine, + printf("qd_balance[%u]: 1:%ld 2:%ld rr:%u = %u\t(%u - %u) (%u - %u)\n", + wrk->id, qd[VCS1], qd[VCS2], wrk->vcs_rr, engine, current_seqno(wrk, VCS1), current_gpu_seqno(wrk, VCS1), current_seqno(wrk, VCS2), current_gpu_seqno(wrk, VCS2)); #endif @@ -1033,7 +1074,14 @@ qdavg_balance(const struct workload_balancer *balancer, qd[engine] = ewma_rt_read(&wrk->rt.avg[engine]); } - return __qd_select_engine(wrk, qd, false); + engine = __qd_select_engine(wrk, qd, false); +#ifdef DEBUG + printf("qdavg_balance[%u]: 1:%ld 2:%ld rr:%u = %u\t(%u - %u) (%u - %u)\n", + wrk->id, qd[VCS1], qd[VCS2], wrk->vcs_rr, engine, + current_seqno(wrk, VCS1), current_gpu_seqno(wrk, VCS1), + current_seqno(wrk, VCS2), current_gpu_seqno(wrk, VCS2)); +#endif + return engine; } static enum intel_engine_id @@ -1229,6 +1277,48 @@ static const struct workload_balancer all_balancers[] = { }, }; +static unsigned int +global_get_qd(const struct workload_balancer *balancer, + struct workload *wrk, enum intel_engine_id engine) +{ + igt_assert(wrk->global_wrk); + igt_assert(wrk->global_balancer); + + return wrk->global_balancer->get_qd(wrk->global_balancer, + wrk->global_wrk, engine); +} + +static enum intel_engine_id +global_balance(const struct workload_balancer *balancer, + struct workload *wrk, struct w_step *w) +{ + enum intel_engine_id engine; + int ret; + + igt_assert(wrk->global_wrk); + igt_assert(wrk->global_balancer); + + wrk = wrk->global_wrk; + + ret = pthread_mutex_lock(&wrk->mutex); + igt_assert(ret == 0); + + engine = wrk->global_balancer->balance(wrk->global_balancer, wrk, w); + + ret = pthread_mutex_unlock(&wrk->mutex); + igt_assert(ret == 0); + + return engine; +} + +static const struct workload_balancer global_balancer = { + .id = ~0, + .name = "global", + .desc = "Global balancer", + .get_qd = global_get_qd, + .balance = global_balance, + }; + static void update_bb_seqno(struct w_step *w, enum intel_engine_id engine, uint32_t seqno) { @@ -1713,7 +1803,9 @@ static void print_help(void) " -2 Remap VCS2 to BCS.\n" " -R Round-robin initial VCS assignment per client.\n" " -S Synchronize the sequence of random batch durations between\n" -" clients." +" clients.\n" +" -G Global load balancing - a single load balancer will be shared\n" +" between all clients and there will be a single seqno domain." ); } @@ -1848,7 +1940,7 @@ int main(int argc, char **argv) init_clocks(); - while ((c = getopt(argc, argv, "hqv2RSHxc:n:r:w:W:a:t:b:p:")) != -1) { + while ((c = getopt(argc, argv, "hqv2RSHxGc:n:r:w:W:a:t:b:p:")) != -1) { switch (c) { case 'W': if (master_workload >= 0) { @@ -1907,6 +1999,9 @@ int main(int argc, char **argv) case 'H': flags |= HEARTBEAT; break; + case 'G': + flags |= GLOBAL_BALANCE; + break; case 'b': i = find_balancer_by_name(optarg); if (i < 0) { @@ -1964,6 +2059,13 @@ int main(int argc, char **argv) return 1; } + if ((flags & GLOBAL_BALANCE) && !balancer) { + if (verbose) + fprintf(stderr, + "Balancer not specified in global balancing mode!\n"); + return 1; + } + if (append_workload_arg) { append_workload_arg = load_workload_descriptor(append_workload_arg); if (!append_workload_arg) { @@ -2017,7 +2119,10 @@ int main(int argc, char **argv) printf("%u client%s.\n", clients, clients > 1 ? "s" : ""); if (flags & SWAPVCS) printf("Swapping VCS rings between clients.\n"); - if (balancer) + if (flags & GLOBAL_BALANCE) + printf("Using %s balancer in global mode.\n", + balancer->name); + else if (balancer) printf("Using %s balancer.\n", balancer->name); } @@ -2035,15 +2140,21 @@ int main(int argc, char **argv) if (flags & SWAPVCS && i & 1) flags_ &= ~SWAPVCS; - prepare_workload(i, w[i], flags_); + if (flags & GLOBAL_BALANCE) { + w[i]->balancer = &global_balancer; + w[i]->global_wrk = w[0]; + w[i]->global_balancer = balancer; + } else { + w[i]->balancer = balancer; + } w[i]->flags = flags; w[i]->repeat = repeat; - w[i]->balancer = balancer; - w[i]->run = true; w[i]->background = master_workload >= 0 && i != master_workload; w[i]->print_stats = verbose > 1 || (verbose > 0 && master_workload == i); + + prepare_workload(i, w[i], flags_); } gem_quiescent_gpu(fd); |