tuneup_pre.c
/* This file is part of the gf2x library.
Copyright 2007, 2008, 2009, 2010, 2013, 2015
Richard Brent, Pierrick Gaudry, Emmanuel Thome', Paul Zimmermann
This program is free software; you can redistribute it and/or modify it
under the terms of either:
- If the archive contains a file named toom-gpl.c (not a trivial
placeholder), the GNU General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
- If the archive contains a file named toom-gpl.c which is a trivial
placeholder, 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.
This program 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 license text for more details.
You should have received a copy of the GNU General Public License as
well as the GNU Lesser General Public License along with this program;
see the files COPYING and COPYING.LIB. If not, write to the Free
Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301, USA.
*/
/* Tuning program for GF(2)[x] low-level multiplication. */
/* The environment variable GF2X_TUNE_LOWLEVEL_TIME gives the time, in
microseconds, to spend benching each function. The default is 1000000,
thus one second.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/types.h>
#include <string.h>
/* gf2x is used for checking correctness -- not otherwise */
#include "gf2x.h"
#include "timing.h"
#include "tuning_undefs_@@SIZE@@.h"
// make it somewhat realistic.
#define N (1 << 16)
#define NMASK ((N)-1)
#if @@SIZE@@ == 1
extern void gf2x_mul@@SIZE@@(unsigned long *c, unsigned long a, unsigned long b);
#else
extern void gf2x_mul@@SIZE@@(unsigned long *c, const unsigned long *a, const unsigned long *b);
#endif
int main(int argc, char *argv[])
{
unsigned long i, *c0, *c, *a, *b;
uint64_t st;
char *benchtime;
uint64_t btime = 1000000;
char * progname = "me";
if (argc >= 1) {
progname = argv[0];
}
benchtime = getenv("GF2X_TUNE_LOWLEVEL_TIME");
if (benchtime != NULL) {
btime = strtol(benchtime, (char **)NULL, 10);
if (btime < 1000 || btime > 100000000) {
fprintf(stderr, "Warning: unrealistic GF2X_TUNE_LOWLEVEL_TIME, ");
fprintf(stderr, "set back to default\n");
btime = 1000000;
}
}
a = (unsigned long *) malloc((N + @@SIZE@@) * sizeof(unsigned long));
b = (unsigned long *) malloc((N + @@SIZE@@) * sizeof(unsigned long));
c = (unsigned long *) malloc(2 * @@SIZE@@ * sizeof(unsigned long));
c0 = (unsigned long *) malloc(2 * @@SIZE@@ * sizeof(unsigned long));
for (i = 0; i < N + @@SIZE@@; i++) {
a[i] = (unsigned long) rand();
b[i] = (unsigned long) rand();
}
st = 0;
for (i = 0; i < 10 && i < N; i++) {
/* Use this one as a reference implementation */
gf2x_mul(c0, a + i, @@SIZE@@, b + i, @@SIZE@@);
st -= microseconds();
#if @@SIZE@@ == 1
gf2x_mul@@SIZE@@ (c, a[i & NMASK], b[i & NMASK]);
#else
gf2x_mul@@SIZE@@ (c, a + (i & NMASK), b + (i & NMASK));
#endif
st += microseconds();
if (memcmp(c, c0, 2 * @@SIZE@@ * sizeof(unsigned long)) != 0)
{
unsigned long i;
fprintf (stderr, "Error, computed test values do not match\n");
fprintf (stderr, "a=");
for (i = 0; i < @@SIZE@@; i++)
fprintf (stderr, "%lu ", a[i]);
fprintf (stderr, "\n");
fprintf (stderr, "b=");
for (i = 0; i < @@SIZE@@; i++)
fprintf (stderr, "%lu ", b[i]);
fprintf (stderr, "\n");
fprintf (stderr, "gf2x_mul gives:\n");
for (i = 0; i < 2 * @@SIZE@@; i++)
fprintf (stderr, "%lu ", c0[i]);
fprintf (stderr, "\n");
fprintf (stderr, "gf2x_mul@@SIZE@@ gives:\n");
for (i = 0; i < 2 * @@SIZE@@; i++)
fprintf (stderr, "%lu ", c[i]);
fprintf (stderr, "\n");
exit (255);
}
}
uint64_t m = i;
/* arrange for the measure to take at least .1 seconds */
for( ; ; ) {
st = -microseconds();
for (i = 0; i < m; i++) {
#if @@SIZE@@ == 1
gf2x_mul@@SIZE@@ (c, a[i & NMASK], b[i & NMASK]);
#else
gf2x_mul@@SIZE@@ (c, a + (i & NMASK), b + (i & NMASK));
#endif
}
st += microseconds();
if (st >= btime)
break;
m *= 3;
}
printf("%s : %1.1f ns\n", progname, (double) st / (double) m * 1.0e3);
free(c0);
free(c);
free(b);
free(a);
return 0;
}