diff mbox series

[i-g-t,05/10] gem_wsim: Support random buffer sizes

Message ID 20200617160120.16555-6-tvrtko.ursulin@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series gem_wsim improvements | expand

Commit Message

Tvrtko Ursulin June 17, 2020, 4:01 p.m. UTC
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

See README for more details.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 benchmarks/gem_wsim.c  | 71 +++++++++++++++++++++++++++++++++---------
 benchmarks/wsim/README |  4 +++
 2 files changed, 61 insertions(+), 14 deletions(-)

Comments

Chris Wilson June 17, 2020, 4:31 p.m. UTC | #1
Quoting Tvrtko Ursulin (2020-06-17 17:01:15)
> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> 
> See README for more details.
> 
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> ---
>  benchmarks/gem_wsim.c  | 71 +++++++++++++++++++++++++++++++++---------
>  benchmarks/wsim/README |  4 +++
>  2 files changed, 61 insertions(+), 14 deletions(-)
> 
> diff --git a/benchmarks/gem_wsim.c b/benchmarks/gem_wsim.c
> index 5893de38a98e..c1405596c46a 100644
> --- a/benchmarks/gem_wsim.c
> +++ b/benchmarks/gem_wsim.c
> @@ -117,12 +117,18 @@ struct bond {
>         enum intel_engine_id master;
>  };
>  
> +struct work_buffer_size {
> +       unsigned long size;
> +       unsigned long min;
> +       unsigned long max;
> +};
> +
>  struct working_set {
>         int id;
>         bool shared;
>         unsigned int nr;
>         uint32_t *handles;
> -       unsigned long *sizes;
> +       struct work_buffer_size *sizes;
>  };
>  
>  struct workload;
> @@ -203,6 +209,7 @@ struct workload
>         bool print_stats;
>  
>         uint32_t bb_prng;
> +       uint32_t bo_prng;
>  
>         struct timespec repeat_start;
>  
> @@ -757,10 +764,12 @@ static int add_buffers(struct working_set *set, char *str)
>          * 4m
>          * 4g
>          * 10n4k - 10 4k batches
> +        * 4096-16k - random size in range
>          */
> -       unsigned long *sizes, size;
> +       struct work_buffer_size *sizes;
> +       unsigned long min_sz, max_sz;
> +       char *n, *max = NULL;
>         unsigned int add, i;
> -       char *n;
>  
>         n = index(str, 'n');
>         if (n) {
> @@ -773,16 +782,34 @@ static int add_buffers(struct working_set *set, char *str)
>                 add = 1;
>         }
>  
> -       size = parse_size(str);
> -       if (!size)
> +       n = index(str, '-');
> +       if (n) {
> +               *n = 0;
> +               max = ++n;
> +       }
> +
> +       min_sz = parse_size(str);
> +       if (!min_sz)
>                 return -1;
>  
> +       if (max) {
> +               max_sz = parse_size(max);
> +               if (!max_sz)
> +                       return -1;
> +       } else {
> +               max_sz = min_sz;
> +       }
> +
>         sizes = realloc(set->sizes, (set->nr + add) * sizeof(*sizes));
>         if (!sizes)
>                 return -1;
>  
> -       for (i = 0; i < add; i++)
> -               sizes[set->nr + i] = size;
> +       for (i = 0; i < add; i++) {
> +               struct work_buffer_size *sz = &sizes[set->nr + i];
> +               sz->min = min_sz;
> +               sz->max = max_sz;
> +               sz->size = 0;
> +       }
>  
>         set->nr += add;
>         set->sizes = sizes;
> @@ -824,7 +851,7 @@ static uint64_t engine_list_mask(const char *_str)
>         return mask;
>  }
>  
> -static void allocate_working_set(struct working_set *set);
> +static void allocate_working_set(struct workload *wrk, struct working_set *set);
>  
>  #define int_field(_STEP_, _FIELD_, _COND_, _ERR_) \
>         if ((field = strtok_r(fstart, ".", &fctx))) { \
> @@ -1177,10 +1204,12 @@ add_step:
>  
>         wrk->nr_steps = nr_steps;
>         wrk->steps = steps;
> +       wrk->flags = flags;
>         wrk->prio = arg->prio;
>         wrk->sseu = arg->sseu;
>         wrk->max_working_set_id = -1;
>         wrk->working_sets = NULL;
> +       wrk->bo_prng = (wrk->flags & SYNCEDCLIENTS) ? master_prng : rand();
>  
>         free(desc);
>  
> @@ -1234,7 +1263,7 @@ add_step:
>          */
>         for (i = 0, w = wrk->steps; i < wrk->nr_steps; i++, w++) {
>                 if (w->type == WORKINGSET && w->working_set.shared)
> -                       allocate_working_set(&w->working_set);
> +                       allocate_working_set(wrk, &w->working_set);
>         }
>  
>         wrk->max_working_set_id = -1;
> @@ -1267,6 +1296,7 @@ clone_workload(struct workload *_wrk)
>         igt_assert(wrk);
>         memset(wrk, 0, sizeof(*wrk));
>  
> +       wrk->flags = _wrk->flags;
>         wrk->prio = _wrk->prio;
>         wrk->sseu = _wrk->sseu;
>         wrk->nr_steps = _wrk->nr_steps;

wrk->flags wasn't introduced in this patch, why are we needing to copy
them now.

I see wrk->bo_prn = flags & SYNC above, but I haven't seem them used
again later. They used to carry the balancer info and were setup in
main. Am I not mistaken in thinking they still are being set in main()
as well?
-Chris
Tvrtko Ursulin June 18, 2020, 8:06 a.m. UTC | #2
On 17/06/2020 17:31, Chris Wilson wrote:
> Quoting Tvrtko Ursulin (2020-06-17 17:01:15)
>> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>>
>> See README for more details.
>>
>> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>> ---
>>   benchmarks/gem_wsim.c  | 71 +++++++++++++++++++++++++++++++++---------
>>   benchmarks/wsim/README |  4 +++
>>   2 files changed, 61 insertions(+), 14 deletions(-)
>>
>> diff --git a/benchmarks/gem_wsim.c b/benchmarks/gem_wsim.c
>> index 5893de38a98e..c1405596c46a 100644
>> --- a/benchmarks/gem_wsim.c
>> +++ b/benchmarks/gem_wsim.c
>> @@ -117,12 +117,18 @@ struct bond {
>>          enum intel_engine_id master;
>>   };
>>   
>> +struct work_buffer_size {
>> +       unsigned long size;
>> +       unsigned long min;
>> +       unsigned long max;
>> +};
>> +
>>   struct working_set {
>>          int id;
>>          bool shared;
>>          unsigned int nr;
>>          uint32_t *handles;
>> -       unsigned long *sizes;
>> +       struct work_buffer_size *sizes;
>>   };
>>   
>>   struct workload;
>> @@ -203,6 +209,7 @@ struct workload
>>          bool print_stats;
>>   
>>          uint32_t bb_prng;
>> +       uint32_t bo_prng;
>>   
>>          struct timespec repeat_start;
>>   
>> @@ -757,10 +764,12 @@ static int add_buffers(struct working_set *set, char *str)
>>           * 4m
>>           * 4g
>>           * 10n4k - 10 4k batches
>> +        * 4096-16k - random size in range
>>           */
>> -       unsigned long *sizes, size;
>> +       struct work_buffer_size *sizes;
>> +       unsigned long min_sz, max_sz;
>> +       char *n, *max = NULL;
>>          unsigned int add, i;
>> -       char *n;
>>   
>>          n = index(str, 'n');
>>          if (n) {
>> @@ -773,16 +782,34 @@ static int add_buffers(struct working_set *set, char *str)
>>                  add = 1;
>>          }
>>   
>> -       size = parse_size(str);
>> -       if (!size)
>> +       n = index(str, '-');
>> +       if (n) {
>> +               *n = 0;
>> +               max = ++n;
>> +       }
>> +
>> +       min_sz = parse_size(str);
>> +       if (!min_sz)
>>                  return -1;
>>   
>> +       if (max) {
>> +               max_sz = parse_size(max);
>> +               if (!max_sz)
>> +                       return -1;
>> +       } else {
>> +               max_sz = min_sz;
>> +       }
>> +
>>          sizes = realloc(set->sizes, (set->nr + add) * sizeof(*sizes));
>>          if (!sizes)
>>                  return -1;
>>   
>> -       for (i = 0; i < add; i++)
>> -               sizes[set->nr + i] = size;
>> +       for (i = 0; i < add; i++) {
>> +               struct work_buffer_size *sz = &sizes[set->nr + i];
>> +               sz->min = min_sz;
>> +               sz->max = max_sz;
>> +               sz->size = 0;
>> +       }
>>   
>>          set->nr += add;
>>          set->sizes = sizes;
>> @@ -824,7 +851,7 @@ static uint64_t engine_list_mask(const char *_str)
>>          return mask;
>>   }
>>   
>> -static void allocate_working_set(struct working_set *set);
>> +static void allocate_working_set(struct workload *wrk, struct working_set *set);
>>   
>>   #define int_field(_STEP_, _FIELD_, _COND_, _ERR_) \
>>          if ((field = strtok_r(fstart, ".", &fctx))) { \
>> @@ -1177,10 +1204,12 @@ add_step:
>>   
>>          wrk->nr_steps = nr_steps;
>>          wrk->steps = steps;
>> +       wrk->flags = flags;
>>          wrk->prio = arg->prio;
>>          wrk->sseu = arg->sseu;
>>          wrk->max_working_set_id = -1;
>>          wrk->working_sets = NULL;
>> +       wrk->bo_prng = (wrk->flags & SYNCEDCLIENTS) ? master_prng : rand();
>>   
>>          free(desc);
>>   
>> @@ -1234,7 +1263,7 @@ add_step:
>>           */
>>          for (i = 0, w = wrk->steps; i < wrk->nr_steps; i++, w++) {
>>                  if (w->type == WORKINGSET && w->working_set.shared)
>> -                       allocate_working_set(&w->working_set);
>> +                       allocate_working_set(wrk, &w->working_set);
>>          }
>>   
>>          wrk->max_working_set_id = -1;
>> @@ -1267,6 +1296,7 @@ clone_workload(struct workload *_wrk)
>>          igt_assert(wrk);
>>          memset(wrk, 0, sizeof(*wrk));
>>   
>> +       wrk->flags = _wrk->flags;
>>          wrk->prio = _wrk->prio;
>>          wrk->sseu = _wrk->sseu;
>>          wrk->nr_steps = _wrk->nr_steps;
> 
> wrk->flags wasn't introduced in this patch, why are we needing to copy
> them now.
> 
> I see wrk->bo_prn = flags & SYNC above, but I haven't seem them used
> again later. They used to carry the balancer info and were setup in
> main. Am I not mistaken in thinking they still are being set in main()
> as well?

I couldn't remember but looking around looks like you are right. I'll do 
some experiments and remove it if confirmed.

Regards,

Tvrtko
diff mbox series

Patch

diff --git a/benchmarks/gem_wsim.c b/benchmarks/gem_wsim.c
index 5893de38a98e..c1405596c46a 100644
--- a/benchmarks/gem_wsim.c
+++ b/benchmarks/gem_wsim.c
@@ -117,12 +117,18 @@  struct bond {
 	enum intel_engine_id master;
 };
 
+struct work_buffer_size {
+	unsigned long size;
+	unsigned long min;
+	unsigned long max;
+};
+
 struct working_set {
 	int id;
 	bool shared;
 	unsigned int nr;
 	uint32_t *handles;
-	unsigned long *sizes;
+	struct work_buffer_size *sizes;
 };
 
 struct workload;
@@ -203,6 +209,7 @@  struct workload
 	bool print_stats;
 
 	uint32_t bb_prng;
+	uint32_t bo_prng;
 
 	struct timespec repeat_start;
 
@@ -757,10 +764,12 @@  static int add_buffers(struct working_set *set, char *str)
 	 * 4m
 	 * 4g
 	 * 10n4k - 10 4k batches
+	 * 4096-16k - random size in range
 	 */
-	unsigned long *sizes, size;
+	struct work_buffer_size *sizes;
+	unsigned long min_sz, max_sz;
+	char *n, *max = NULL;
 	unsigned int add, i;
-	char *n;
 
 	n = index(str, 'n');
 	if (n) {
@@ -773,16 +782,34 @@  static int add_buffers(struct working_set *set, char *str)
 		add = 1;
 	}
 
-	size = parse_size(str);
-	if (!size)
+	n = index(str, '-');
+	if (n) {
+		*n = 0;
+		max = ++n;
+	}
+
+	min_sz = parse_size(str);
+	if (!min_sz)
 		return -1;
 
+	if (max) {
+		max_sz = parse_size(max);
+		if (!max_sz)
+			return -1;
+	} else {
+		max_sz = min_sz;
+	}
+
 	sizes = realloc(set->sizes, (set->nr + add) * sizeof(*sizes));
 	if (!sizes)
 		return -1;
 
-	for (i = 0; i < add; i++)
-		sizes[set->nr + i] = size;
+	for (i = 0; i < add; i++) {
+		struct work_buffer_size *sz = &sizes[set->nr + i];
+		sz->min = min_sz;
+		sz->max = max_sz;
+		sz->size = 0;
+	}
 
 	set->nr += add;
 	set->sizes = sizes;
@@ -824,7 +851,7 @@  static uint64_t engine_list_mask(const char *_str)
 	return mask;
 }
 
-static void allocate_working_set(struct working_set *set);
+static void allocate_working_set(struct workload *wrk, struct working_set *set);
 
 #define int_field(_STEP_, _FIELD_, _COND_, _ERR_) \
 	if ((field = strtok_r(fstart, ".", &fctx))) { \
@@ -1177,10 +1204,12 @@  add_step:
 
 	wrk->nr_steps = nr_steps;
 	wrk->steps = steps;
+	wrk->flags = flags;
 	wrk->prio = arg->prio;
 	wrk->sseu = arg->sseu;
 	wrk->max_working_set_id = -1;
 	wrk->working_sets = NULL;
+	wrk->bo_prng = (wrk->flags & SYNCEDCLIENTS) ? master_prng : rand();
 
 	free(desc);
 
@@ -1234,7 +1263,7 @@  add_step:
 	 */
 	for (i = 0, w = wrk->steps; i < wrk->nr_steps; i++, w++) {
 		if (w->type == WORKINGSET && w->working_set.shared)
-			allocate_working_set(&w->working_set);
+			allocate_working_set(wrk, &w->working_set);
 	}
 
 	wrk->max_working_set_id = -1;
@@ -1267,6 +1296,7 @@  clone_workload(struct workload *_wrk)
 	igt_assert(wrk);
 	memset(wrk, 0, sizeof(*wrk));
 
+	wrk->flags = _wrk->flags;
 	wrk->prio = _wrk->prio;
 	wrk->sseu = _wrk->sseu;
 	wrk->nr_steps = _wrk->nr_steps;
@@ -1515,7 +1545,7 @@  alloc_step_batch(struct workload *wrk, struct w_step *w, unsigned int flags)
 
 			igt_assert(set->nr);
 			igt_assert(entry->target < set->nr);
-			igt_assert(set->sizes[entry->target]);
+			igt_assert(set->sizes[entry->target].size);
 
 			dep_handle = set->handles[entry->target];
 		}
@@ -1683,15 +1713,27 @@  static size_t sizeof_engines_bond(int count)
 			engines[count]);
 }
 
-static void allocate_working_set(struct working_set *set)
+static unsigned long
+get_buffer_size(struct workload *wrk, const struct work_buffer_size *sz)
+{
+	if (sz->min == sz->max)
+		return sz->min;
+	else
+		return sz->min + hars_petruska_f54_1_random(&wrk->bo_prng) %
+		       (sz->max + 1 - sz->min);
+}
+
+static void allocate_working_set(struct workload *wrk, struct working_set *set)
 {
 	unsigned int i;
 
 	set->handles = calloc(set->nr, sizeof(*set->handles));
 	igt_assert(set->handles);
 
-	for (i = 0; i < set->nr; i++)
-		set->handles[i] = alloc_bo(fd, set->sizes[i]);
+	for (i = 0; i < set->nr; i++) {
+		set->sizes[i].size = get_buffer_size(wrk, &set->sizes[i]);
+		set->handles[i] = alloc_bo(fd, set->sizes[i].size);
+	}
 }
 
 #define alloca0(sz) ({ size_t sz__ = (sz); memset(alloca(sz__), 0, sz__); })
@@ -1707,6 +1749,7 @@  prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags)
 
 	wrk->id = id;
 	wrk->bb_prng = (wrk->flags & SYNCEDCLIENTS) ? master_prng : rand();
+	wrk->bo_prng = (wrk->flags & SYNCEDCLIENTS) ? master_prng : rand();
 	wrk->run = true;
 
 	/*
@@ -1939,7 +1982,7 @@  prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags)
 	 */
 	for (i = 0, w = wrk->steps; i < wrk->nr_steps; i++, w++) {
 		if (w->type == WORKINGSET && !w->working_set.shared)
-			allocate_working_set(&w->working_set);
+			allocate_working_set(wrk, &w->working_set);
 	}
 
 	/*
diff --git a/benchmarks/wsim/README b/benchmarks/wsim/README
index 3d9143226740..8c71f2fe6579 100644
--- a/benchmarks/wsim/README
+++ b/benchmarks/wsim/README
@@ -307,11 +307,15 @@  For size a byte size can be given, or suffix 'k', 'm' or 'g' can be used (case
 insensitive). Prefix in the format of "<int>n<size>" can also be given to create
 multiple objects of the same size.
 
+Ranges can also be specified using the <min>-<max> syntax.
+
 Examples:
 
   w.1.4k - Working set 1 with a single 4KiB object in it.
   W.2.2M/32768 - Working set 2 with one 2MiB and one 32768 byte object.
   w.3.10n4k/2n20000 - Working set 3 with ten 4KiB and two 20000 byte objects.
+  w.4.4n4k-1m - Working set 4 with four objects of random size between 4KiB and
+		1MiB.
 
 Working set objects can be referenced as data dependency targets using the new
 'r'/'w' syntax. Simple example: