summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Arceri <tarceri@itsqueeze.com>2018-06-12 14:38:38 +1000
committerTimothy Arceri <tarceri@itsqueeze.com>2018-06-13 10:27:11 +1000
commit2a34cfcb7a0d1b83ad1631dd82877eb3293a18b4 (patch)
treec2429301dbe710dd796ad22e0f265ad18b499996
parent1f4d975247e09041b73e43ab9e96db0f111d351c (diff)
vkpipeline-db: add support for anv
Acked-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
-rwxr-xr-xanv-report.py191
-rw-r--r--run.c75
2 files changed, 239 insertions, 27 deletions
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. */