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

Rhys Perry pendingchaos02 at gmail.com
Sun Aug 5 12:06:12 UTC 2018


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
+
+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]
+    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]
+    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")
+    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



More information about the mesa-dev mailing list