]> rtime.felk.cvut.cz Git - linux-conf-perf.git/commitdiff
Update evaluation script
authorMichal Sojka <sojkam1@fel.cvut.cz>
Sun, 11 Oct 2015 22:13:29 +0000 (00:13 +0200)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Sun, 11 Oct 2015 22:13:29 +0000 (00:13 +0200)
scripts/eval2.py

index 1e627d9539aef78617a14ec03ed12304ac04ac8a..15fbf83217000c4471058a106725c590a84aa7fa 100755 (executable)
@@ -3,16 +3,21 @@ import os
 import sys
 import re
 
-
 import numpy as np
 import numpy.linalg as nplag
+import matplotlib.pyplot as plt
+import matplotlib
+
 import collections
 import psycopg2
 import psycopg2.extras
 import subprocess
 import json
+import pickle
 import utils
 
+#matplotlib.rcParams['font.size'] = 8
+matplotlib.rcParams['savefig.bbox'] = 'tight'
 
 conn = psycopg2.connect(dbname="linux-conf-perf", connection_factory=psycopg2.extras.NamedTupleConnection)
 cur = conn.cursor()
@@ -87,72 +92,176 @@ class VariableOptions(dict):
                 for k in self:
                         print("%-40s %s" % (k, self[k]))
 
-configs = {}
+def load_configs(measurements, options):
+        try:
+                configs = pickle.load(open('configs.pickle', 'rb'))
+        except:
+                configs = {}
+                for i in range(len(measurements)):
+                        config = Config(measurements[i].conf)
+                        keys = config.copy().keys()
+                        for k in keys:
+                                if not k in options:
+                                        del config[k]
+                        configs[measurements[i].conf] = config
+                pickle.dump(configs, open('configs.pickle', 'wb'))
+        return configs
 
-def construct_ab(options, measurements):
-        A = np.zeros((len(measurements), len(options) + 1))
-        B = np.zeros((len(measurements), 1))
+def construct_ab(options, measurements, configs):
+        A = np.mat(np.zeros((len(measurements), len(options) + 1)))
+        B = np.mat(np.zeros((len(measurements), 1)))
 
         for i in range(len(measurements)):
-                try:
-                        config = configs[measurements[i].conf]
-                except KeyError:
-                        config = Config(measurements[i].conf)
-                        configs[measurements[i].conf] = config
+                config = configs[measurements[i].conf]
                 A[i, len(options)] = 1
                 B[i] = measurements[i].value
                 for j in range(len(options)):
                         A[i,j] = 1 if config[options.name_by_index(j)] == 'y' else 0
         return (A, B)
 
+def plot_values(measurements, configs, measurements_est, highlight_options):
+        print(measurements_est.__class__, measurements_est.shape)
+        B = np.mat(np.zeros((len(measurements),1)))
+        for i in range(len(measurements)):
+                B[i] = measurements[i].value
+
+        idx = np.argsort(B, 0)
+        B = B[idx,0]
+        measurements = sorted(measurements, key=lambda x: x.value)
+        measurements_est = measurements_est[idx, 0]
 
-def evaluate():
-        cur.execute("SELECT conf, value FROM measure WHERE result='nominal' AND toolgit IN (1, 11);")
-        measurements = cur.fetchall()
+        plt.plot(measurements_est, 'x', color='#aaaaaa')
+        plt.hold(True)
+        plt.gcf().set_size_inches(8,4)
+        plt.plot(B, color='b')
+        plt.xlabel('Configuration')
+        plt.ylabel('cyclictest result [µs]')
+        yy = 0
+        for o in highlight_options if 0 else []:
+                yy += 1
+                x = []
+                y = []
+                for i in range(len(measurements)):
+                        if configs[measurements[i].conf][o] == 'y':
+                                x.append(i)
+                                y.append(measurements[i].value)
+                plt.plot(x, (yy*5-150)*np.ones(len(x)), '+')
+
+        plt.legend(['Model', 'Measured'] + [o[7:] for o in highlight_options], loc = 'upper left')
+        plt.grid(True)
+        plt.xlim(0,len(measurements))
+        plt.savefig('measurements.pdf')
+        #plt.show()
+
+def save_options(options):
+        json.dump(options, open('options.json', 'w'), indent='  ', sort_keys=True)
 
+def load_variable_options(measurements):
         if os.path.exists('options.json'):
             options = VariableOptions([])
             options.update(json.load(open('options.json', 'r')))
             options.update_order()
         else:
             options = VariableOptions(measurements)
-            json.dump(options, open('options.json', 'w'), indent='  ', sort_keys=True)
+            save_options(options)
         #options.print()
+        return options
 
-        (A,B) = construct_ab(options, measurements)
+def remove_linerly_dependent_options(options, measurements, configs):
+        (A,B) = construct_ab(options, measurements, configs)
         rank = nplag.matrix_rank(A)
 
+        if rank == A.shape[1]:
+                return options
+
         o = options.copy()
         for k in sorted(o.keys()):
                 del options[k]
                 options.update_order()
-                (A,B) = construct_ab(options, measurements)
+                (A,B) = construct_ab(options, measurements, configs)
                 if nplag.matrix_rank(A) != rank:
                         options[k]=None
                         options.update_order()
                 else:
                         print("Removed", k)
+        return options
+
+class OptionResult:
+        def __init__(self, option_name, regression=None, yes_count=None):
+                self.option_name = option_name
+                self.regression = regression
+                self.yes_count = int(yes_count)
+                self.measure_diff = []
+
+        def calc_measure_diff(self, A, B, options):
+                oidx = options[self.option_name]
+                for m1 in range(A.shape[0]):
+                        if A[m1,oidx] == 1:
+                                row = A[m1].copy()
+                                row[0,oidx] = 0
+                                for m2 in range(A.shape[0]):
+                                        if A[m2,oidx] == 0 and (row == A[m2]).all():
+                                                self.measure_diff.append(B[m1] - B[m2])
+                                                break
+
+def plot_bars(results):
+        y_pos = np.arange(len(results), 0, -1)
+        regr = np.array([r.regression for r in results])
+        diff = np.array([np.array(r.measure_diff).mean() for r in results])
+
+        fig, ax = plt.subplots()
+        fig.set_size_inches(8,12)
+
+        ax.set_yticks(y_pos)
+        ax.set_yticklabels([r.option_name[7:] for r in results], fontsize=12)
+        rects1 = ax.barh(y_pos, regr, height=0.35, color='b')
+        rects2 = ax.barh(y_pos+0.35, diff, height=0.35, color='w', hatch='//')
+        ax.legend(['regression', 'two measurement diff'])
+        ax.grid(True)
+        ax.set_xlabel("Config option influence [µs]")
+        plt.savefig('option_res.pdf')
+        #plt.show()
+
+def evaluate():
+        cur.execute("SELECT conf, value FROM measure WHERE result='nominal' AND toolgit IN (1, 11);")
+        measurements = cur.fetchall()
+
+        options = load_variable_options(measurements)
+        configs = load_configs(measurements, options)
 
-        (A,B) = construct_ab(options, measurements)
+        options = remove_linerly_dependent_options(options, measurements, configs)
+        save_options(options)
+
+        (A,B) = construct_ab(options, measurements, configs)
 
         #np.set_printoptions(threshold = float('nan'), linewidth = 300)
         np.set_printoptions(edgeitems = 9, linewidth = 80)
 #         print(A)
 #         print(B)
         result = nplag.lstsq(A, B)
-        print(result)
 
-        x=result[0]
+        x=np.mat(result[0])
+        try:
+                results = pickle.load(open('results.pickle', 'rb'))
+        except:
+                results = []
+                for k in options:
+                        print(k)
+                        idx = options[k]
+                        r = OptionResult(k, regression=x.item(idx), yes_count=A[:,idx].sum())
+                        r.calc_measure_diff(A, B, options)
+
+                        results.append(r)
+                results.sort(key=lambda r: r.regression)
+                pickle.dump(results, open('results.pickle', 'wb'))
 
-        results = []
-        for k in options:
-                idx = options[k]
-                results.append((k, x[idx], A[:,idx].sum(), A[:,idx].sum()/A.shape[0]*100))
-        results.sort(key=lambda r: r[1])
         for r in results:
-                print("%-40s %7.4g %8d %3d%%" % r)
-        print("%-40s %g" % ("common", x[len(options)]))
+                print("{option_name:<40} {regression:7.2f} {yes_count:4d} {percent:2}%".format(percent=10, **r.__dict__))
+        print("%-40s %6.2f" % ("common", x[len(options)]))
         print(A.shape)
 
+        plot_values(measurements, configs, A*x, [r.option_name for r in results])
+        plot_bars(results)
+
 if __name__ == '__main__':
        evaluate()