...
 
Commits (10)
((prog-mode
(indent-tabs-mode . nil)
(tab-width . 4)
(c-basic-offset . 4)
(c-file-style . "k&r")
(fill-column . 78)
)
)
......@@ -26,12 +26,14 @@ LDLIBS = -lepoxy -lgbm
INTEL_STUB_CFLAGS = -g -fPIC -shared -Wall `pkg-config libdrm_intel --cflags`
INTEL_STUB_LIBS = -ldl
all: intel_stub.so run
all: intel_stub.so run fd-report
intel_stub.so: intel_stub.c
$(CC) $(INTEL_STUB_CFLAGS) $< -o $@ $(INTEL_STUB_LIBS)
run:
fd-report:
clean:
rm -f intel_stub.so run
rm -f intel_stub.so run fd-report
This diff is collapsed.
......@@ -45,7 +45,7 @@ class Stats(object):
self.dwords = 0
def record(self, name, stat):
assert name not in self.stats, name
#assert name not in self.stats, name
self.stats[name] = stat
for attr in ("half", "full", "const", "instr", "dwords"):
setattr(self, attr, getattr(self, attr) + getattr(stat, attr))
......@@ -76,7 +76,7 @@ def analyze(fname):
if i == 3:
#print(m1.group("name") + ": " + str)
m2 = RE2.match(str)
assert m2, str
#assert m2, str
stats.record(m1.group("name"), Stat(m2))
i = 0
str = None
......@@ -94,7 +94,7 @@ def main(argv):
before = analyze(argv[1])
after = analyze(argv[2])
keys = before.stats.keys()
assert after.stats.keys() == keys
#assert after.stats.keys().sort() == keys
helped = Stat()
hurt = Stat()
......
......@@ -2,6 +2,7 @@
import re
import argparse
import math
import statistics
from scipy import stats
import numpy as np
......@@ -12,28 +13,48 @@ def get_results(filename):
lines = file.read().split('\n')
results = {}
results["time"] = 0
re_match = re.compile(r"(\S+) - (\S+ \S+) shader: (\S*) inst, (\S*) loops, (\S*) cycles, (\S*):(\S*) spills:fills")
time_match = re.compile(r"Thread \S+ took (\S+) seconds")
re_match = re.compile(r"(\S+) - (.*) shader: (.*)")
for line in lines:
match = re.search(time_match, line)
if match is not None:
results["time"] = results["time"] + float(match.group(1))
continue
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
}
app = groups[0]
stage = groups[1]
stats = groups[2]
result_group = {}
for stat in stats.split(', '):
stat_split_spaces = stat.split(' ')
name = stat_split_spaces[1]
val = stat_split_spaces[0]
# Skipping "Promoted 0 constants" and "compacted..." on i965.
# We should probably change "compacted" to just a shader size
# in bytes.
if len(stat_split_spaces) != 2 :
continue
if name == "inst":
name = "instructions"
if name == "spills:fills":
(spills, fills) = val.split(':')
result_group['spills'] = int(spills)
result_group['fills'] = int(fills)
elif val.isnumeric():
result_group[name] = int(val)
results[(app, stage)] = result_group
return results
......@@ -44,6 +65,12 @@ def format_percent(frac):
else:
return "{:.2f}%".format(frac * 100)
def format_num(n):
assert n >= 0
if n - math.floor(n) < 0.01:
return str(math.floor(n))
else:
return "{:.2f}".format(n)
def get_delta(b, a):
if b != 0 and a != 0:
......@@ -54,7 +81,7 @@ def get_delta(b, a):
def change(b, a):
return str(b) + " -> " + str(a) + get_delta(b, a)
return format_num(b) + " -> " + format_num(a) + get_delta(b, a)
def get_result_string(p, b, a):
......@@ -104,10 +131,17 @@ def main():
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")
parser.add_argument("before", help="the output of the original code")
parser.add_argument("after", help="the output of the new code")
args = parser.parse_args()
before = get_results(args.before);
after = get_results(args.after);
# Grab these and remove them from the dictionary
time_before = before.pop("time")
time_after = after.pop("time")
total_before = {}
total_after = {}
affected_before = {}
......@@ -126,18 +160,18 @@ def main():
helped = []
hurt = []
for p in args.before:
before_count = args.before[p][m]
for p in before:
before_count = before[p][m]
if args.after.get(p) is None:
if 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"]:
if m != "loops" and before[p]["loops"] != after[p]["loops"]:
continue
after_count = args.after[p][m]
after_count = after[p][m]
total_before[m] += before_count
total_after[m] += after_count
......@@ -146,32 +180,34 @@ def main():
affected_before[m] += before_count
affected_after[m] += after_count
if after_count > before_count:
higher_is_better = m == "threads"
if (after_count > before_count) ^ higher_is_better:
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])
key=lambda k: after[k][m] if before[k][m] == 0 else float(before[k][m] - after[k][m]) / 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]))
namestr, before[p][m], 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])
key=lambda k: after[k][m] if before[k][m] == 0 else float(after[k][m] - before[k][m]) / 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]))
namestr, before[p][m], after[p][m]))
if hurt:
print("")
helped_statistics[m] = gather_statistics(helped, args.before, args.after, m)
hurt_statistics[m] = gather_statistics(hurt, args.before, args.after, m)
helped_statistics[m] = gather_statistics(helped, before, after, m)
hurt_statistics[m] = gather_statistics(hurt, before, after, m)
num_helped[m] = len(helped)
num_hurt[m] = len(hurt)
......@@ -181,20 +217,20 @@ def main():
continue
if num_hurt[m] + num_helped[m] > 3:
A = [args.after[p][m] - args.before[p][m] for p in helped + hurt]
B = [0 if args.before[p][m] == 0 else (args.after[p][m] - args.before[p][m]) / args.before[p][m] for p in helped + hurt]
A = [after[p][m] - before[p][m] for p in helped + hurt]
B = [0 if before[p][m] == 0 else (after[p][m] - before[p][m]) / before[p][m] for p in helped + hurt]
confidence_interval[m] = (mean_confidence_interval(A), mean_confidence_interval(B))
lost = []
gained = []
for p in args.before:
if args.after.get(p) is None:
for p in before:
if after.get(p) is None:
lost.append(p[0] + " " + p[1])
for p in args.after:
if args.before.get(p) is None:
for p in after:
if before.get(p) is None:
gained.append(p[0] + " " + p[1])
if not args.summary_only:
......@@ -286,5 +322,8 @@ def main():
if not any_helped_or_hurt:
print("No changes.")
print("")
print("Total CPU time (seconds): " + change(time_before, time_after))
if __name__ == "__main__":
main()
......@@ -582,6 +582,7 @@ main(int argc, char **argv)
addenv("ST_DEBUG", "precompile");
addenv("R600_DEBUG", "precompile");
addenv("FD_MESA_DEBUG", "shaderdb");
addenv("V3D_DEBUG", "precompile");
const char *client_extensions = eglQueryString(EGL_NO_DISPLAY,
EGL_EXTENSIONS);
......@@ -839,7 +840,7 @@ main(int argc, char **argv)
enum shader_type type;
unsigned num_shaders;
bool use_separate_shader_objects;
struct binding_list *binding;
struct binding_list *binding = NULL;
struct shader *shader = get_shaders(&core, &compat, &es,
text, shader_test[i].filesize,
&type, &num_shaders,
......