This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[ping][PATCH] Allow multiple input domains to be run in the same benchmark program
- From: Siddhesh Poyarekar <siddhesh at redhat dot com>
- To: libc-alpha at sourceware dot org
- Date: Tue, 30 Apr 2013 11:21:18 +0530
- Subject: [ping][PATCH] Allow multiple input domains to be run in the same benchmark program
- References: <20130424143007 dot GH14810 at spoyarek dot pnq dot redhat dot com>
Ping!
On Wed, Apr 24, 2013 at 08:00:07PM +0530, Siddhesh Poyarekar wrote:
> Hi,
>
> 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 input file, resulting
> in separate programs.
>
> This clutters up benchtests, 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:
>
> ## name: foo
>
> tells the benchmark generation script that what follows is a different
> ddomain 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): ...
>
> I'll consolidate the documentation for using benchmarks into a README
> along with this information. The patch applies on top of the earlier
> patch to run for constant time.
>
> Siddhesh
>
> * 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.
>
>
> diff --git a/benchtests/Makefile b/benchtests/Makefile
> index 9d25d69..19e1be6 100644
> --- a/benchtests/Makefile
> +++ b/benchtests/Makefile
> @@ -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
> diff --git a/benchtests/atan-inputs b/benchtests/atan-inputs
> index c685db3..4a2cf3a 100644
> --- a/benchtests/atan-inputs
> +++ b/benchtests/atan-inputs
> @@ -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
> diff --git a/benchtests/bench-modf.c b/benchtests/bench-modf.c
> index 90a5255..7fae7dc 100644
> --- a/benchtests/bench-modf.c
> +++ b/benchtests/bench-modf.c
> @@ -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"
> diff --git a/benchtests/bench-skeleton.c b/benchtests/bench-skeleton.c
> index bbd151b..f5dba21 100644
> --- a/benchtests/bench-skeleton.c
> +++ b/benchtests/bench-skeleton.c
> @@ -30,7 +30,6 @@ 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++)
> - {
> - clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &start);
> - for (k = 0; k < iters; k++)
> - BENCH_FUNC(i);
> - clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &end);
> + /* Run for approxmately DURATION seconds. */
> + clock_gettime (CLOCK_MONOTONIC_RAW, &runtime);
> + runtime.tv_sec += DURATION;
>
> - uint64_t cur = (end.tv_nsec - start.tv_nsec
> - + ((end.tv_sec - start.tv_sec)
> - * (uint64_t) 1000000000));
> + double d_total_i = 0;
> + uint64_t total = 0, max = 0, min = 0x7fffffffffffffff;
> + while (1)
> + {
> + 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);
>
> - if (cur > max)
> - max = cur;
> + uint64_t cur = (end.tv_nsec - start.tv_nsec
> + + ((end.tv_sec - start.tv_sec)
> + * (uint64_t) 1000000000));
>
> - if (cur < min)
> - min = cur;
> + if (cur > max)
> + max = cur;
>
> - total += cur;
> + if (cur < min)
> + min = cur;
>
> - d_total_i += iters;
> - }
> + total += cur;
>
> - struct timespec curtime;
> + 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;
> - }
> + memset (&curtime, 0, sizeof (curtime));
> + clock_gettime (CLOCK_MONOTONIC_RAW, &curtime);
> + if (TIMESPEC_AFTER (curtime, runtime))
> + goto done;
> + }
>
> - double d_total_s;
> - double d_iters;
> + double d_total_s;
> + double d_iters;
>
> - done:
> - d_total_s = total * 1e-9;
> - d_iters = 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);
> + 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);
> + }
>
> return 0;
> }
> diff --git a/benchtests/cos-inputs b/benchtests/cos-inputs
> index 98f4122..82a4060 100644
> --- a/benchtests/cos-inputs
> +++ b/benchtests/cos-inputs
> @@ -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
> diff --git a/benchtests/exp-inputs b/benchtests/exp-inputs
> index d81cc07..e9d33a3 100644
> --- a/benchtests/exp-inputs
> +++ b/benchtests/exp-inputs
> @@ -1 +1,5 @@
> 42
> +# Slowest path with computation in 768 bit precision.
> +# Implemented in: sysdeps/ieee754/dbl-64/mpexp.c
> +## name: 768bits
> +708.00096423260981737257679924368858
> diff --git a/benchtests/pow-inputs b/benchtests/pow-inputs
> index 2f7cc03..dad6505 100644
> --- a/benchtests/pow-inputs
> +++ b/benchtests/pow-inputs
> @@ -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
> diff --git a/benchtests/sin-inputs b/benchtests/sin-inputs
> index 620cea8..08192d8 100644
> --- a/benchtests/sin-inputs
> +++ b/benchtests/sin-inputs
> @@ -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
> diff --git a/benchtests/slowatan-inputs b/benchtests/slowatan-inputs
> deleted file mode 100644
> index e557a3c..0000000
> --- a/benchtests/slowatan-inputs
> +++ /dev/null
> @@ -1,3 +0,0 @@
> -0x1.000000c5cba87p0
> -0x1.000001883003bp0
> -0x1.00000dfb2b675p0
> diff --git a/benchtests/slowatan.c b/benchtests/slowatan.c
> deleted file mode 100644
> index 9a11d30..0000000
> --- a/benchtests/slowatan.c
> +++ /dev/null
> @@ -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
> diff --git a/benchtests/slowcos-inputs b/benchtests/slowcos-inputs
> deleted file mode 100644
> index b7eb235..0000000
> --- a/benchtests/slowcos-inputs
> +++ /dev/null
> @@ -1,5 +0,0 @@
> -0x1.000000cf4a2a2p0
> -0x1.0000010b239a9p0
> -0x1.00000162a932bp0
> -0x1.000002d452a10p0
> -0x1.000005bc7d86dp0
> diff --git a/benchtests/slowcos.c b/benchtests/slowcos.c
> deleted file mode 100644
> index 9f56234..0000000
> --- a/benchtests/slowcos.c
> +++ /dev/null
> @@ -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
> diff --git a/benchtests/slowexp-inputs b/benchtests/slowexp-inputs
> deleted file mode 100644
> index a2086ba..0000000
> --- a/benchtests/slowexp-inputs
> +++ /dev/null
> @@ -1 +0,0 @@
> -708.00096423260981737257679924368858
> diff --git a/benchtests/slowexp.c b/benchtests/slowexp.c
> deleted file mode 100644
> index 92ac5e9..0000000
> --- a/benchtests/slowexp.c
> +++ /dev/null
> @@ -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
> diff --git a/benchtests/slowpow-inputs b/benchtests/slowpow-inputs
> deleted file mode 100644
> index dbb1270..0000000
> --- a/benchtests/slowpow-inputs
> +++ /dev/null
> @@ -1 +0,0 @@
> -1.0000000000000020, 1.5
> diff --git a/benchtests/slowpow.c b/benchtests/slowpow.c
> deleted file mode 100644
> index 08f436d..0000000
> --- a/benchtests/slowpow.c
> +++ /dev/null
> @@ -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
> diff --git a/benchtests/slowsin-inputs b/benchtests/slowsin-inputs
> deleted file mode 100644
> index 39daf80..0000000
> --- a/benchtests/slowsin-inputs
> +++ /dev/null
> @@ -1,7 +0,0 @@
> -0.93340582292648832662962377071381
> -2.3328432680770916363144351635128
> -3.7439477503636453548097051680088
> -3.9225160069792437411706487182528
> -4.0711651639931289992091478779912
> -4.7858438478542097982426639646292
> -5.9840767662578002727968851104379
> diff --git a/benchtests/slowsin.c b/benchtests/slowsin.c
> deleted file mode 100644
> index b6809bd..0000000
> --- a/benchtests/slowsin.c
> +++ /dev/null
> @@ -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
> diff --git a/benchtests/slowtan-inputs b/benchtests/slowtan-inputs
> deleted file mode 100644
> index 74a7eab..0000000
> --- a/benchtests/slowtan-inputs
> +++ /dev/null
> @@ -1 +0,0 @@
> -0x1.dffffffffff1fp-22
> diff --git a/benchtests/slowtan.c b/benchtests/slowtan.c
> deleted file mode 100644
> index 583f16f..0000000
> --- a/benchtests/slowtan.c
> +++ /dev/null
> @@ -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
> diff --git a/benchtests/tan-inputs b/benchtests/tan-inputs
> index 4369d75..629414f 100644
> --- a/benchtests/tan-inputs
> +++ b/benchtests/tan-inputs
> @@ -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
> diff --git a/scripts/bench.pl b/scripts/bench.pl
> index 5856cfa..dcc5ead 100755
> --- a/scripts/bench.pl
> +++ b/scripts/bench.pl
> @@ -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";