[Mesa-dev] [PATCH shader-db v2 5/5] nv-report: add options to print affected programs

Ilia Mirkin imirkin at alum.mit.edu
Sun Aug 5 15:53:23 UTC 2018


On Sun, Aug 5, 2018 at 8:06 AM, Rhys Perry <pendingchaos02 at gmail.com> wrote:
> v2: rework --top and --smallest
> v2: add --affected option
> v2: make the summary after the affected program lists
>
> Signed-off-by: Rhys Perry <pendingchaos02 at gmail.com>
> ---
>  nv-report.py | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 117 insertions(+), 2 deletions(-)
>
> diff --git a/nv-report.py b/nv-report.py
> index 1894f91409..4f4150a4cb 100644
> --- a/nv-report.py
> +++ b/nv-report.py
> @@ -12,6 +12,7 @@ fields, except for the type, are optional.
>
>  import re
>  import sys
> +import random
>  import argparse
>
>
> @@ -79,13 +80,18 @@ def read_stats(fname):
>
>      return stats
>
> -def diff(a, b):
> +def get_diff_percentage(a, b):
>      percentage = 0.
>      if a != 0.:
>          percentage = b * 100. / a - 100.
>      elif b != 0.:
>          percentage = float('inf')
> -    return "%d -> %d (%.2f%%)" % (a, b, percentage)
> +    return percentage

The "percentage" variable is a bit extraneous now -- can just do
"return" each time instead of setting it.

> +
> +def diff(a, b):
> +    return "%d -> %d (%.2f%%)" % (a, b, get_diff_percentage(a, b))
> +
> +# summary
>
>  def print_summary(before, after, keys, only_affected):
>      if only_affected:
> @@ -135,10 +141,109 @@ def print_helped_hurt(keys, before, after):
>          print "%10d " % getattr(hurt, attr),
>      print
>
> +# --smallest, --affected and --top options
> +
> +def iter_affected(before, after, keys, attrs, only_hurt):
> +    for key in keys:
> +        a = after.stats[key]
> +        b = before.stats[key]
> +        affected = False
> +        hurt = False
> +        for attr in attrs if isinstance(attrs, list) else [attrs]:
> +            aa = getattr(a, attr)
> +            ba = getattr(b, attr)
> +            if aa != ba:
> +                affected = True
> +            if aa > ba:
> +                hurt = True
> +        if only_hurt and not hurt:
> +            continue
> +        if affected:
> +            yield key, b, a
> +
> +def print_affected_list(args, fmt, attrs, print_size, affected):
> +    message = fmt % len(affected)
> +    if args.only_hurt:
> +        message += "hurt"
> +    else:
> +        message += "affected"
> +    message += " programs for " + ', '.join(attrs)
> +    print message
> +
> +    for key, _, b, a in affected:
> +        if print_size:
> +            print "    %d inst : " % a.inst + key
> +        else:
> +            print "    " + key
> +        for attr in attrs:
> +            ba = getattr(b, attr)
> +            aa = getattr(a, attr)
> +            if ba != aa:
> +                print "        %s : %s" % (attr, diff(ba, aa))
> +    print
> +
> +def parse_list_opt(arg):
> +    try:
> +        num = int(arg[0])
> +        attrs = arg[1:]
> +    except Exception:
> +        num = None # l[:None] == l
> +        attrs = arg
> +    if len(attrs) == 0:
> +        attrs = STATS
> +    return num, attrs
> +
> +def print_affected(before, after, keys, args, arg):
> +    num, attrs = parse_list_opt(arg)
> +
> +    affected = iter_affected(before, after, keys, attrs, args.only_hurt)
> +    affected = [(key, None, b, a) for key, b, a in affected]

I prefer list(...) instead of [...]. [] has some nasty side-effects in
Python 2.x, in that the variables being iterated on end up in the
containing scope. I prefer not to tempt fate.

> +    random.shuffle(affected)
> +    affected = affected[:num]
> +
> +    print_affected_list(args, "%d random ", attrs, False, affected)
> +
> +def print_top(before, after, keys, args, arg):
> +    num, attrs = parse_list_opt(arg)
> +    attrs = [attrs[0]]
> +
> +    candidates = []
> +    for key, b, a in iter_affected(before, after, keys, attrs, args.only_hurt):
> +        ba = getattr(b, attrs[0])
> +        aa = getattr(a, attrs[0])
> +        score = abs(get_diff_percentage(ba, aa))
> +        if args.scale_size:
> +            score /= float(after.stats[key].inst)
> +        candidates.append((key, score, b, a))
> +    candidates.sort(key = lambda a: a[1], reverse=True)
> +    candidates = candidates[:num]
> +
> +    print_affected_list(args, "top %d ", attrs, False, candidates)
> +
> +def print_smallest(before, after, keys, args, arg):
> +    num, attrs = parse_list_opt(arg)
> +
> +    affected_iter = iter_affected(before, after, keys, attrs, args.only_hurt)
> +    candidates = [(key, after.stats[key].inst, b, a) for key, b, a, in affected_iter]

list() instead of []

> +    candidates.sort(key = lambda a: a[1])
> +    candidates = candidates[:num]
> +
> +    print_affected_list(args, "smallest %d ", attrs, True, candidates)
> +
>  def main(argv):
>      parser = argparse.ArgumentParser(description=DESCRIPTION)
>      parser.add_argument('before', help="the baseline run")
>      parser.add_argument('after', help="the run to compare against the baseline")
> +    parser.add_argument("--top", action="append", nargs='+', metavar=("N", "ATTR"),
> +        help="also show the top n (or all) programs affected by the first ATTR")

What's the use-case for having multiple --top and others?

> +    parser.add_argument('--smallest', action="append", nargs='*', metavar=("N", "ATTR"),
> +        help="also show the smallest n (or all) programs affected")
> +    parser.add_argument('--affected', action="append", nargs='*', metavar=("N", "ATTR"),
> +        help="also show n (or all) affected programs in a random order (note that N is not needed for ATTR)")
> +    parser.add_argument('--scale_size', action="store_true",
> +        help="scale the score for --top by the program size so smaller ones are first")
> +    parser.add_argument('--only_hurt', action="store_true",
> +        help="only show hurt programs for --smallest, --affected and --small_affected")
>      args = parser.parse_args(argv[1:])
>
>      before = read_stats(args.before)
> @@ -151,6 +256,15 @@ def main(argv):
>              continue
>          keys.add(key)
>
> +    for arg in args.affected or []:
> +        print_affected(before, after, keys, args, arg)
> +
> +    for arg in args.top or []:
> +        print_top(before, after, keys, args, arg)
> +
> +    for arg in args.smallest or []:
> +        print_smallest(before, after, keys, args, arg)
> +
>      print_summary(before, after, keys, True)
>      print
>      print_summary(before, after, keys, False)
> @@ -159,4 +273,5 @@ def main(argv):
>
>
>  if __name__ == "__main__":
> +    random.seed(0)
>      main(sys.argv)
> --
> 2.14.4
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list