Allow multiple input domains to be run in the same benchmark program

Some math functions have distinct performance characteristics in
specific domains of inputs, where some inputs return via a fast path
while other inputs require multiple precision calculations, that too
at different precision levels.  The way to implement different domains
was to have a separate source file and benchmark definition, resulting
in separate programs.

This clutters up the benchmark, so this change allows these domains to
be consolidated into the same input file.  To do this, the input file
format is now enhanced to allow comments with a preceding # and
directives with two # at the begining of a line.  A directive that
looks like:

tells the benchmark generation script that what follows is a different
domain of inputs.  The value of the 'name' directive (in this case,
foo) is used in the output.  The two input domains are then executed
sequentially and their results collated separately.  with the above
directive, there would be two lines in the result that look like:

func(): ....
func(foo): ...
This commit is contained in:
Siddhesh Poyarekar 2013-04-30 14:17:57 +05:30
parent d569c6eeb4
commit f0ee064b7d
23 changed files with 204 additions and 231 deletions

View File

@ -1,5 +1,31 @@
2013-04-30 Siddhesh Poyarekar <siddhesh@redhat.com>
* benchtests/Makefile (bench): Remove slow benchmarks.
* benchtests/atan-inputs: Add slow benchmark inputs.
* benchtests/bench-modf.c (NUM_VARIANTS): Define.
(BENCH_FUNC): Accept variant offset.
(VARIANT): Define.
* benchtests/bench-skeleton.c (main): Run benchmark for each
variant.
* benchtests/cos-inputs: Add slow benchmark inputs.
* benchtests/exp-inputs: Likewise.
* benchtests/pow-inputs: Likewise.
* benchtests/sin-inputs: Likewise.
* benchtests/slowatan-inputs: Remove.
* benchtests/slowatan.c: Remove.
* benchtests/slowcos-inputs: Remove.
* benchtests/slowcos.c: Remove.
* benchtests/slowexp-inputs: Remove.
* benchtests/slowexp.c: Remove.
* benchtests/slowpow-inputs: Remove.
* benchtests/slowpow.c: Remove.
* benchtests/slowsin-inputs: Remove.
* benchtests/slowsin.c: Remove.
* benchtests/slowtan-inputs: Remove.
* benchtests/slowtan.c: Remove.
* benchtests/tan-inputs: Add slow benchmark inputs.
* scripts/bench.pl: Parse comments and directives.
* benchtests/Makefile: Remove *-ITER. Define BENCH_DURATION
in CPPFLAGS.
($(objpfx)bench-%.c): Remove *-ITER.

View File

@ -39,15 +39,12 @@
# See pow-inputs for an example.
subdir := benchtests
bench := exp pow rint sin cos tan atan modf \
slowexp slowpow slowsin slowcos slowtan slowatan
bench := exp pow rint sin cos tan atan modf
# exp function fast path: sysdeps/ieee754/dbl-64/e_exp.c
exp-ARGLIST = double
exp-RET = double
LDFLAGS-bench-exp = -lm
# pow function fast path: sysdeps/ieee754/dbl-64/e_pow.c
pow-ARGLIST = double:double
pow-RET = double
LDFLAGS-bench-pow = -lm
@ -56,62 +53,22 @@ rint-ARGLIST = double
rint-RET = double
LDFLAGS-bench-rint = -lm
# exp function slowest path: sysdeps/ieee754/dbl-64/mpexp.c
slowexp-ARGLIST = double
slowexp-RET = double
slowexp-INCLUDE = slowexp.c
LDFLAGS-bench-slowexp = -lm
# sin function fast path: sysdeps/ieee754/dbl-64/s_sin.c
sin-ARGLIST = double
sin-RET = double
LDFLAGS-bench-sin = -lm
# cos function fast path: sysdeps/ieee754/dbl-64/s_sin.c
cos-ARGLIST = double
cos-RET = double
LDFLAGS-bench-cos = -lm
# tan function fast path: sysdeps/ieee754/dbl-64/s_tan.c
tan-ARGLIST = double
tan-RET = double
LDFLAGS-bench-tan = -lm
# atan function fast path: sysdeps/ieee754/dbl-64/s_atan.c
atan-ARGLIST = double
atan-RET = double
LDFLAGS-bench-atan = -lm
# pow function slowest path: sysdeps/ieee754/dbl-64/slowpow.c
slowpow-ARGLIST = double:double
slowpow-RET = double
slowpow-INCLUDE = slowpow.c
LDFLAGS-bench-slowpow = -lm
# sin function slowest path: sysdeps/ieee754/dbl-64/sincos32.c
slowsin-ARGLIST = double
slowsin-RET = double
slowsin-INCLUDE = slowsin.c
LDFLAGS-bench-slowsin = -lm
# cos function slowest path: sysdeps/ieee754/dbl-64/sincos32.c
slowcos-ARGLIST = double
slowcos-RET = double
slowcos-INCLUDE = slowcos.c
LDFLAGS-bench-slowcos = -lm
# tan function slowest path: sysdeps/ieee754/dbl-64/mptan.c
slowtan-ARGLIST = double
slowtan-RET = double
slowtan-INCLUDE = slowtan.c
LDFLAGS-bench-slowtan = -lm
# atan function slowest path: sysdeps/ieee754/dbl-64/mpatan.c
slowatan-ARGLIST = double
slowatan-RET = double
slowatan-INCLUDE = slowatan.c
LDFLAGS-bench-slowatan = -lm
# Rules to build and execute the benchmarks. Do not put any benchmark

View File

@ -1,3 +1,9 @@
0x1.000000c5cba86p0
0x1.000001883003ap0
0x1.00000dfb2b674p0
# atan slowest path at 768 bits
# Implemented in sysdeps/ieee754/dbl-64/mpatan.c
## name: 768bits
0x1.000000c5cba87p0
0x1.000001883003bp0
0x1.00000dfb2b675p0

View File

@ -17,7 +17,7 @@
extern double modf (double, double *);
#define CALL_BENCH_FUNC(j, i) modf ( in[j].arg0, &i);
#define CALL_BENCH_FUNC(j, i) modf (in[j].arg0, &i);
struct args
{
@ -28,11 +28,17 @@ struct args
{ -42.42 }
};
#define NUM_SAMPLES (sizeof (in) / sizeof (struct args))
#define NUM_VARIANTS 1
#define NUM_SAMPLES(v) (sizeof (in) / sizeof (struct args))
static volatile double ret = 0.0;
#define BENCH_FUNC(j) ({double iptr; ret = CALL_BENCH_FUNC (j, iptr);})
#define BENCH_FUNC(v, j) \
({ \
double iptr; \
ret = CALL_BENCH_FUNC (j, iptr); \
})
#define FUNCNAME "modf"
#define VARIANT(v) FUNCNAME "()"
#include "bench-skeleton.c"

View File

@ -25,12 +25,11 @@
#define TIMESPEC_AFTER(a, b) \
(((a).tv_sec == (b).tv_sec) ? \
((a).tv_nsec > (b).tv_nsec) : \
((a).tv_sec > (b).tv_sec))
((a).tv_sec > (b).tv_sec))
int
main (int argc, char **argv)
{
unsigned long i, k;
uint64_t total = 0, max = 0, min = 0x7fffffffffffffff;
struct timespec start, end, runtime;
memset (&runtime, 0, sizeof (runtime));
@ -45,53 +44,57 @@ main (int argc, char **argv)
but it's better than having nothing at all. */
unsigned long iters = 1000 * start.tv_nsec;
/* Run for approxmately DURATION seconds. */
clock_gettime (CLOCK_MONOTONIC_RAW, &runtime);
runtime.tv_sec += DURATION;
double d_total_i = 0;
while (1)
for (int v = 0; v < NUM_VARIANTS; v++)
{
for (i = 0; i < NUM_SAMPLES; i++)
/* Run for approximately DURATION seconds. */
clock_gettime (CLOCK_MONOTONIC_RAW, &runtime);
runtime.tv_sec += DURATION;
double d_total_i = 0;
uint64_t total = 0, max = 0, min = 0x7fffffffffffffff;
while (1)
{
clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &start);
for (k = 0; k < iters; k++)
BENCH_FUNC(i);
clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &end);
for (i = 0; i < NUM_SAMPLES (v); i++)
{
clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &start);
for (k = 0; k < iters; k++)
BENCH_FUNC (v, i);
clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &end);
uint64_t cur = (end.tv_nsec - start.tv_nsec
+ ((end.tv_sec - start.tv_sec)
* (uint64_t) 1000000000));
uint64_t cur = (end.tv_nsec - start.tv_nsec
+ ((end.tv_sec - start.tv_sec)
* (uint64_t) 1000000000));
if (cur > max)
max = cur;
if (cur > max)
max = cur;
if (cur < min)
min = cur;
if (cur < min)
min = cur;
total += cur;
total += cur;
d_total_i += iters;
d_total_i += iters;
}
struct timespec curtime;
memset (&curtime, 0, sizeof (curtime));
clock_gettime (CLOCK_MONOTONIC_RAW, &curtime);
if (TIMESPEC_AFTER (curtime, runtime))
goto done;
}
struct timespec curtime;
double d_total_s;
double d_iters;
memset (&curtime, 0, sizeof (curtime));
clock_gettime (CLOCK_MONOTONIC_RAW, &curtime);
if (TIMESPEC_AFTER (curtime, runtime))
goto done;
done:
d_total_s = total * 1e-9;
d_iters = iters;
printf ("%s: ITERS:%g: TOTAL:%gs, MAX:%gns, MIN:%gns, %g iter/s\n",
VARIANT (v),
d_total_i, d_total_s, max / d_iters, min / d_iters,
d_total_i / d_total_s);
}
double d_total_s;
double d_iters;
done:
d_total_s = total * 1e-9;
d_iters = iters;
printf (FUNCNAME ": ITERS:%g: TOTAL:%gs, MAX:%gns, MIN:%gns, %g iter/s\n",
d_total_i, d_total_s, max / d_iters, min / d_iters,
d_total_i / d_total_s);
return 0;
}

View File

@ -3,3 +3,11 @@
0x1.00000162a932ap0
0x1.000002d452a11p0
0x1.000005bc7d86cp0
# cos slow path at 768 bits
# Implemented in sysdeps/ieee754/dbl-64/sincos32.c
## name: 768bits
0x1.000000cf4a2a2p0
0x1.0000010b239a9p0
0x1.00000162a932bp0
0x1.000002d452a10p0
0x1.000005bc7d86dp0

View File

@ -1 +1,5 @@
42
# Slowest path with computation in 768 bit precision.
# Implemented in: sysdeps/ieee754/dbl-64/mpexp.c
## name: 768bits
708.00096423260981737257679924368858

View File

@ -1 +1,5 @@
42.0, 42.0
# pow slowest path at 768 bits
# Implemented in sysdeps/ieee754/dbl-64/slowpow.c
## name: 768bits
1.0000000000000020, 1.5

View File

@ -5,3 +5,13 @@
4.0
4.7
5.9
# sin slowest path at 768 bits
# Implemented in sysdeps/ieee754/dbl-64/sincos32.c
## name: 768bits
0.93340582292648832662962377071381
2.3328432680770916363144351635128
3.7439477503636453548097051680088
3.9225160069792437411706487182528
4.0711651639931289992091478779912
4.7858438478542097982426639646292
5.9840767662578002727968851104379

View File

@ -1,3 +0,0 @@
0x1.000000c5cba87p0
0x1.000001883003bp0
0x1.00000dfb2b675p0

View File

@ -1,19 +0,0 @@
/* Define slowatan.
Copyright (C) 2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define slowatan atan

View File

@ -1,5 +0,0 @@
0x1.000000cf4a2a2p0
0x1.0000010b239a9p0
0x1.00000162a932bp0
0x1.000002d452a10p0
0x1.000005bc7d86dp0

View File

@ -1,19 +0,0 @@
/* Define slowcos.
Copyright (C) 2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define slowcos cos

View File

@ -1 +0,0 @@
708.00096423260981737257679924368858

View File

@ -1,19 +0,0 @@
/* Define slowexp.
Copyright (C) 2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define slowexp exp

View File

@ -1 +0,0 @@
1.0000000000000020, 1.5

View File

@ -1,19 +0,0 @@
/* Define slowpow.
Copyright (C) 2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define slowpow pow

View File

@ -1,7 +0,0 @@
0.93340582292648832662962377071381
2.3328432680770916363144351635128
3.7439477503636453548097051680088
3.9225160069792437411706487182528
4.0711651639931289992091478779912
4.7858438478542097982426639646292
5.9840767662578002727968851104379

View File

@ -1,19 +0,0 @@
/* Define slowsin.
Copyright (C) 2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define slowsin sin

View File

@ -1 +0,0 @@
0x1.dffffffffff1fp-22

View File

@ -1,19 +0,0 @@
/* Define slowtan.
Copyright (C) 2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define slowtan tan

View File

@ -1 +1,5 @@
0x1.dffffffffff1ep-22
# tan slowest path at 768 bits
# Implemented in sysdeps/ieee754/dbl-64/mptan.c
## name: 768bits
0x1.dffffffffff1fp-22

View File

@ -42,15 +42,28 @@ if (@ARGV == 3) {
my $decl = "extern $ret $func (";
# Function has no arguments.
if (@args == 0 || $args[0] eq "void") {
print "$decl void);\n";
print "#define CALL_BENCH_FUNC(j) $func();\n";
print "#define NUM_SAMPLES (1)\n";
print "#define CALL_BENCH_FUNC(i,j) $func();\n";
print "#define NUM_VARIANTS (1)\n";
print "#define NUM_SAMPLES(v) (1)\n";
print "#define VARIANT(v) FUNCNAME \"()\"\n"
}
# The function has arguments, so parse them and populate the inputs.
else {
my $num = 0;
my $bench_func = "#define CALL_BENCH_FUNC(j) $func (";
my $struct = "struct args {";
my $bench_func = "#define CALL_BENCH_FUNC(v, i) $func (";
my $struct =
"struct _variants
{
const char *name;
int count;
struct args *in;
};\n";
my $arg_struct = "struct args {";
foreach $arg (@args) {
if ($num > 0) {
@ -58,24 +71,87 @@ else {
$decl = "$decl,";
}
$struct = "$struct $arg arg$num;";
$bench_func = "$bench_func in[j].arg$num";
$arg_struct = "$arg_struct $arg arg$num;";
$bench_func = "$bench_func variants[v].in[i].arg$num";
$decl = "$decl $arg";
$num = $num + 1;
}
print "$decl);\n";
print "$bench_func);\n";
print "$struct } in[] = {";
$arg_struct = $arg_struct . "};\n";
$decl = $decl . ");\n";
$bench_func = $bench_func . ");\n";
# We create a hash of inputs for each variant of the test.
my $variant = "";
my @curvals;
my %vals;
open INPUTS, "<$func-inputs" or die $!;
while (<INPUTS>) {
LINE:while (<INPUTS>) {
chomp;
print "{$_},\n";
# New variant.
if (/^## (\w+): (\w+)/) {
#We only identify Name for now.
if ($1 ne "name") {
next LINE;
}
# Save values in the last variant.
my @copy = @curvals;
$vals{$variant} = \@copy;
# Prepare for the next.
$variant=$2;
undef @curvals;
next LINE;
}
# Skip over comments.
if (/^#/) {
next LINE;
}
push (@curvals, $_);
}
print "};\n";
print "#define NUM_SAMPLES (sizeof (in) / sizeof (struct args))\n"
$vals{$variant} = \@curvals;
# Print the definitions and macros.
print $decl;
print $bench_func;
print $arg_struct;
print $struct;
my $c = 0;
my $key;
# Print the input arrays.
foreach $key (keys %vals) {
my @arr = @{$vals{$key}};
print "struct args in" . $c . "[" . @arr . "] = {\n";
foreach (@arr) {
print "{$_},\n";
}
print "};\n\n";
$c += 1;
}
# The variants. Each variant then points to the appropriate input array we
# defined above.
print "struct _variants variants[" . (keys %vals) . "] = {\n";
$c = 0;
foreach $key (keys %vals) {
print "{\"$func($key)\", " . @{$vals{$key}} . ", in$c},\n";
$c += 1;
}
print "};\n\n";
# Finally, print the last set of macros.
print "#define NUM_VARIANTS $c\n";
print "#define NUM_SAMPLES(i) (variants[i].count)\n";
print "#define VARIANT(i) (variants[i].name)\n";
}
# In some cases not storing a return value seems to result in the function call
@ -85,7 +161,8 @@ if ($ret ne "void") {
$getret = "ret = ";
}
print "#define BENCH_FUNC(j) ({$getret CALL_BENCH_FUNC (j);})\n";
# And we're done.
print "#define BENCH_FUNC(i, j) ({$getret CALL_BENCH_FUNC (i, j);})\n";
print "#define FUNCNAME \"$func\"\n";
print "#include \"bench-skeleton.c\"\n";