diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2010-08-17 09:10:13 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2010-08-17 09:10:13 +0000 |
commit | c9583bdfe064e1069828e518533f7bc29a8fdddb (patch) | |
tree | 2400842d4095628b8486fbeabaf7bc7b8af4ed02 /tune/speed.c | |
parent | 50ac5b5985174201c7fa6e20496cd2b096107001 (diff) | |
download | mpfr-c9583bdfe064e1069828e518533f7bc29a8fdddb.tar.gz |
Source reorganization. In short:
* Added directories and moved related files into them:
- src for the MPFR source files (to build the library).
- doc for documentation files (except INSTALL, README...).
- tools for various tools (scripts) and mbench.
- tune for tuneup-related source files.
- other for other source files (not distributed in tarballs).
Existing directories:
- tests for the source files of the test suite (make check).
- examples for examples.
- m4 for m4 files.
* Renamed configure.in to configure.ac.
* Added/updated Makefile.am files where needed.
* Updated acinclude.m4 and configure.ac (AC_CONFIG_FILES line).
* Updated the documentation (INSTALL, README, doc/README.dev and
doc/mpfr.texi).
* Updated NEWS and TODO.
* Updated the scripts now in tools.
The following script was used:
#!/usr/bin/env zsh
svn mkdir doc other src tools tune
svn mv ${${(M)$(sed -n '/libmpfr_la_SOURCES/,/[^\]$/p' \
Makefile.am):#*.[ch]}:#get_patches.c} mparam_h.in \
round_raw_generic.c jyn_asympt.c src
svn mv mbench check_inits_clears coverage get_patches.sh mpfrlint \
nightly-test update-patchv update-version tools
svn mv bidimensional_sample.c speed.c tuneup.c tune
svn mv *.{c,h} other
svn mv FAQ.html README.dev algorithm* faq.xsl fdl.texi mpfr.texi \
update-faq doc
svn mv configure.in configure.ac
svn cp Makefile.am src/Makefile.am
svn rm replace_all
[Modifying some files, see above]
svn add doc/Makefile.am
svn add tune/Makefile.am
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@7087 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'tune/speed.c')
-rw-r--r-- | tune/speed.c | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/tune/speed.c b/tune/speed.c new file mode 100644 index 000000000..80969aedf --- /dev/null +++ b/tune/speed.c @@ -0,0 +1,283 @@ +/* Tune various threshold of MPFR + +Copyright 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +Contributed by the Arenaire and Caramel projects, INRIA. + +This file is part of the GNU MPFR Library. + +The GNU MPFR 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 3 of the License, or (at your +option) any later version. + +The GNU MPFR 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 MPFR Library; see the file COPYING.LESSER. If not, see +http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include <stdlib.h> +#include <time.h> + +#define MPFR_NEED_LONGLONG_H +#include "mpfr-impl.h" + +/* extracted from mulders.c */ +#ifdef MPFR_MULHIGH_TAB_SIZE +static short mulhigh_ktab[MPFR_MULHIGH_TAB_SIZE]; +#else +static short mulhigh_ktab[] = {MPFR_MULHIGH_TAB}; +#define MPFR_MULHIGH_TAB_SIZE \ + ((mp_size_t) (sizeof(mulhigh_ktab) / sizeof(mulhigh_ktab[0]))) +#endif + +#undef _PROTO +#define _PROTO __GMP_PROTO +#include "speed.h" + +int verbose; + +/* s->size: precision of both input and output + s->xp : Mantissa of first input + s->yp : mantissa of second input */ + +#define SPEED_MPFR_FUNC(mean_fun) do { \ + unsigned i; \ + mp_ptr wp; \ + double t; \ + mpfr_t w, x; \ + mp_size_t size; \ + MPFR_TMP_DECL (marker); \ + \ + SPEED_RESTRICT_COND (s->size >= MPFR_PREC_MIN); \ + SPEED_RESTRICT_COND (s->size <= MPFR_PREC_MAX); \ + MPFR_TMP_MARK (marker); \ + \ + size = (s->size-1)/GMP_NUMB_BITS+1; \ + s->xp[size-1] |= MPFR_LIMB_HIGHBIT; \ + MPFR_TMP_INIT1 (s->xp, x, s->size); \ + MPFR_SET_EXP (x, 0); \ + \ + MPFR_TMP_INIT (wp, w, s->size, size); \ + \ + speed_operand_src (s, s->xp, size); \ + speed_operand_dst (s, wp, size); \ + speed_cache_fill (s); \ + \ + speed_starttime (); \ + i = s->reps; \ + do \ + mean_fun (w, x, MPFR_RNDN); \ + while (--i != 0); \ + t = speed_endtime (); \ + \ + MPFR_TMP_FREE (marker); \ + return t; \ +} while (0) + +#define SPEED_MPFR_OP(mean_fun) do { \ + unsigned i; \ + mp_ptr wp; \ + double t; \ + mpfr_t w, x, y; \ + mp_size_t size; \ + MPFR_TMP_DECL (marker); \ + \ + SPEED_RESTRICT_COND (s->size >= MPFR_PREC_MIN); \ + SPEED_RESTRICT_COND (s->size <= MPFR_PREC_MAX); \ + MPFR_TMP_MARK (marker); \ + \ + size = (s->size-1)/GMP_NUMB_BITS+1; \ + s->xp[size-1] |= MPFR_LIMB_HIGHBIT; \ + MPFR_TMP_INIT1 (s->xp, x, s->size); \ + MPFR_SET_EXP (x, 0); \ + s->yp[size-1] |= MPFR_LIMB_HIGHBIT; \ + MPFR_TMP_INIT1 (s->yp, y, s->size); \ + MPFR_SET_EXP (y, 0); \ + \ + MPFR_TMP_INIT (wp, w, s->size, size); \ + \ + speed_operand_src (s, s->xp, size); \ + speed_operand_src (s, s->yp, size); \ + speed_operand_dst (s, wp, size); \ + speed_cache_fill (s); \ + \ + speed_starttime (); \ + i = s->reps; \ + do \ + mean_fun (w, x, y, MPFR_RNDN); \ + while (--i != 0); \ + t = speed_endtime (); \ + \ + MPFR_TMP_FREE (marker); \ + return t; \ +} while (0) + + +/* First we include all the functions we want to tune inside this program. + We can't use GNU MPFR library since the THRESHOLD can't vary */ + +/* Setup mpfr_mul */ +mpfr_prec_t mpfr_mul_threshold = MPFR_MUL_THRESHOLD; +static double speed_mpfr_mul (struct speed_params *s) { + SPEED_MPFR_OP (mpfr_mul); +} + + + +/************************************************ + * Common functions (inspired by GMP function) * + ************************************************/ +#define THRESHOLD_WINDOW 16 +#define THRESHOLD_FINAL_WINDOW 128 +static double domeasure (mpfr_prec_t *threshold, + double (*func) (struct speed_params *), + mpfr_prec_t p) +{ + struct speed_params s; + mp_size_t size; + double t; + + s.align_xp = s.align_yp = s.align_wp = 64; + s.size = p; + size = (p - 1)/GMP_NUMB_BITS+1; + s.xp = malloc (2*size*sizeof (mp_limb_t)); + if (s.xp == NULL) + { + fprintf (stderr, "Can't allocate memory.\n"); + abort (); + } + mpn_random (s.xp, size); + s.yp = s.xp + size; + mpn_random (s.yp, size); + t = speed_measure (func, &s); + if (t == -1.0) + { + fprintf (stderr, "Failed to measure function!\n"); + abort (); + } + free (s.xp); + return t; +} + +/* Tune a function with a simple THRESHOLD + The function doesn't depend on another threshold. + It assumes that it uses algo1 if p < THRESHOLD + and algo2 otherwise. + if algo2 is better for low prec, and algo1 better for high prec, + the behaviour of this function is undefined. */ +static void +tune_simple_func (mpfr_prec_t *threshold, + double (*func) (struct speed_params *), + mpfr_prec_t pstart, mpfr_prec_t pend) +{ + double measure; + mpfr_prec_t p = pstart; + mp_size_t k, n; + + while (p <= pend) + { + measure = domeasure (threshold, func, p); + printf ("prec=%lu mpfr_mul=%e ", p, measure); + n = 1 + (p - 1) / GMP_NUMB_BITS; + if (n <= MPFR_MUL_THRESHOLD) + k = MUL_FFT_THRESHOLD + 1; + else if (n < MPFR_MULHIGH_TAB_SIZE) + k = mulhigh_ktab[n]; + else + k = 2*n/3; + if (k < 0) + printf ("[mpn_mul_basecase]\n"); + else if (k == 0) + printf ("[mpfr_mulhigh_n_basecase]\n"); + else if (k > MUL_FFT_THRESHOLD) + printf ("[mpn_mul_n]\n"); + else + printf ("[mpfr_mulhigh_n]\n"); + p = p + p / 10; + } +} + +/******************************************************* + * Tune all the threshold of MPFR * + * Warning: tune the function in their dependent order!* + *******************************************************/ +static void +all (void) +{ + FILE *f = stdout; + time_t start_time, end_time; + struct tm *tp; + + speed_time_init (); + if (verbose) { + printf ("Using: %s\n", speed_time_string); + printf ("speed_precision %d", speed_precision); + if (speed_unittime == 1.0) + printf (", speed_unittime 1 cycle"); + else + printf (", speed_unittime %.2e secs", speed_unittime); + if (speed_cycletime == 1.0 || speed_cycletime == 0.0) + printf (", CPU freq unknown\n"); + else + printf (", CPU freq %.2f MHz\n\n", 1e-6/speed_cycletime); + } + + time (&start_time); + tp = localtime (&start_time); + fprintf (f, "/* Generated by MPFR's tuneup.c, %d-%02d-%02d, ", + tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday); + +#ifdef __ICC + fprintf (f, "icc %d.%d.%d */\n", __ICC / 100, __ICC / 10 % 10, __ICC % 10); +#elif defined(__GNUC__) + fprintf (f, "gcc %d.%d */\n", __GNUC__, __GNUC_MINOR__); +#elif defined (__SUNPRO_C) + fprintf (f, "Sun C %d.%d */\n", __SUNPRO_C / 0x100, __SUNPRO_C % 0x100); +#elif defined (__sgi) && defined (_COMPILER_VERSION) + fprintf (f, "MIPSpro C %d.%d.%d */\n", + _COMPILER_VERSION / 100, + _COMPILER_VERSION / 10 % 10, + _COMPILER_VERSION % 10); +#elif defined (__DECC) && defined (__DECC_VER) + fprintf (f, "DEC C %d */\n", __DECC_VER); +#else + fprintf (f, "system compiler */\n"); +#endif + fprintf (f, "\n"); + + /* Tune mpfr_mul (threshold is in limbs, but it doesn't matter too much) */ + if (verbose) + printf ("Measuring mpfr_mul with mpfr_mul_threshold=%lu...\n", + mpfr_mul_threshold); + tune_simple_func (&mpfr_mul_threshold, speed_mpfr_mul, + 2*GMP_NUMB_BITS+1, 1000); + + /* End of tuning */ + time (&end_time); + if (verbose) + printf ("Complete (took %ld seconds).\n", end_time - start_time); +} + + +/* Main function */ +int main (int argc, char *argv[]) +{ + /* Unbuffered so if output is redirected to a file it isn't lost if the + program is killed part way through. */ + setbuf (stdout, NULL); + setbuf (stderr, NULL); + + verbose = argc > 1; + + if (verbose) + printf ("Tuning MPFR (Coffee time?)...\n"); + + all (); + + return 0; +} |