1#!/usr/bin/env python3 2 3# Copyright Hans Dembinski 2018 - 2019. 4# Distributed under the Boost Software License, Version 1.0. 5# (See accompanying file LICENSE_1_0.txt or copy at 6# https://www.boost.org/LICENSE_1_0.txt) 7 8import os 9import numpy as np 10import glob 11import re 12import json 13import sys 14from collections import defaultdict, OrderedDict 15from matplotlib.patches import Rectangle 16from matplotlib.lines import Line2D 17from matplotlib.text import Text 18from matplotlib.font_manager import FontProperties 19import matplotlib.pyplot as plt 20import matplotlib as mpl 21 22mpl.rcParams.update(mpl.rcParamsDefault) 23 24cpu_frequency = 0 25 26data = defaultdict(lambda: []) 27for fn in sys.argv[1:]: 28 d = json.load(open(fn)) 29 cpu_frequency = d["context"]["mhz_per_cpu"] 30 for bench in d["benchmarks"]: 31 name = bench["name"] 32 time = min(bench["cpu_time"], bench["real_time"]) 33 m = re.match("fill_(n_)?([0-9])d<([^>]+)>", name) 34 if m.group(1): 35 time /= 1 << 15 36 tags = m.group(3).split(", ") 37 dim = int(m.group(2)) 38 label = re.search( 39 "fill_([a-z]+)", os.path.splitext(os.path.split(fn)[1])[0] 40 ).group(1) 41 dist = tags[0] 42 if len(tags) > 1 and tags[1] in ("dynamic_tag", "static_tag"): 43 if len(tags) == 3 and "DStore" in tags[2]: 44 continue 45 label += "-" + {"dynamic_tag": "dyn", "static_tag": "sta"}[tags[1]] 46 label += "-fill" if m.group(1) else "-call" 47 data[dim].append((label, dist, time / dim)) 48 49time_per_cycle_in_ns = 1.0 / (cpu_frequency * 1e6) / 1e-9 50 51plt.figure(figsize=(7, 6)) 52i = 0 53for dim in sorted(data): 54 v = data[dim] 55 labels = OrderedDict() 56 for label, dist, time in v: 57 if label in labels: 58 labels[label][dist] = time / time_per_cycle_in_ns 59 else: 60 labels[label] = {dist: time / time_per_cycle_in_ns} 61 j = 0 62 for label, d in labels.items(): 63 t1 = d["uniform"] 64 t2 = d["normal"] 65 i -= 1 66 z = float(j) / len(labels) 67 col = (1.0 - z) * np.array((1.0, 0.0, 0.0)) + z * np.array((1.0, 1.0, 0.0)) 68 if label == "root": 69 col = "k" 70 label = "ROOT 6" 71 if "numpy" in label: 72 col = "0.6" 73 if "gsl" in label: 74 col = "0.3" 75 label = "GSL" 76 tmin = min(t1, t2) 77 tmax = max(t1, t2) 78 r1 = Rectangle((0, i), tmax, 1, facecolor=col) 79 r2 = Rectangle( 80 (tmin, i), tmax - tmin, 1, facecolor="none", edgecolor="w", hatch="//////" 81 ) 82 plt.gca().add_artist(r1) 83 plt.gca().add_artist(r2) 84 font = FontProperties(size=9) 85 tx = Text( 86 -0.5, 87 i + 0.5, 88 "%s" % label, 89 fontproperties=font, 90 va="center", 91 ha="right", 92 clip_on=False, 93 ) 94 plt.gca().add_artist(tx) 95 j += 1 96 i -= 1 97 font = FontProperties() 98 font.set_weight("bold") 99 tx = Text( 100 -0.5, 101 i + 0.6, 102 "%iD" % dim, 103 fontproperties=font, 104 va="center", 105 ha="right", 106 clip_on=False, 107 ) 108 plt.gca().add_artist(tx) 109plt.ylim(0, i) 110plt.xlim(0, 80) 111 112plt.tick_params("y", left=False, labelleft=False) 113plt.xlabel("average CPU cycles per random input value (smaller is better)") 114 115plt.tight_layout() 116 117plt.savefig("fill_performance.svg") 118plt.show() 119