[Mesa-dev] [PATCH 2/2] vkpipeline-db: add support for anv

Timothy Arceri tarceri at itsqueeze.com
Tue Jun 12 05:05:18 UTC 2018


From: Timothy Arceri <tarceri at localhost.localdomain>

---
 anv-report.py | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++
 run.c         |  75 +++++++++++++-------
 2 files changed, 239 insertions(+), 27 deletions(-)
 create mode 100755 anv-report.py

diff --git a/anv-report.py b/anv-report.py
new file mode 100755
index 0000000..b306220
--- /dev/null
+++ b/anv-report.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python3
+
+import re
+import argparse
+
+
+def get_results(filename):
+    file = open(filename, "r")
+    lines = file.read().split('\n')
+
+    results = {}
+
+    re_match = re.compile(r"(\S+) - (\S+ \S+) shader: (\S*) inst, (\S*) loops, (\S*) cycles, (\S*):(\S*) spills:fills")
+    for line in lines:
+        match = re.search(re_match, line)
+        if match is None:
+            continue
+
+        groups = match.groups()
+        inst_count = int(groups[2])
+        loop_count = int(groups[3])
+        cycle_count = int(groups[4])
+        spill_count = int(groups[5])
+        fill_count = int(groups[6])
+        if inst_count != 0:
+            results[(groups[0], groups[1])] = {
+                "instructions": inst_count,
+                "spills": spill_count,
+                "fills": fill_count,
+                "cycles": cycle_count,
+                "loops": loop_count
+            }
+
+    return results
+
+
+def format_percent(frac):
+    """Converts a factional value (typically 0.0 to 1.0) to a string as a percentage"""
+    if abs(frac) > 0.0 and abs(frac) < 0.0001:
+        return "<.01%"
+    else:
+        return "{:.2f}%".format(frac * 100)
+
+
+def get_delta(b, a):
+    if b != 0 and a != 0:
+        frac = float(a) / float(b) - 1.0
+        return ' ({})'.format(format_percent(frac))
+    else:
+        return ''
+
+
+def change(b, a):
+    return str(b) + " -> " + str(a) + get_delta(b, a)
+
+
+def get_result_string(p, b, a):
+    p = p + ": "
+    while len(p) < 50:
+        p = p + ' '
+    return p + change(b, a)
+
+def split_list(string):
+    return string.split(",")
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--measurements", "-m", type=split_list,
+                        default=["instructions", "cycles", "loops", "spills", "fills"],
+                        help="comma-separated list of measurements to report")
+    parser.add_argument("--summary-only", "-s", action="store_true", default=False,
+                        help="do not show the per-shader helped / hurt data")
+    parser.add_argument("--changes-only", "-c", action="store_true", default=False,
+                        help="only show measurements that have changes")
+    parser.add_argument("before", type=get_results, help="the output of the original code")
+    parser.add_argument("after", type=get_results, help="the output of the new code")
+    args = parser.parse_args()
+
+    total_before = {}
+    total_after = {}
+    affected_before = {}
+    affected_after = {}
+    num_hurt = {}
+    num_helped = {}
+
+    for m in args.measurements:
+        total_before[m] = 0
+        total_after[m] = 0
+        affected_before[m] = 0
+        affected_after[m] = 0
+
+        helped = []
+        hurt = []
+        for p in args.before:
+            before_count = args.before[p][m]
+
+            if args.after.get(p) is None:
+                continue
+
+            # If the number of loops changed, then we may have unrolled some
+            # loops, in which case other measurements will be misleading.
+            if m != "loops" and args.before[p]["loops"] != args.after[p]["loops"]:
+                continue
+
+            after_count = args.after[p][m]
+
+            total_before[m] += before_count
+            total_after[m] += after_count
+
+            if before_count != after_count:
+                affected_before[m] += before_count
+                affected_after[m] += after_count
+
+                if after_count > before_count:
+                    hurt.append(p)
+                else:
+                    helped.append(p)
+
+        if not args.summary_only:
+            helped.sort(
+                key=lambda k: args.after[k][m] if args.before[k][m] == 0 else float(args.before[k][m] - args.after[k][m]) / args.before[k][m])
+            for p in helped:
+                namestr = p[0] + " " + p[1]
+                print(m + " helped:   " + get_result_string(
+                    namestr, args.before[p][m], args.after[p][m]))
+            if helped:
+                print("")
+
+            hurt.sort(
+                key=lambda k: args.after[k][m] if args.before[k][m] == 0 else float(args.after[k][m] - args.before[k][m]) / args.before[k][m])
+            for p in hurt:
+                namestr = p[0] + " " + p[1]
+                print(m + " HURT:   " + get_result_string(
+                    namestr, args.before[p][m], args.after[p][m]))
+            if hurt:
+                print("")
+
+        num_helped[m] = len(helped)
+        num_hurt[m] = len(hurt)
+
+
+    lost = []
+    gained = []
+
+    for p in args.before:
+        if args.after.get(p) is None:
+            lost.append(p[0] + " " + p[1])
+
+    for p in args.after:
+        if args.before.get(p) is None:
+            gained.append(p[0] + " " + p[1])
+
+    if not args.summary_only:
+        lost.sort()
+        for p in lost:
+            print("LOST:   " + p)
+        if lost:
+            print("")
+
+        gained.sort()
+        for p in gained:
+            print("GAINED: " + p)
+        if gained:
+            print("")
+
+    any_helped_or_hurt = False
+    for m in args.measurements:
+        if num_helped[m] > 0 or num_hurt[m] > 0:
+            any_helped_or_hurt = True
+
+        if num_helped[m] > 0 or num_hurt[m] > 0 or not args.changes_only:
+            print("total {0} in shared programs: {1}\n"
+                  "{0} in affected programs: {2}\n"
+                  "helped: {3}\n"
+                  "HURT: {4}\n".format(
+	              m,
+	              change(total_before[m], total_after[m]),
+	              change(affected_before[m], affected_after[m]),
+	              num_helped[m],
+	              num_hurt[m]))
+
+
+    if lost or gained or not args.changes_only:
+        print("LOST:   " + str(len(lost)))
+        print("GAINED: " + str(len(gained)))
+    else:
+        if not any_helped_or_hurt:
+            print("No changes.")
+
+if __name__ == "__main__":
+    main()
diff --git a/run.c b/run.c
index a962887..25b9e44 100644
--- a/run.c
+++ b/run.c
@@ -42,6 +42,13 @@
 
 #include "serialize.h"
 
+enum vendors {
+    VENDOR_AMD = 0x1002,
+    VENDOR_INTEL = 0x8086
+};
+
+enum vendors vendor;
+
 #define unlikely(x) __builtin_expect(!!(x), 0)
 
 int max_threads;
@@ -130,7 +137,7 @@ struct shader_stats
         return -1;
 
 static int
-parse_shader_stats(char *buf, struct shader_stats *stats)
+amd_parse_shader_stats(char *buf, struct shader_stats *stats)
 {
     char *line;
     char *saveptr;
@@ -179,39 +186,28 @@ is_shader_stage_valid(VkDevice device, VkPipeline pipeline,
 }
 
 static int
-get_shader_stats(VkDevice device, VkPipeline pipeline,
-                 VkShaderStageFlagBits stage,
-                 struct shader_stats *stats)
+get_shader_info(VkDevice device, VkPipeline pipeline,
+                VkShaderStageFlagBits stage,
+                char **shader_info)
 {
     VkResult result;
     size_t size;
-    char *buf;
-    int ret = 0;
 
     result = vkGetShaderInfo(device, pipeline, stage,
                              VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD, &size, NULL);
     if (unlikely(result != VK_SUCCESS))
         return -1;
 
-    buf = malloc(size);
-    if (unlikely(!buf))
+    *shader_info = malloc(size);
+    if (unlikely(!*shader_info))
         return -1;
 
     result = vkGetShaderInfo(device, pipeline, stage,
-                             VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD, &size, buf);
-    if (unlikely(result != VK_SUCCESS)) {
-        ret = -1;
-        goto fail;
-    }
-
-    if (unlikely(parse_shader_stats(buf, stats) < 0)) {
-        ret = -1;
-        goto fail;
-    }
+                             VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD, &size, *shader_info);
+    if (unlikely(result != VK_SUCCESS))
+         return -1;
 
-fail:
-    free(buf);
-    return ret;
+    return 0;
 }
 
 static const char *
@@ -229,8 +225,8 @@ get_shader_stage_name(VkShaderStageFlagBits stage)
 }
 
 static void
-print_shader_stats(const char *pipeline_name, VkShaderStageFlagBits stage,
-                   const struct shader_stats *stats)
+amd_print_shader_stats(const char *pipeline_name, VkShaderStageFlagBits stage,
+                       const struct shader_stats *stats)
 {
     pthread_mutex_lock(&printf_mutex);
     printf("%s (%s) - ", pipeline_name, get_shader_stage_name(stage));
@@ -364,18 +360,42 @@ create_pipeline(VkDevice device, const char *pipeline_name,
     for (uint32_t i = 0; i < info->stageCount; i++) {
         VkPipelineShaderStageCreateInfo *pCreateInfo = &info->pShaderStagesInfo[i];
         VkShaderStageFlagBits stage = pCreateInfo->stage;
-        struct shader_stats stats = {};
 
         if (!is_shader_stage_valid(device, pipeline, stage))
             continue;
 
-        ret = get_shader_stats(device, pipeline, stage, &stats);
+        char *shader_info = NULL;
+        ret = get_shader_info(device, pipeline, stage, &shader_info);
         if (unlikely(ret < 0)) {
-            fprintf(stderr, "Failed to get shader stats!\n");
+            fprintf(stderr, "Failed to get shader info!\n");
             goto fail;
         }
 
-        print_shader_stats(pipeline_name, stage, &stats);
+        if (vendor == VENDOR_AMD) {
+            struct shader_stats stats = {};
+            if (unlikely(amd_parse_shader_stats(shader_info, &stats) < 0)) {
+                ret = -1;
+                free(shader_info);
+                goto fail;
+            }
+            amd_print_shader_stats(pipeline_name, stage, &stats);
+        } else {
+            char *line = NULL;
+
+            pthread_mutex_lock(&printf_mutex);
+
+            line = strtok(shader_info, "\r\n");
+            while (line != NULL) {
+                printf("%s - %s\n",
+                       current_pipeline_names[omp_get_thread_num()],
+                       line);
+                line = strtok(NULL, "\r\n");
+            }
+
+            pthread_mutex_unlock(&printf_mutex);
+        }
+
+        free(shader_info);
     }
 
 fail:
@@ -508,6 +528,7 @@ int main(int argc, char **argv)
 
     VkPhysicalDeviceProperties device_properties;
     vkGetPhysicalDeviceProperties(physical_devices[0], &device_properties);
+    vendor = device_properties.vendorID;
     fprintf(stderr, "GPU: %s\n", device_properties.deviceName);
 
     /* Get queue properties. */
-- 
2.17.1



More information about the mesa-dev mailing list