~linaro-toolchain-dev/cortex-strings/trunk

29 by Michael Hope
Added some scripts to run the benchmarks and to plot the results.
1
#!/usr/bin/env python
2
58 by Michael Hope
Bumped the version as we're almost at 1.0. Tidied up the README. Added an overview comment to one of the scripts.
3
"""Simple harness that benchmarks different variants of the routines,
4
caches the results, and emits all of the records at the end.
5
6
Results are generated for different values of:
7
 * Source
8
 * Routine
9
 * Length
10
 * Alignment
11
"""
12
29 by Michael Hope
Added some scripts to run the benchmarks and to plot the results.
13
import subprocess
14
import math
15
import sys
16
32 by Michael Hope
Added support for different alignments. Flattened out the loops.
17
# Prefix to the executables
29 by Michael Hope
Added some scripts to run the benchmarks and to plot the results.
18
build = '../build/try-'
19
79 by Michael Hope
Update the list of variants and routines in each. Rework how the
20
ALL = 'memchr memcmp memcpy memset strchr strcmp strcpy strlen'
32 by Michael Hope
Added support for different alignments. Flattened out the loops.
21
22
HAS = {
79 by Michael Hope
Update the list of variants and routines in each. Rework how the
23
    'this': 'bounce memchr memcpy memset strchr strcpy strlen',
104 by Will Newton
Add support for bionic-a9 and bionic-a15.
24
    'bionic-a9': 'memcmp memcpy memset strcmp strcpy strlen',
25
    'bionic-a15': 'memcmp memcpy memset strcmp strcpy strlen',
79 by Michael Hope
Update the list of variants and routines in each. Rework how the
26
    'bionic-c': ALL,
27
    'csl': 'memcpy memset',
28
    'glibc': 'memcpy memset strlen',
29
    'glibc-c': ALL,
30
    'newlib': 'memcpy strcmp strcpy strlen',
31
    'newlib-c': ALL,
32
    'newlib-xscale': 'memchr memcpy memset strchr strcmp strcpy strlen',
32 by Michael Hope
Added support for different alignments. Flattened out the loops.
33
    'plain': 'memset memcpy strcmp strcpy',
34
}
35
49 by Michael Hope
Benchmark more sizes and alignments. Make the figures bigger to make the text smaller. Put the 'this' results first.
36
def run(cache, variant, function, bytes, loops, alignment=8, quiet=False):
32 by Michael Hope
Added support for different alignments. Flattened out the loops.
37
    """Perform a single run, exercising the cache as appropriate."""
38
    key = ':'.join('%s' % x for x in (variant, function, bytes, loops, alignment))
29 by Michael Hope
Added some scripts to run the benchmarks and to plot the results.
39
40
    if key in cache:
49 by Michael Hope
Benchmark more sizes and alignments. Make the figures bigger to make the text smaller. Put the 'this' results first.
41
        got = cache[key]
29 by Michael Hope
Added some scripts to run the benchmarks and to plot the results.
42
    else:
43
        xbuild = build
32 by Michael Hope
Added support for different alignments. Flattened out the loops.
44
        cmd = '%(xbuild)s%(variant)s -t %(function)s -c %(bytes)s -l %(loops)s -a %(alignment)s' % locals()
29 by Michael Hope
Added some scripts to run the benchmarks and to plot the results.
45
30 by Michael Hope
Added more ranges. changed everything to MB/s. Account for the loop overhead.
46
        try:
47
            got = subprocess.check_output(cmd.split()).strip()
48
        except OSError, ex:
49
            assert False, 'Error %s while running %s' % (ex, cmd)
29 by Michael Hope
Added some scripts to run the benchmarks and to plot the results.
50
49 by Michael Hope
Benchmark more sizes and alignments. Make the figures bigger to make the text smaller. Put the 'this' results first.
51
    parts = got.split(':')
52
    took = float(parts[5])
53
54
    cache[key] = got
55
56
    if not quiet:
57
        print got
58
        sys.stdout.flush()
59
60
    return took
29 by Michael Hope
Added some scripts to run the benchmarks and to plot the results.
61
32 by Michael Hope
Added support for different alignments. Flattened out the loops.
62
def run_many(cache, variants, bytes, alignments):
49 by Michael Hope
Benchmark more sizes and alignments. Make the figures bigger to make the text smaller. Put the 'this' results first.
63
    # We want the data to come out in a useful order.  So fix an
64
    # alignment and function, and do all sizes for a variant first
65
    bytes = sorted(bytes)
66
    mid = bytes[len(bytes)/2]
67
68
    # Use the ordering in 'this' as the default
69
    all_functions = HAS['this'].split()
70
71
    # Find all other functions
72
    for functions in HAS.values():
73
        for function in functions.split():
74
            if function not in all_functions:
75
                all_functions.append(function)
76
77
    for alignment in alignments:
78
        for function in all_functions:
79
            for variant in variants:
80
                if function not in HAS[variant].split():
81
                    continue
82
83
                # Run a tracer through and see how long it takes and
84
                # adjust the number of loops based on that.  Not great
85
                # for memchr() and similar which are O(n), but it will
86
                # do
87
                f = 50000000
88
                want = 5.0
89
90
                loops = int(f / math.sqrt(max(1, mid)))
91
                took = run(cache, variant, function, mid, loops, alignment, quiet=True)
92
                # Keep it reasonable for silly routines like bounce
93
                factor = min(20, max(0.05, want/took))
94
                f = f * factor
95
                
96
                # Round f to a few significant figures
97
                scale = 10**int(math.log10(f) - 1)
98
                f = scale*int(f/scale)
99
32 by Michael Hope
Added support for different alignments. Flattened out the loops.
100
                for b in sorted(bytes):
101
                    # Figure out the number of loops to give a roughly consistent run
49 by Michael Hope
Benchmark more sizes and alignments. Make the figures bigger to make the text smaller. Put the 'this' results first.
102
                    loops = int(f / math.sqrt(max(1, b)))
32 by Michael Hope
Added support for different alignments. Flattened out the loops.
103
                    run(cache, variant, function, b, loops, alignment)
29 by Michael Hope
Added some scripts to run the benchmarks and to plot the results.
104
105
def run_top(cache):
32 by Michael Hope
Added support for different alignments. Flattened out the loops.
106
    variants = sorted(HAS.keys())
107
49 by Michael Hope
Benchmark more sizes and alignments. Make the figures bigger to make the text smaller. Put the 'this' results first.
108
    # Upper limit in bytes to test to
109
    top = 512*1024
110
    # Test all powers of 2
111
    step1 = 2.0
112
    # Test intermediate powers of 1.4
113
    step2 = 1.4
114
    
115
    bytes = []
79 by Michael Hope
Update the list of variants and routines in each. Rework how the
116
    
117
    for step in [step1, step2]:
118
        if step:
119
            # Figure out how many steps get us up to the top
120
            steps = int(round(math.log(top) / math.log(step)))
121
            bytes.extend([int(step**x) for x in range(0, steps+1)])
49 by Michael Hope
Benchmark more sizes and alignments. Make the figures bigger to make the text smaller. Put the 'this' results first.
122
123
    alignments = [8, 16, 4, 1, 2, 32]
32 by Michael Hope
Added support for different alignments. Flattened out the loops.
124
125
    run_many(cache, variants, bytes, alignments)
29 by Michael Hope
Added some scripts to run the benchmarks and to plot the results.
126
127
def main():
128
    cachename = 'cache.txt'
129
130
    cache = {}
131
132
    try:
133
        with open(cachename) as f:
134
            for line in f:
135
                line = line.strip()
136
                parts = line.split(':')
32 by Michael Hope
Added support for different alignments. Flattened out the loops.
137
                cache[':'.join(parts[:5])] = line
29 by Michael Hope
Added some scripts to run the benchmarks and to plot the results.
138
    except:
139
        pass
140
141
    try:
142
        run_top(cache)
143
    finally:
144
        with open(cachename, 'w') as f:
79 by Michael Hope
Update the list of variants and routines in each. Rework how the
145
            for line in sorted(cache.values()):
29 by Michael Hope
Added some scripts to run the benchmarks and to plot the results.
146
                print >> f, line
147
30 by Michael Hope
Added more ranges. changed everything to MB/s. Account for the loop overhead.
148
if __name__ == '__main__':
149
    main()