From 786058aacbe0ca662e14ea5f00f1c0872a599577 Mon Sep 17 00:00:00 2001
From: Tom Rondeau <trondeau@vt.edu>
Date: Tue, 7 Feb 2012 18:32:09 -0500
Subject: volk: adding an examples directory with scripts to benchmark and
 compare volk-optimized GR blocks.

---
 .../python/volk_benchmark/volk_math.py             | 146 ++++++++++++++++++
 .../python/volk_benchmark/volk_plot.py             |  81 ++++++++++
 .../python/volk_benchmark/volk_test_funcs.py       | 171 +++++++++++++++++++++
 3 files changed, 398 insertions(+)
 create mode 100755 gnuradio-examples/python/volk_benchmark/volk_math.py
 create mode 100755 gnuradio-examples/python/volk_benchmark/volk_plot.py
 create mode 100644 gnuradio-examples/python/volk_benchmark/volk_test_funcs.py

(limited to 'gnuradio-examples/python')

diff --git a/gnuradio-examples/python/volk_benchmark/volk_math.py b/gnuradio-examples/python/volk_benchmark/volk_math.py
new file mode 100755
index 0000000000..ec85ce0ada
--- /dev/null
+++ b/gnuradio-examples/python/volk_benchmark/volk_math.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python
+
+from gnuradio import gr
+import argparse
+from volk_test_funcs import *
+
+def multiply_const_cc(N):
+    k = 3.3
+    op = gr.multiply_const_cc(k)
+    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 1, 1)
+    return tb
+
+######################################################################
+
+def multiply_const_ff(N):
+    k = 3.3
+    op = gr.multiply_const_ff(k)
+    tb = helper(N, op, gr.sizeof_float, gr.sizeof_float, 1, 1)
+    return tb
+
+######################################################################
+
+def multiply_cc(N):
+    op = gr.multiply_cc()
+    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 2, 1)
+    return tb
+
+######################################################################
+
+def multiply_ff(N):
+    op = gr.multiply_ff()
+    tb = helper(N, op, gr.sizeof_float, gr.sizeof_float, 2, 1)
+    return tb
+
+######################################################################
+
+def add_ff(N):
+    op = gr.add_ff()
+    tb = helper(N, op, gr.sizeof_float, gr.sizeof_float, 2, 1)
+    return tb
+
+######################################################################
+
+def conjugate_cc(N):
+    op = gr.conjugate_cc()
+    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 1, 1)
+    return tb
+
+######################################################################
+
+def multiply_conjugate_cc_volk(N):
+    op = gr.multiply_conjugate_cc()
+    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 2, 1)
+    return tb
+
+def multiply_conjugate_cc_nonvolk(N):
+    class s(gr.hier_block2):
+        def __init__(self):
+            gr.hier_block2.__init__(self, "s",
+                                    gr.io_signature(2, 2, gr.sizeof_gr_complex),
+                                    gr.io_signature(1, 1, gr.sizeof_gr_complex))
+            conj = gr.conjugate_cc()
+            mult = gr.multiply_cc()
+            self.connect((self,0), (mult,0))
+            self.connect((self,1), conj, (mult,1))
+            self.connect(mult, self)
+
+    op = s()
+    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 2, 1)
+    return tb
+
+#multiply_conjugate_cc = multiply_conjugate_cc_volk
+multiply_conjugate_cc = multiply_conjugate_cc_nonvolk
+
+######################################################################
+
+def run_tests(func, N, iters):
+    print("Running Test: {0}".format(func.__name__))
+    tb = func(N)
+    t = timeit(tb, iters)
+    res = format_results(func.__name__, t)
+    return res
+
+def main():
+    avail_tests = [multiply_const_cc,
+                   multiply_const_ff,
+                   multiply_cc,
+                   multiply_ff,
+                   add_ff,
+                   conjugate_cc,
+                   multiply_conjugate_cc]
+
+    desc='Time an operation to compare with other implementations. \
+          This program runs a simple GNU Radio flowgraph to test a \
+          particular math function, mostly to compare the  \
+          Volk-optimized implementation versus a regular \
+          implementation. The results are stored to an SQLite database \
+          that can then be read by volk_plot.py to plot the differences.'
+    parser = argparse.ArgumentParser(description=desc)
+    parser.add_argument('label', type=str,
+                        default=None,
+                        help='Label of database table [default: %(default)s]')
+    parser.add_argument('-D', '--database', type=str,
+                        default="volk_results.db",
+                        help='Database file to store data in [default: %(default)s]')
+    parser.add_argument('-N', '--nitems', type=float,
+                        default=1e9,
+                        help='Number of items per iterations [default: %(default)s]')
+    parser.add_argument('-I', '--iterations', type=int,
+                        default=20,
+                        help='Number of iterations [default: %(default)s]')
+    parser.add_argument('--test', type=int,
+                        choices=xrange(len(avail_tests)),
+                        help='Test to run')
+    parser.add_argument('--list', action='store_true',
+                        help='List the available tests')
+    parser.add_argument('--all', action='store_true',
+                        help='Run all tests')
+    args = parser.parse_args()
+
+    if(args.list):
+        print "Available Tests to Run:"
+        print "\n".join(["\t{0}: {1}".format(i,f.__name__) for i,f in enumerate(avail_tests)])
+        sys.exit(0)      
+
+    N = int(args.nitems)
+    iters = args.iterations
+    label = args.label
+
+    conn = create_connection(args.database)
+    new_table(conn, label)
+
+    if not args.all:
+        func = avail_tests[args.test]
+        res = run_tests(func, N, iters)
+        replace_results(conn, label, N, iters, res)
+    else:
+        for f in avail_tests:
+            res = run_tests(f, N, iters)
+            replace_results(conn, label, N, iters, res)
+            
+if __name__ == "__main__":
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/volk_benchmark/volk_plot.py b/gnuradio-examples/python/volk_benchmark/volk_plot.py
new file mode 100755
index 0000000000..665df5e14a
--- /dev/null
+++ b/gnuradio-examples/python/volk_benchmark/volk_plot.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+
+import sys
+import argparse
+from volk_test_funcs import *
+
+try:
+    import matplotlib
+    import matplotlib.pyplot as plt
+except ImportError:
+    sys.stderr.write("Could not import Matplotlib (http://matplotlib.sourceforge.net/)\n")
+    sys.exit(1)
+
+def main():
+    desc='Plot Volk performance results from a SQLite database. ' + \
+        'Run one of the volk tests first (e.g, volk_math.py)'
+    parser = argparse.ArgumentParser(description=desc)
+    parser.add_argument('-D', '--database', type=str,
+                        default="volk_results.db",
+                        help='Database file to read data from [default: %(default)s]')
+    args = parser.parse_args()
+    
+    # Set up global plotting properties
+    matplotlib.rcParams['figure.subplot.bottom'] = 0.2
+    matplotlib.rcParams['figure.subplot.top'] = 0.95
+    matplotlib.rcParams['ytick.labelsize'] = 16
+    matplotlib.rcParams['xtick.labelsize'] = 16
+    matplotlib.rcParams['legend.fontsize'] = 18
+    
+    # Get list of tables to compare
+    conn = create_connection(args.database)
+    tables = list_tables(conn)
+    M = len(tables)
+
+    # width of bars depends on number of comparisons
+    wdth = 0.80/M
+
+    colors = ['b', 'r', 'g', 'm', 'k']
+
+    # Set up figure for plotting
+    f0 = plt.figure(0, facecolor='w', figsize=(14,10))
+    s0 = f0.add_subplot(1,1,1)
+
+    for i,table in enumerate(tables):
+        # Get results from the next table
+        res = get_results(conn, table[0])
+    
+        xlabels = []
+        averages = []
+        variances = []
+        maxes = []
+        mins = []
+        for r in res:
+            xlabels.append(r['kernel'])
+            averages.append(r['avg'])
+            variances.append(r['var'])
+            maxes.append(r['max'])
+            mins.append(r['min'])
+
+        # makes x values for this data set placement
+        x0 = xrange(len(res))
+        x1 = [x + i*wdth for x in x0]
+
+        s0.bar(x1, averages, width=wdth,
+               #yerr=variances,
+               color=colors[i%M], label=table[0],
+               edgecolor='k', linewidth=2)
+
+    s0.legend()
+    s0.set_ylabel("Processing time (sec) [{0:G} items]".format(res[0]['nitems']),
+                  fontsize=22, fontweight='bold')
+    s0.set_xticks(x0)
+    s0.set_xticklabels(xlabels)
+    for label in s0.xaxis.get_ticklabels():
+        label.set_rotation(45)
+        label.set_fontsize(16)
+
+    plt.show()
+
+if __name__ == "__main__":
+    main()
diff --git a/gnuradio-examples/python/volk_benchmark/volk_test_funcs.py b/gnuradio-examples/python/volk_benchmark/volk_test_funcs.py
new file mode 100644
index 0000000000..4f4e4afd36
--- /dev/null
+++ b/gnuradio-examples/python/volk_benchmark/volk_test_funcs.py
@@ -0,0 +1,171 @@
+#!/usr/bin/env python
+
+from gnuradio import gr
+import math, sys, os, time
+
+try:
+    import scipy
+except ImportError:
+    sys.stderr.write("Unable to import Scipy (www.scipy.org)\n")
+    sys.exit(1)
+
+try:
+    import sqlite3
+except ImportError:
+    sys.stderr.write("Unable to import sqlite3: requires Python 2.5\n")
+    sys.exit(1)
+
+def execute(conn, cmd):
+    '''
+    Executes the command cmd to the database opened in connection conn.
+    '''
+    c = conn.cursor()
+    c.execute(cmd)
+    conn.commit()
+    c.close()
+
+def create_connection(database):
+    '''
+    Returns a connection object to the SQLite database.
+    '''
+    return sqlite3.connect(database)
+
+def new_table(conn, tablename):
+    '''
+    Create a new table for results.
+    All results are in the form: [kernel | nitems | iters | avg. time | variance | max time | min time ]
+    Each table is meant as a different setting (e.g., volk_aligned, volk_unaligned, etc.)
+    '''
+    cols = "kernel text, nitems int, iters int, avg real, var real, max real, min real"
+    cmd = "create table if not exists {0} ({1})".format(
+        tablename, cols)
+    execute(conn, cmd)
+
+def replace_results(conn, tablename, nitems, iters, res):
+    '''
+    Inserts or replaces the results 'res' dictionary values into the table.
+    This deletes all old entries of the kernel in this table.
+    '''
+    cmd = "DELETE FROM {0} where kernel='{1}'".format(tablename, res["kernel"])
+    execute(conn, cmd)
+    insert_results(conn, tablename, nitems, iters, res)
+
+def insert_results(conn, tablename, nitems, iters, res):
+    '''
+    Inserts the results dictionary values into the table.
+    '''
+    cols = "kernel, nitems, iters, avg, var, max, min"
+    cmd = "INSERT INTO {0} ({1}) VALUES ('{2}', {3}, {4}, {5}, {6}, {7}, {8})".format(
+        tablename, cols, res["kernel"], nitems, iters, 
+        res["avg"], res["var"], res["max"], res["min"])
+    execute(conn, cmd)
+
+def list_tables(conn):
+    '''
+    Returns a list of all tables in the database.
+    '''
+    cmd = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"
+    c = conn.cursor()
+    c.execute(cmd)
+    t = c.fetchall()
+    c.close()
+
+    return t
+    
+def get_results(conn, tablename):
+    '''
+    Gets all results in tablename.
+    '''
+    cmd = "SELECT * FROM {0}".format(tablename)
+    c = conn.cursor()
+    c.execute(cmd)
+    fetched = c.fetchall()
+    c.close()
+
+    res = list()
+    for f in fetched:
+        r = dict()
+        r['kernel'] = f[0]
+        r['nitems'] = f[1]
+        r['iters']  = f[2]
+        r['avg'] = f[3]
+        r['var'] = f[4]
+        r['min'] = f[5]
+        r['max'] = f[6]
+        res.append(r)
+
+    return res
+    
+
+class helper(gr.top_block):
+    '''
+    Helper function to run the tests. The parameters are:
+      N: number of items to process (int)
+      op: The GR block/hier_block to test
+      isizeof: the sizeof the input type
+      osizeof: the sizeof the output type
+      nsrcs: number of inputs to the op
+      nsnks: number of outputs of the op
+
+    This function can only handle blocks where all inputs are the same
+    datatype and all outputs are the same data type
+    '''
+    def __init__(self, N, op,
+                 isizeof=gr.sizeof_gr_complex,
+                 osizeof=gr.sizeof_gr_complex,
+                 nsrcs=1, nsnks=1):
+        gr.top_block.__init__(self, "helper")
+
+        self.op = op
+        self.srcs = []
+        self.snks = []
+        self.head = gr.head(isizeof, N)
+
+        for n in xrange(nsrcs):
+            self.srcs.append(gr.null_source(isizeof))
+
+        for n in xrange(nsnks):
+            self.snks.append(gr.null_sink(osizeof))
+
+        self.connect(self.srcs[0], self.head, (self.op,0))
+
+        for n in xrange(1, nsrcs):
+            self.connect(self.srcs[n], (self.op,n))
+
+        for n in xrange(nsnks):
+            self.connect((self.op,n), self.snks[n])
+
+def timeit(tb, iterations):
+    '''
+    Given a top block, this function times it for a number of
+    iterations and stores the time in a list that is returned.
+    '''
+    r = gr.enable_realtime_scheduling()
+    if r != gr.RT_OK:
+        print "Warning: failed to enable realtime scheduling"
+
+    times = []
+    for i in xrange(iterations):
+        start_time = time.time()
+        tb.run()
+        end_time = time.time()
+        tb.head.reset()
+
+        times.append(end_time - start_time)
+
+    return times
+
+def format_results(kernel, times):
+    '''
+    Convinience function to convert the results of the timeit function
+    into a dictionary.
+    '''
+    res = dict()
+    res["kernel"] = kernel
+    res["avg"] = scipy.mean(times)
+    res["var"] = scipy.var(times)
+    res["max"] = max(times)
+    res["min"] = min(times)
+    return res
+
+
-- 
cgit v1.2.3


From 4c048e77d0f7f78cd684534133a9312be936fcc6 Mon Sep 17 00:00:00 2001
From: Tom Rondeau <trondeau@vt.edu>
Date: Tue, 7 Feb 2012 22:18:00 -0500
Subject: volk: test commands for measuring type conversion performance.

---
 .../python/volk_benchmark/volk_types.py            | 183 +++++++++++++++++++++
 1 file changed, 183 insertions(+)
 create mode 100755 gnuradio-examples/python/volk_benchmark/volk_types.py

(limited to 'gnuradio-examples/python')

diff --git a/gnuradio-examples/python/volk_benchmark/volk_types.py b/gnuradio-examples/python/volk_benchmark/volk_types.py
new file mode 100755
index 0000000000..3dd10ae960
--- /dev/null
+++ b/gnuradio-examples/python/volk_benchmark/volk_types.py
@@ -0,0 +1,183 @@
+#!/usr/bin/env python
+
+from gnuradio import gr
+import argparse
+from volk_test_funcs import *
+
+######################################################################
+
+def float_to_char(N):
+    op = gr.float_to_char()
+    tb = helper(N, op, gr.sizeof_float, gr.sizeof_char, 1, 1)
+    return tb
+
+######################################################################
+
+def float_to_int(N):
+    op = gr.float_to_int()
+    tb = helper(N, op, gr.sizeof_float, gr.sizeof_int, 1, 1)
+    return tb
+
+######################################################################
+
+def float_to_short(N):
+    op = gr.float_to_short()
+    tb = helper(N, op, gr.sizeof_float, gr.sizeof_short, 1, 1)
+    return tb
+
+######################################################################
+
+def short_to_float(N):
+    op = gr.short_to_float()
+    tb = helper(N, op, gr.sizeof_short, gr.sizeof_float, 1, 1)
+    return tb
+
+######################################################################
+
+def short_to_char(N):
+    op = gr.short_to_char()
+    tb = helper(N, op, gr.sizeof_short, gr.sizeof_char, 1, 1)
+    return tb
+
+######################################################################
+
+def char_to_short(N):
+    op = gr.char_to_short()
+    tb = helper(N, op, gr.sizeof_char, gr.sizeof_short, 1, 1)
+    return tb
+
+######################################################################
+
+def char_to_float(N):
+    op = gr.char_to_float()
+    tb = helper(N, op, gr.sizeof_char, gr.sizeof_float, 1, 1)
+    return tb
+
+######################################################################
+
+def int_to_float(N):
+    op = gr.int_to_float()
+    tb = helper(N, op, gr.sizeof_int, gr.sizeof_float, 1, 1)
+    return tb
+
+######################################################################
+
+def complex_to_float(N):
+    op = gr.complex_to_float()
+    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 2)
+    return tb
+
+######################################################################
+
+def complex_to_real(N):
+    op = gr.complex_to_real()
+    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1)
+    return tb
+
+######################################################################
+
+def complex_to_imag(N):
+    op = gr.complex_to_imag()
+    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1)
+    return tb
+
+######################################################################
+
+def complex_to_mag(N):
+    op = gr.complex_to_mag()
+    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1)
+    return tb
+
+######################################################################
+
+def complex_to_mag_squared(N):
+    op = gr.complex_to_mag_squared()
+    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1)
+    return tb
+
+######################################################################
+
+def complex_to_arg(N):
+    op = gr.complex_to_arg()
+    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1)
+    return tb
+
+######################################################################
+
+def run_tests(func, N, iters):
+    print("Running Test: {0}".format(func.__name__))
+    tb = func(N)
+    t = timeit(tb, iters)
+    res = format_results(func.__name__, t)
+    return res
+
+def main():
+    avail_tests = [float_to_char,
+                   float_to_int,
+                   float_to_short,
+                   short_to_float,
+                   short_to_char,
+                   char_to_short,
+                   char_to_float,
+                   int_to_float,
+                   complex_to_float,
+                   complex_to_real,
+                   complex_to_imag,
+                   complex_to_mag,
+                   complex_to_mag_squared,
+                   complex_to_arg]
+
+    desc='Time an operation to compare with other implementations. \
+          This program runs a simple GNU Radio flowgraph to test a \
+          particular math function, mostly to compare the  \
+          Volk-optimized implementation versus a regular \
+          implementation. The results are stored to an SQLite database \
+          that can then be read by volk_plot.py to plot the differences.'
+    parser = argparse.ArgumentParser(description=desc)
+    parser.add_argument('label', type=str,
+                        default=None,
+                        help='Label of database table [default: %(default)s]')
+    parser.add_argument('-D', '--database', type=str,
+                        default="volk_results.db",
+                        help='Database file to store data in [default: %(default)s]')
+    parser.add_argument('-N', '--nitems', type=float,
+                        default=1e9,
+                        help='Number of items per iterations [default: %(default)s]')
+    parser.add_argument('-I', '--iterations', type=int,
+                        default=20,
+                        help='Number of iterations [default: %(default)s]')
+    parser.add_argument('--test', type=int,
+                        choices=xrange(len(avail_tests)),
+                        help='Test to run')
+    parser.add_argument('--list', action='store_true',
+                        help='List the available tests')
+    parser.add_argument('--all', action='store_true',
+                        help='Run all tests')
+    args = parser.parse_args()
+
+    if(args.list):
+        print "Available Tests to Run:"
+        print "\n".join(["\t{0}: {1}".format(i,f.__name__) for i,f in enumerate(avail_tests)])
+        sys.exit(0)      
+
+    N = int(args.nitems)
+    iters = args.iterations
+    label = args.label
+
+    conn = create_connection(args.database)
+    new_table(conn, label)
+
+    if not args.all:
+        func = avail_tests[args.test]
+        res = run_tests(func, N, iters)
+        replace_results(conn, label, N, iters, res)
+    else:
+        for f in avail_tests:
+            res = run_tests(f, N, iters)
+            replace_results(conn, label, N, iters, res)
+            
+if __name__ == "__main__":
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
-- 
cgit v1.2.3


From a9a2c632040d37562a64eb81ed7d4f136a7a774e Mon Sep 17 00:00:00 2001
From: Tom Rondeau <trondeau@vt.edu>
Date: Thu, 9 Feb 2012 20:49:44 -0500
Subject: volk: improved GR benchmark and plotting utilities.

---
 .../python/volk_benchmark/volk_math.py             | 61 ++++++++--------
 .../python/volk_benchmark/volk_plot.py             | 84 +++++++++++++++++-----
 .../python/volk_benchmark/volk_types.py            | 18 +++--
 3 files changed, 110 insertions(+), 53 deletions(-)

(limited to 'gnuradio-examples/python')

diff --git a/gnuradio-examples/python/volk_benchmark/volk_math.py b/gnuradio-examples/python/volk_benchmark/volk_math.py
index ec85ce0ada..42f3ffa4b5 100755
--- a/gnuradio-examples/python/volk_benchmark/volk_math.py
+++ b/gnuradio-examples/python/volk_benchmark/volk_math.py
@@ -48,38 +48,41 @@ def conjugate_cc(N):
 
 ######################################################################
 
-def multiply_conjugate_cc_volk(N):
-    op = gr.multiply_conjugate_cc()
-    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 2, 1)
-    return tb
-
-def multiply_conjugate_cc_nonvolk(N):
-    class s(gr.hier_block2):
-        def __init__(self):
-            gr.hier_block2.__init__(self, "s",
-                                    gr.io_signature(2, 2, gr.sizeof_gr_complex),
-                                    gr.io_signature(1, 1, gr.sizeof_gr_complex))
-            conj = gr.conjugate_cc()
-            mult = gr.multiply_cc()
-            self.connect((self,0), (mult,0))
-            self.connect((self,1), conj, (mult,1))
-            self.connect(mult, self)
-
-    op = s()
-    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 2, 1)
-    return tb
+def multiply_conjugate_cc(N):
+    try:
+        op = gr.multiply_conjugate_cc()
+        tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 2, 1)
+        return tb
+
+    except AttributeError:
+        class s(gr.hier_block2):
+            def __init__(self):
+                gr.hier_block2.__init__(self, "s",
+                                        gr.io_signature(2, 2, gr.sizeof_gr_complex),
+                                        gr.io_signature(1, 1, gr.sizeof_gr_complex))
+                conj = gr.conjugate_cc()
+                mult = gr.multiply_cc()
+                self.connect((self,0), (mult,0))
+                self.connect((self,1), conj, (mult,1))
+                self.connect(mult, self)
+
+        op = s()
+        tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 2, 1)
+        return tb
 
-#multiply_conjugate_cc = multiply_conjugate_cc_volk
-multiply_conjugate_cc = multiply_conjugate_cc_nonvolk
 
 ######################################################################
 
 def run_tests(func, N, iters):
     print("Running Test: {0}".format(func.__name__))
-    tb = func(N)
-    t = timeit(tb, iters)
-    res = format_results(func.__name__, t)
-    return res
+    try:
+        tb = func(N)
+        t = timeit(tb, iters)
+        res = format_results(func.__name__, t)
+        return res
+    except AttributeError:
+        print "\tCould not run test. Skipping."
+        return None
 
 def main():
     avail_tests = [multiply_const_cc,
@@ -133,11 +136,13 @@ def main():
     if not args.all:
         func = avail_tests[args.test]
         res = run_tests(func, N, iters)
-        replace_results(conn, label, N, iters, res)
+        if res is not None:
+            replace_results(conn, label, N, iters, res)
     else:
         for f in avail_tests:
             res = run_tests(f, N, iters)
-            replace_results(conn, label, N, iters, res)
+            if res is not None:
+                replace_results(conn, label, N, iters, res)
             
 if __name__ == "__main__":
     try:
diff --git a/gnuradio-examples/python/volk_benchmark/volk_plot.py b/gnuradio-examples/python/volk_benchmark/volk_plot.py
index 665df5e14a..d7578c5a72 100755
--- a/gnuradio-examples/python/volk_benchmark/volk_plot.py
+++ b/gnuradio-examples/python/volk_benchmark/volk_plot.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 
-import sys
+import sys, math
 import argparse
 from volk_test_funcs import *
 
@@ -16,8 +16,15 @@ def main():
         'Run one of the volk tests first (e.g, volk_math.py)'
     parser = argparse.ArgumentParser(description=desc)
     parser.add_argument('-D', '--database', type=str,
-                        default="volk_results.db",
+                        default='volk_results.db',
                         help='Database file to read data from [default: %(default)s]')
+    parser.add_argument('-E', '--errorbars',
+                        action='store_true', default=False,
+                        help='Show error bars (1 standard dev.)')
+    parser.add_argument('-P', '--plot', type=str,
+                        choices=['mean', 'min', 'max'],
+                        default='mean',
+                        help='Set the type of plot to produce [default: %(default)s]')
     args = parser.parse_args()
     
     # Set up global plotting properties
@@ -35,42 +42,81 @@ def main():
     # width of bars depends on number of comparisons
     wdth = 0.80/M
 
+    # Colors to distinguish each table in the bar graph
+    # More than 5 tables will wrap around to the start.
     colors = ['b', 'r', 'g', 'm', 'k']
 
     # Set up figure for plotting
     f0 = plt.figure(0, facecolor='w', figsize=(14,10))
     s0 = f0.add_subplot(1,1,1)
 
+    # Create a register of names that exist in all tables
+    tmp_regs = []
+    for table in tables:
+        # Get results from the next table
+        res = get_results(conn, table[0])
+
+        tmp_regs.append(list())
+        for r in res:
+            try:
+                tmp_regs[-1].index(r['kernel'])
+            except ValueError:
+                tmp_regs[-1].append(r['kernel'])
+
+    # Get only those names that are common in all tables            
+    name_reg = tmp_regs[0]
+    for t in tmp_regs[1:]:
+        name_reg = list(set(name_reg) & set(t))
+    name_reg.sort()
+
+    # Pull the data out for each table into a dictionary
+    # we can ref the table by it's name and the data associated
+    # with a given kernel in name_reg by it's name.
+    # This ensures there is no sorting issue with the data in the
+    # dictionary, so the kernels are plotted against each other.
+    table_data = dict()
     for i,table in enumerate(tables):
         # Get results from the next table
         res = get_results(conn, table[0])
-    
-        xlabels = []
-        averages = []
-        variances = []
-        maxes = []
-        mins = []
+
+        data = dict()
         for r in res:
-            xlabels.append(r['kernel'])
-            averages.append(r['avg'])
-            variances.append(r['var'])
-            maxes.append(r['max'])
-            mins.append(r['min'])
+            data[r['kernel']] = r
+
+        table_data[table[0]] = data
 
+    # Plot the results
+    x0 = xrange(len(name_reg))
+    for i,t in enumerate(table_data):
         # makes x values for this data set placement
-        x0 = xrange(len(res))
         x1 = [x + i*wdth for x in x0]
 
-        s0.bar(x1, averages, width=wdth,
-               #yerr=variances,
-               color=colors[i%M], label=table[0],
-               edgecolor='k', linewidth=2)
+        ydata = []
+        stds = []
+        for name in name_reg:
+            stds.append(math.sqrt(table_data[t][name]['var']))
+            if(args.plot == 'max'):
+                ydata.append(table_data[t][name]['max'])
+            elif(args.plot == 'min'):
+                ydata.append(table_data[t][name]['min'])
+            if(args.plot == 'mean'):
+                ydata.append(table_data[t][name]['avg'])
+
+        if(args.errorbars is False):
+            stds = None
+
+        s0.bar(x1, ydata, width=wdth,
+               yerr=stds,
+               color=colors[i%M], label=t,
+               edgecolor='k', linewidth=2,
+               error_kw={"ecolor": 'k', "capsize":5,
+                         "linewidth":2})
 
     s0.legend()
     s0.set_ylabel("Processing time (sec) [{0:G} items]".format(res[0]['nitems']),
                   fontsize=22, fontweight='bold')
     s0.set_xticks(x0)
-    s0.set_xticklabels(xlabels)
+    s0.set_xticklabels(name_reg)
     for label in s0.xaxis.get_ticklabels():
         label.set_rotation(45)
         label.set_fontsize(16)
diff --git a/gnuradio-examples/python/volk_benchmark/volk_types.py b/gnuradio-examples/python/volk_benchmark/volk_types.py
index 3dd10ae960..8041ccac1b 100755
--- a/gnuradio-examples/python/volk_benchmark/volk_types.py
+++ b/gnuradio-examples/python/volk_benchmark/volk_types.py
@@ -106,10 +106,14 @@ def complex_to_arg(N):
 
 def run_tests(func, N, iters):
     print("Running Test: {0}".format(func.__name__))
-    tb = func(N)
-    t = timeit(tb, iters)
-    res = format_results(func.__name__, t)
-    return res
+    try:
+        tb = func(N)
+        t = timeit(tb, iters)
+        res = format_results(func.__name__, t)
+        return res
+    except AttributeError:
+        print "\tCould not run test. Skipping."
+        return None
 
 def main():
     avail_tests = [float_to_char,
@@ -170,11 +174,13 @@ def main():
     if not args.all:
         func = avail_tests[args.test]
         res = run_tests(func, N, iters)
-        replace_results(conn, label, N, iters, res)
+        if res is not None:
+            replace_results(conn, label, N, iters, res)
     else:
         for f in avail_tests:
             res = run_tests(f, N, iters)
-            replace_results(conn, label, N, iters, res)
+            if res is not None:
+                replace_results(conn, label, N, iters, res)
             
 if __name__ == "__main__":
     try:
-- 
cgit v1.2.3


From 84cb8f63d0d96ede1a6a10940112ae5a087029fc Mon Sep 17 00:00:00 2001
From: Tom Rondeau <trondeau@vt.edu>
Date: Thu, 9 Feb 2012 23:23:36 -0500
Subject: volk: better args for benchmarking volk tests; can specify a list of
 test numbers.

---
 .../python/volk_benchmark/volk_math.py             |  9 ++++----
 .../python/volk_benchmark/volk_types.py            | 24 +++++++++++-----------
 2 files changed, 17 insertions(+), 16 deletions(-)

(limited to 'gnuradio-examples/python')

diff --git a/gnuradio-examples/python/volk_benchmark/volk_math.py b/gnuradio-examples/python/volk_benchmark/volk_math.py
index 42f3ffa4b5..8b00813872 100755
--- a/gnuradio-examples/python/volk_benchmark/volk_math.py
+++ b/gnuradio-examples/python/volk_benchmark/volk_math.py
@@ -100,8 +100,8 @@ def main():
           implementation. The results are stored to an SQLite database \
           that can then be read by volk_plot.py to plot the differences.'
     parser = argparse.ArgumentParser(description=desc)
-    parser.add_argument('label', type=str,
-                        default=None,
+    parser.add_argument('-L', '--label', type=str,
+                        required=True, default=None,
                         help='Label of database table [default: %(default)s]')
     parser.add_argument('-D', '--database', type=str,
                         default="volk_results.db",
@@ -112,9 +112,10 @@ def main():
     parser.add_argument('-I', '--iterations', type=int,
                         default=20,
                         help='Number of iterations [default: %(default)s]')
-    parser.add_argument('--test', type=int,
+    parser.add_argument('--tests', type=int, nargs='*',
                         choices=xrange(len(avail_tests)),
-                        help='Test to run')
+                        help='A list of tests to run; can be a single test or a \
+                              space-separated list.')
     parser.add_argument('--list', action='store_true',
                         help='List the available tests')
     parser.add_argument('--all', action='store_true',
diff --git a/gnuradio-examples/python/volk_benchmark/volk_types.py b/gnuradio-examples/python/volk_benchmark/volk_types.py
index 8041ccac1b..893318dddc 100755
--- a/gnuradio-examples/python/volk_benchmark/volk_types.py
+++ b/gnuradio-examples/python/volk_benchmark/volk_types.py
@@ -138,8 +138,8 @@ def main():
           implementation. The results are stored to an SQLite database \
           that can then be read by volk_plot.py to plot the differences.'
     parser = argparse.ArgumentParser(description=desc)
-    parser.add_argument('label', type=str,
-                        default=None,
+    parser.add_argument('-L', '--label', type=str,
+                        required=True, default=None,
                         help='Label of database table [default: %(default)s]')
     parser.add_argument('-D', '--database', type=str,
                         default="volk_results.db",
@@ -150,9 +150,10 @@ def main():
     parser.add_argument('-I', '--iterations', type=int,
                         default=20,
                         help='Number of iterations [default: %(default)s]')
-    parser.add_argument('--test', type=int,
+    parser.add_argument('--tests', type=int, nargs='*',
                         choices=xrange(len(avail_tests)),
-                        help='Test to run')
+                        help='A list of tests to run; can be a single test or a \
+                              space-separated list.')
     parser.add_argument('--list', action='store_true',
                         help='List the available tests')
     parser.add_argument('--all', action='store_true',
@@ -171,16 +172,15 @@ def main():
     conn = create_connection(args.database)
     new_table(conn, label)
 
-    if not args.all:
-        func = avail_tests[args.test]
-        res = run_tests(func, N, iters)
+    if args.all:
+        tests = xrange(len(avail_tests))
+    else:
+        tests = args.tests
+
+    for test in tests:
+        res = run_tests(avail_tests[test], N, iters)
         if res is not None:
             replace_results(conn, label, N, iters, res)
-    else:
-        for f in avail_tests:
-            res = run_tests(f, N, iters)
-            if res is not None:
-                replace_results(conn, label, N, iters, res)
             
 if __name__ == "__main__":
     try:
-- 
cgit v1.2.3


From ca8889bc5d83bf380832431ebb30c88ddef5a924 Mon Sep 17 00:00:00 2001
From: Tom Rondeau <trondeau@vt.edu>
Date: Mon, 13 Feb 2012 14:47:42 -0500
Subject: volk: better handling of plot for error bars. Older versions of pylab
 don't like the kwargs.

---
 gnuradio-examples/python/volk_benchmark/volk_plot.py | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

(limited to 'gnuradio-examples/python')

diff --git a/gnuradio-examples/python/volk_benchmark/volk_plot.py b/gnuradio-examples/python/volk_benchmark/volk_plot.py
index d7578c5a72..562d4f2f75 100755
--- a/gnuradio-examples/python/volk_benchmark/volk_plot.py
+++ b/gnuradio-examples/python/volk_benchmark/volk_plot.py
@@ -103,14 +103,16 @@ def main():
                 ydata.append(table_data[t][name]['avg'])
 
         if(args.errorbars is False):
-            stds = None
-
-        s0.bar(x1, ydata, width=wdth,
-               yerr=stds,
-               color=colors[i%M], label=t,
-               edgecolor='k', linewidth=2,
-               error_kw={"ecolor": 'k', "capsize":5,
-                         "linewidth":2})
+            s0.bar(x1, ydata, width=wdth,
+                   color=colors[i%M], label=t,
+                   edgecolor='k', linewidth=2)
+        else:
+            s0.bar(x1, ydata, width=wdth,
+                   yerr=stds,
+                   color=colors[i%M], label=t,
+                   edgecolor='k', linewidth=2,
+                   error_kw={"ecolor": 'k', "capsize":5,
+                             "linewidth":2})
 
     s0.legend()
     s0.set_ylabel("Processing time (sec) [{0:G} items]".format(res[0]['nitems']),
-- 
cgit v1.2.3


From e36d6f1f766e702d147ca494e21131cc66f157dd Mon Sep 17 00:00:00 2001
From: Tom Rondeau <trondeau@vt.edu>
Date: Mon, 13 Feb 2012 16:10:14 -0500
Subject: volk: can specify a table to calculate the percent improvement
 against instead of just the raw numbers.

---
 .../python/volk_benchmark/volk_plot.py             | 80 ++++++++++++++++------
 1 file changed, 60 insertions(+), 20 deletions(-)

(limited to 'gnuradio-examples/python')

diff --git a/gnuradio-examples/python/volk_benchmark/volk_plot.py b/gnuradio-examples/python/volk_benchmark/volk_plot.py
index 562d4f2f75..823dfbf641 100755
--- a/gnuradio-examples/python/volk_benchmark/volk_plot.py
+++ b/gnuradio-examples/python/volk_benchmark/volk_plot.py
@@ -25,11 +25,15 @@ def main():
                         choices=['mean', 'min', 'max'],
                         default='mean',
                         help='Set the type of plot to produce [default: %(default)s]')
+    parser.add_argument('-%', '--percent', type=str,
+                        default=None, metavar="table",
+                        help='Show percent difference to the given type [default: %(default)s]')
     args = parser.parse_args()
     
     # Set up global plotting properties
     matplotlib.rcParams['figure.subplot.bottom'] = 0.2
     matplotlib.rcParams['figure.subplot.top'] = 0.95
+    matplotlib.rcParams['figure.subplot.right'] = 0.98
     matplotlib.rcParams['ytick.labelsize'] = 16
     matplotlib.rcParams['xtick.labelsize'] = 16
     matplotlib.rcParams['legend.fontsize'] = 18
@@ -39,9 +43,6 @@ def main():
     tables = list_tables(conn)
     M = len(tables)
 
-    # width of bars depends on number of comparisons
-    wdth = 0.80/M
-
     # Colors to distinguish each table in the bar graph
     # More than 5 tables will wrap around to the start.
     colors = ['b', 'r', 'g', 'm', 'k']
@@ -85,12 +86,23 @@ def main():
 
         table_data[table[0]] = data
 
+    if args.percent is not None:
+        for i,t in enumerate(table_data):
+            if args.percent == t:
+                norm_data = []
+                for name in name_reg:
+                    if(args.plot == 'max'):
+                        norm_data.append(table_data[t][name]['max'])
+                    elif(args.plot == 'min'):
+                        norm_data.append(table_data[t][name]['min'])
+                    elif(args.plot == 'mean'):
+                        norm_data.append(table_data[t][name]['avg'])
+        
+
     # Plot the results
     x0 = xrange(len(name_reg))
-    for i,t in enumerate(table_data):
-        # makes x values for this data set placement
-        x1 = [x + i*wdth for x in x0]
-
+    i = 0
+    for t in (table_data):
         ydata = []
         stds = []
         for name in name_reg:
@@ -99,24 +111,52 @@ def main():
                 ydata.append(table_data[t][name]['max'])
             elif(args.plot == 'min'):
                 ydata.append(table_data[t][name]['min'])
-            if(args.plot == 'mean'):
+            elif(args.plot == 'mean'):
                 ydata.append(table_data[t][name]['avg'])
 
-        if(args.errorbars is False):
-            s0.bar(x1, ydata, width=wdth,
-                   color=colors[i%M], label=t,
-                   edgecolor='k', linewidth=2)
+        if args.percent is not None:
+            ydata = [-100*(y-n)/y for y,n in zip(ydata,norm_data)]
+            if(args.percent != t):
+                # makes x values for this data set placement
+                # width of bars depends on number of comparisons
+                wdth = 0.80/(M-1)
+                x1 = [x + i*wdth for x in x0]
+                i += 1
+
+                s0.bar(x1, ydata, width=wdth,
+                       color=colors[(i-1)%M], label=t,
+                       edgecolor='k', linewidth=2)
+
         else:
-            s0.bar(x1, ydata, width=wdth,
-                   yerr=stds,
-                   color=colors[i%M], label=t,
-                   edgecolor='k', linewidth=2,
-                   error_kw={"ecolor": 'k', "capsize":5,
-                             "linewidth":2})
+            # makes x values for this data set placement
+            # width of bars depends on number of comparisons
+            wdth = 0.80/M
+            x1 = [x + i*wdth for x in x0]
+            i += 1
+
+            if(args.errorbars is False):
+                s0.bar(x1, ydata, width=wdth,
+                       color=colors[(i-1)%M], label=t,
+                       edgecolor='k', linewidth=2)
+            else:
+                s0.bar(x1, ydata, width=wdth,
+                       yerr=stds,
+                       color=colors[i%M], label=t,
+                       edgecolor='k', linewidth=2,
+                       error_kw={"ecolor": 'k', "capsize":5,
+                                 "linewidth":2})
+
+    nitems = res[0]['nitems']
+    if args.percent is None:
+        s0.set_ylabel("Processing time (sec) [{0:G} items]".format(nitems),
+                      fontsize=22, fontweight='bold',
+                      horizontalalignment='center')
+    else:
+        s0.set_ylabel("% Improvement over {0} [{1:G} items]".format(
+                args.percent, nitems),
+                      fontsize=22, fontweight='bold')
 
     s0.legend()
-    s0.set_ylabel("Processing time (sec) [{0:G} items]".format(res[0]['nitems']),
-                  fontsize=22, fontweight='bold')
     s0.set_xticks(x0)
     s0.set_xticklabels(name_reg)
     for label in s0.xaxis.get_ticklabels():
-- 
cgit v1.2.3


From ef1748e4efc40cc065fb5f1b40d710256dd37efa Mon Sep 17 00:00:00 2001
From: Tom Rondeau <trondeau@vt.edu>
Date: Mon, 13 Feb 2012 20:53:51 -0500
Subject: volk: complex_to_arg doesn't actually use Volk. No need to benchmark
 it.

---
 gnuradio-examples/python/volk_benchmark/volk_types.py | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

(limited to 'gnuradio-examples/python')

diff --git a/gnuradio-examples/python/volk_benchmark/volk_types.py b/gnuradio-examples/python/volk_benchmark/volk_types.py
index 893318dddc..3bc5a22aec 100755
--- a/gnuradio-examples/python/volk_benchmark/volk_types.py
+++ b/gnuradio-examples/python/volk_benchmark/volk_types.py
@@ -97,12 +97,6 @@ def complex_to_mag_squared(N):
 
 ######################################################################
 
-def complex_to_arg(N):
-    op = gr.complex_to_arg()
-    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1)
-    return tb
-
-######################################################################
 
 def run_tests(func, N, iters):
     print("Running Test: {0}".format(func.__name__))
@@ -128,8 +122,7 @@ def main():
                    complex_to_real,
                    complex_to_imag,
                    complex_to_mag,
-                   complex_to_mag_squared,
-                   complex_to_arg]
+                   complex_to_mag_squared]
 
     desc='Time an operation to compare with other implementations. \
           This program runs a simple GNU Radio flowgraph to test a \
-- 
cgit v1.2.3


From ba3f1a4e8d5879c91eb5c47cc7e7c3ac73b1989d Mon Sep 17 00:00:00 2001
From: Tom Rondeau <trondeau@vt.edu>
Date: Tue, 14 Feb 2012 17:20:11 -0500
Subject: volk: added README file to explain how to run the benchmark tests and
 plotting tool.

---
 gnuradio-examples/python/volk_benchmark/README | 252 +++++++++++++++++++++++++
 1 file changed, 252 insertions(+)
 create mode 100644 gnuradio-examples/python/volk_benchmark/README

(limited to 'gnuradio-examples/python')

diff --git a/gnuradio-examples/python/volk_benchmark/README b/gnuradio-examples/python/volk_benchmark/README
new file mode 100644
index 0000000000..516fc15bdd
--- /dev/null
+++ b/gnuradio-examples/python/volk_benchmark/README
@@ -0,0 +1,252 @@
+VOLK Benchmarking Scripts
+
+The Python programs in this directory are designed to help benchmark
+and compare Volk enhancements to GNU Radio. There are two kinds of
+scripts here: collecting data and displaying the data.
+
+Data collection is done by running a Volk testing script that will
+populate a SQLite database file (volk_results.db by default). The
+plotting utility provided here reads from the database files and plots
+bar graphs to compare the different installations.
+
+These benchmarks can be used to compare previous versions of GNU
+Radio to using Volk; they can be used to compare different Volk
+proto-kernels, as well, by editing the volk_config file; or they could
+be used to compare performance between different machines and/or
+processors.
+
+
+======================================================================
+Volk Profiling
+
+Before doing any kind of Volk benchmarking, it is important to run the
+volk_profile program. The profiler will build a config file for the
+best SIMD architecture for your processor. Run volk_profile that is
+installed into $PREFIX/bin. This program tests all known Volk kernels
+for each proto-kernel supported by the processor. When finished, it
+will write to $HOME/.volk/volk_config the best architecture for the
+VOLK function. This file is read when using a function to know the
+best version of the function to execute.
+
+The volk_config file contains a line for each kernel, where each line
+looks like:
+
+    volk_<KERNEL_NAME> <ARCHITECTURE>
+
+The architecture will be something like (sse, sse2, sse3, avx, neon,
+etc.), depending on your processor.
+
+
+======================================================================
+Benchmark Tests
+
+There are currently two benchmark scripts defined for collecting
+data. There is one that runs through the type conversions that have
+been converted to Volk (volk_types.py) and the other runs through the
+math operators converted to using Volk (volk_math.py).
+
+Script prototypes
+Both have the same structure for use:
+
+----------------------------------------------------------------------
+./volk_<test>.py [-h] -L LABEL [-D DATABASE] [-N NITEMS] [-I ITERATIONS]
+                    [--tests [{0,1,2,3} [{0,1,2,3} ...]]] [--list]
+                    [--all]
+
+optional arguments:
+  -h, --help            show this help message and exit
+  -L LABEL, --label LABEL
+                        Label of database table [default: None]
+  -D DATABASE, --database DATABASE
+                        Database file to store data in [default:
+                        volk_results.db]
+  -N NITEMS, --nitems NITEMS
+                        Number of items per iterations [default: 1000000000.0]
+  -I ITERATIONS, --iterations ITERATIONS
+                        Number of iterations [default: 20]
+  --tests [{0,1,2,3} [{0,1,2,3} ...]]
+                        A list of tests to run; can be a single test or a
+                        space-separated list.
+  --list                List the available tests
+  --all                 Run all tests
+----------------------------------------------------------------------
+
+To run, you specify the tests to run and a label to store along with
+the results. To find out what the available tests are, use the
+'--list' option.
+
+To specify a subset of tests, use the '--tests' with space-separated
+list of tests numbers (e.g., --tests 0 2 4 9).
+
+Use the '--all' to run all tests.
+
+The label specified is used as an identifier for the benchmarking
+currently being done. This is required as it is important in
+organizing the data in the database (each label is its own
+table). Usually, the label will specify the type of run being done,
+such as "volk_aligned" or "v3_5_1". In these cases, the "volk_aligned"
+label says that this is for a benchmarking using the GNU Radio version
+that uses the aligned scheduler and Volk calls in the work
+functions. The "v3_5_1" label is if you were benchmarking an installed
+version 3.5.1 of GNU Radio, which is pre-Volk. These will then be
+plotted against each other to see the timing differences.
+
+The 'database' option will output the results to a new database
+file. This can be useful for separating the output of different runs
+or of different benchmarks, such as the types versus the math scripts,
+say, or to distinguish results from different computers.
+
+If rerun using the same database and label, the entries in the table
+will simply be replaced by the new results.
+
+It is often useful to use the 'sqlitebrowser' program to interrogate
+the database file farther, if you are interested in the structure or
+the raw data.
+
+Other parameters of this script set the number of items to process and
+number of iterations to use when computing the benchmarking
+data. These default to 1 billion samples per iteration over 20
+iterations. Expect a default run to take a long time. Using the '-N'
+and '-I' options can be used to change the runtime of the benchmarks
+but are set high to remove problems of variance between iterations.
+
+======================================================================
+Plotting Results
+
+The volk_plot.py script reads a given database file and plots the
+results. The default behavior is to read all of the labels stored in
+the database and plot them as data sets on a bar graph. This shows the
+average time taken to process the number of items given.
+
+The options for the plotting script are:
+
+usage: volk_plot.py [-h] [-D DATABASE] [-E] [-P {mean,min,max}] [-% table]
+
+Plot Volk performance results from a SQLite database. Run one of the volk
+tests first (e.g, volk_math.py)
+
+----------------------------------------------------------------------
+optional arguments:
+  -h, --help            show this help message and exit
+  -D DATABASE, --database DATABASE
+                        Database file to read data from [default:
+                        volk_results.db]
+  -E, --errorbars       Show error bars (1 standard dev.)
+  -P {mean,min,max}, --plot {mean,min,max}
+                        Set the type of plot to produce [default: mean]
+  -% table, --percent table
+                        Show percent difference to the given type [default:
+                        None]
+----------------------------------------------------------------------
+
+This script allows you to specify the database used (-D), but will
+always read all rows from all tables from it and display them. You can
+also turn on plotting error bars (1 standard deviation the mean). Be
+careful, though, as some older versions of Matplotlib might have an
+issue with this option.
+
+The mean time is only one possible statistic that we might be
+interested in when looking at the data. It represents the average user
+experience when running a given block. On the other hand, the minimum
+runtime best represents the actual performance of a block given
+minimal OS interruptions while running. Right now, the data collected
+includes the mean, variance, min, and max over the number of
+iterations given. Using the '-P' option, you can specify the type of
+data to plot (mean, min, or max).
+
+Another useful way of looking at the data is to compare the percent
+improvement of a benchmark compared to another. This is done using the
+'-%' option with the provided table (or label) as the baseline. So if
+we were interested in comparing how much the 'volk_aligned' was over
+'v3_5_1', we would specify '-% v3_5_1' to see this. The plot would
+then only show the percent speedup observed using Volk for each of the
+blocks.
+
+
+======================================================================
+Benchmarking Walkthrough
+
+This will walk through an example of benchmarking the new Volk
+implementation versus the pre-Volk GNU Radio. It also shows how to
+look at the SIMD optimized versions versus the generic
+implementations.
+
+Since we introduced Volk in GNU Radio 3.5.2, we will use the following
+labels for our data:
+
+   1.) volk_aligned: v3.5.2 with volk_profile results in .volk/volk_config
+   2.) v3_5_2: v3.5.2 with the generic (non-SIMD) calls to Volk
+   3.) v3_5_1: an installation of GNU Radio from version v3.5.1
+
+We assume that we have installed two versions of GNU Radio.
+
+   v3.5.2 installed into /opt/gr-3_5_2
+   v3.5.1 installed into /opt/gr-3_5_1
+
+To test cases 1 and 2 above, we have to run GNU Radio from the v3.5.2
+installation, so we set the following environmental variables. Note
+that this is written for Ubuntu 11.10. These commands and directories
+may have to be changed depending on your OS and versions.
+
+    export LD_LIBRARY_PATH=/opt/gr-3_5_2/lib
+    export LD_LIBRARY_PATH=/opt/gr-3_5_2/lib/python2.7/dist-packages
+
+Now we can run the benchmark tests, so we will focus on the math
+operators:
+
+    ./volk_math.py -D volk_results_math.db --all -L volk_aligned
+
+When this finishes, the 'volk_results_math.db' will contain our
+results for this run.
+
+We next want to run the generic, non-SIMD, calls. This can be done by
+changing the Volk kernel settings in $HOME/.volk/volk_config. First,
+make a backup of this file. Then edit it and change all architecture
+calls (sse, sse2, etc.) to 'generic.' Now, Volk will only call the
+generic versions of these functions. So we rerun the benchmark with:
+
+    ./volk_math.py -D volk_results_math.db --all -L v3_5_2
+
+Notice that the only thing changed here was the label to 'v3_5_2'.
+
+Next, we want to collect data for the non-Volk version of GNU
+Radio. This is important because some internals to GNU Radio were made
+when adding support for Volk, so it is nice to know what the
+differences do to our performance. First, we set the environmental
+variables to point to the v3.5.1 installation:
+
+    export LD_LIBRARY_PATH=/opt/gr-3_5_1/lib
+    export LD_LIBRARY_PATH=/opt/gr-3_5_1/lib/python2.7/dist-packages
+
+And when we run the test, we use the same command line, but the GNU
+Radio libraries and Python files used come from v3.5.1. We also change
+the label to indicate the different version to store.
+    
+    ./volk_math.py -D volk_results_math.db --all -L v3_5_1
+
+We now have a database populated with three tables for the three
+different labels. We can plot them all together by simply running:
+
+    ./volk_plot.py -D volk_results_math.db
+
+This will show the average run times for each of the three
+configurations for all math functions tested. We might also be
+interested to see the difference in performance from the v3.5.1
+version, so we can run:
+
+    ./volk_plot.py -D volk_results_math.db -% v3_5_1
+
+That will plot both the 'volk_aligned' and 'v3_5_2' as a percentage
+improvement over v3_5_1. A positive value indicates that this version
+runs faster than the v3.5.1 version.
+
+
+----------------------------------------------------------------------
+
+Another interesting test case could be to compare results on different
+processors. So if you have different generation Intels, AMD, or
+whatever, you can simply pass the .db file around and run the Volk
+benchmark script to populate the database with different results. For
+this, you would specify a label like '-L i7_2620M' that indicates the
+processor type to uniquely ID the data.
+
-- 
cgit v1.2.3