(root)/
mpfr-4.2.1/
tune/
speed.c
       1  /* Tune various threshold of MPFR
       2  
       3  Copyright 2005-2023 Free Software Foundation, Inc.
       4  Contributed by the AriC and Caramba projects, INRIA.
       5  
       6  This file is part of the GNU MPFR Library.
       7  
       8  The GNU MPFR Library is free software; you can redistribute it and/or modify
       9  it under the terms of the GNU Lesser General Public License as published by
      10  the Free Software Foundation; either version 3 of the License, or (at your
      11  option) any later version.
      12  
      13  The GNU MPFR Library is distributed in the hope that it will be useful, but
      14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      15  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
      16  License for more details.
      17  
      18  You should have received a copy of the GNU Lesser General Public License
      19  along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
      20  https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
      21  51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
      22  
      23  #include <stdlib.h>
      24  #include <time.h>
      25  
      26  #define MPFR_NEED_LONGLONG_H
      27  #include "mpfr-impl.h"
      28  
      29  /* extracted from mulders.c */
      30  #ifdef MPFR_MULHIGH_TAB_SIZE
      31  static short mulhigh_ktab[MPFR_MULHIGH_TAB_SIZE];
      32  #else
      33  static short mulhigh_ktab[] = {MPFR_MULHIGH_TAB};
      34  #define MPFR_MULHIGH_TAB_SIZE ((mp_size_t) (numberof (mulhigh_ktab)))
      35  #endif
      36  
      37  #undef _PROTO
      38  #define _PROTO __GMP_PROTO
      39  #include "speed.h"
      40  
      41  int verbose;
      42  
      43  /* s->size: precision of both input and output
      44     s->xp  : Mantissa of first input
      45     s->yp  : mantissa of second input                    */
      46  
      47  #define SPEED_MPFR_FUNC(mean_fun) do {               \
      48    unsigned  i;                                       \
      49    mpfr_limb_ptr wp;                                  \
      50    double    t;                                       \
      51    mpfr_t    w, x;                                    \
      52    mp_size_t size;                                    \
      53    MPFR_TMP_DECL (marker);                            \
      54                                                       \
      55    SPEED_RESTRICT_COND (s->size >= MPFR_PREC_MIN);    \
      56    SPEED_RESTRICT_COND (s->size <= MPFR_PREC_MAX);    \
      57    MPFR_TMP_MARK (marker);                            \
      58                                                       \
      59    size = (s->size-1)/GMP_NUMB_BITS+1;                \
      60    s->xp[size-1] |= MPFR_LIMB_HIGHBIT;                \
      61    MPFR_TMP_INIT1 (s->xp, x, s->size);                \
      62    MPFR_SET_EXP (x, 0);                               \
      63                                                       \
      64    MPFR_TMP_INIT (wp, w, s->size, size);              \
      65                                                       \
      66    speed_operand_src (s, s->xp, size);                \
      67    speed_operand_dst (s, wp, size);                   \
      68    speed_cache_fill (s);                              \
      69                                                       \
      70    speed_starttime ();                                \
      71    i = s->reps;                                       \
      72    do                                                 \
      73      mean_fun (w, x, MPFR_RNDN);                      \
      74    while (--i != 0);                                  \
      75    t = speed_endtime ();                              \
      76                                                       \
      77    MPFR_TMP_FREE (marker);                            \
      78    return t;                                          \
      79  } while (0)
      80  
      81  #define SPEED_MPFR_OP(mean_fun) do {                 \
      82    unsigned  i;                                       \
      83    mpfr_limb_ptr wp;                                  \
      84    double    t;                                       \
      85    mpfr_t    w, x, y;                                 \
      86    mp_size_t size;                                    \
      87    MPFR_TMP_DECL (marker);                            \
      88                                                       \
      89    SPEED_RESTRICT_COND (s->size >= MPFR_PREC_MIN);    \
      90    SPEED_RESTRICT_COND (s->size <= MPFR_PREC_MAX);    \
      91    MPFR_TMP_MARK (marker);                            \
      92                                                       \
      93    size = (s->size-1)/GMP_NUMB_BITS+1;                \
      94    s->xp[size-1] |= MPFR_LIMB_HIGHBIT;                \
      95    MPFR_TMP_INIT1 (s->xp, x, s->size);                \
      96    MPFR_SET_EXP (x, 0);                               \
      97    s->yp[size-1] |= MPFR_LIMB_HIGHBIT;                \
      98    MPFR_TMP_INIT1 (s->yp, y, s->size);                \
      99    MPFR_SET_EXP (y, 0);                               \
     100                                                       \
     101    MPFR_TMP_INIT (wp, w, s->size, size);              \
     102                                                       \
     103    speed_operand_src (s, s->xp, size);                \
     104    speed_operand_src (s, s->yp, size);                \
     105    speed_operand_dst (s, wp, size);                   \
     106    speed_cache_fill (s);                              \
     107                                                       \
     108    speed_starttime ();                                \
     109    i = s->reps;                                       \
     110    do                                                 \
     111      mean_fun (w, x, y, MPFR_RNDN);                   \
     112    while (--i != 0);                                  \
     113    t = speed_endtime ();                              \
     114                                                       \
     115    MPFR_TMP_FREE (marker);                            \
     116    return t;                                          \
     117  } while (0)
     118  
     119  
     120  /* First we include all the functions we want to tune inside this program.
     121     We can't use GNU MPFR library since the THRESHOLD can't vary */
     122  
     123  /* Setup mpfr_mul */
     124  mpfr_prec_t mpfr_mul_threshold = MPFR_MUL_THRESHOLD;
     125  static double speed_mpfr_mul (struct speed_params *s) {
     126    SPEED_MPFR_OP (mpfr_mul);
     127  }
     128  
     129  
     130  
     131  /************************************************
     132   * Common functions (inspired by GMP function)  *
     133   ************************************************/
     134  #define THRESHOLD_WINDOW 16
     135  #define THRESHOLD_FINAL_WINDOW 128
     136  static double domeasure (mpfr_prec_t *threshold,
     137                           double (*func) (struct speed_params *),
     138                           mpfr_prec_t p)
     139  {
     140    struct speed_params s;
     141    mp_size_t size;
     142    double t;
     143  
     144    s.align_xp = s.align_yp = s.align_wp = 64;
     145    s.size = p;
     146    size = (p - 1)/GMP_NUMB_BITS+1;
     147    s.xp = malloc (2*size*sizeof (mp_limb_t));
     148    if (s.xp == NULL)
     149      {
     150        fprintf (stderr, "Can't allocate memory.\n");
     151        abort ();
     152      }
     153    mpn_random (s.xp, size);
     154    s.yp = s.xp + size;
     155    mpn_random (s.yp, size);
     156    t = speed_measure (func, &s);
     157    if (t == -1.0)
     158      {
     159        fprintf (stderr, "Failed to measure function!\n");
     160        abort ();
     161      }
     162    free (s.xp);
     163    return t;
     164  }
     165  
     166  /* Tune a function with a simple THRESHOLD
     167     The function doesn't depend on another threshold.
     168     It assumes that it uses algo1 if p < THRESHOLD
     169     and algo2 otherwise.
     170     if algo2 is better for low prec, and algo1 better for high prec,
     171     the behaviour of this function is undefined. */
     172  static void
     173  tune_simple_func (mpfr_prec_t *threshold,
     174                    double (*func) (struct speed_params *),
     175                    mpfr_prec_t pstart, mpfr_prec_t pend)
     176  {
     177    double measure;
     178    mpfr_prec_t p = pstart;
     179    mp_size_t k, n;
     180  
     181    while (p <= pend)
     182      {
     183        measure = domeasure (threshold, func, p);
     184        printf ("prec=%lu mpfr_mul=%e ", p, measure);
     185        n = 1 + (p - 1) / GMP_NUMB_BITS;
     186        if (n <= MPFR_MUL_THRESHOLD)
     187          k = MUL_FFT_THRESHOLD + 1;
     188        else if (n < MPFR_MULHIGH_TAB_SIZE)
     189          k = mulhigh_ktab[n];
     190        else
     191          k = 2*n/3;
     192        if (k < 0)
     193          printf ("[mpn_mul_basecase]\n");
     194        else if (k == 0)
     195          printf ("[mpfr_mulhigh_n_basecase]\n");
     196        else if (k > MUL_FFT_THRESHOLD)
     197          printf ("[mpn_mul_n]\n");
     198        else
     199          printf ("[mpfr_mulhigh_n]\n");
     200        p = p + p / 10;
     201      }
     202  }
     203  
     204  /*******************************************************
     205   *            Tune all the threshold of MPFR           *
     206   * Warning: tune the function in their dependent order!*
     207   *******************************************************/
     208  static void
     209  all (void)
     210  {
     211    FILE *f = stdout;
     212    time_t  start_time, end_time;
     213    struct tm  *tp;
     214  
     215    speed_time_init ();
     216    if (verbose) {
     217      printf ("Using: %s\n", speed_time_string);
     218      printf ("speed_precision %d", speed_precision);
     219      if (speed_unittime == 1.0)
     220        printf (", speed_unittime 1 cycle");
     221      else
     222        printf (", speed_unittime %.2e secs", speed_unittime);
     223      if (speed_cycletime == 1.0 || speed_cycletime == 0.0)
     224        printf (", CPU freq unknown\n");
     225      else
     226        printf (", CPU freq %.2f MHz\n\n", 1e-6/speed_cycletime);
     227    }
     228  
     229    time (&start_time);
     230    tp = localtime (&start_time);
     231    fprintf (f, "/* Generated by MPFR's tuneup.c, %d-%02d-%02d, ",
     232            tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday);
     233  
     234  #ifdef __ICC
     235    fprintf (f, "icc %d.%d.%d */\n", __ICC / 100, __ICC / 10 % 10, __ICC % 10);
     236  #elif defined(__GNUC__)
     237    fprintf (f, "gcc %d.%d */\n", __GNUC__, __GNUC_MINOR__);
     238  #elif defined (__SUNPRO_C)
     239    fprintf (f, "Sun C %d.%d */\n", __SUNPRO_C / 0x100, __SUNPRO_C % 0x100);
     240  #elif defined (__sgi) && defined (_COMPILER_VERSION)
     241    fprintf (f, "MIPSpro C %d.%d.%d */\n",
     242             _COMPILER_VERSION / 100,
     243             _COMPILER_VERSION / 10 % 10,
     244             _COMPILER_VERSION % 10);
     245  #elif defined (__DECC) && defined (__DECC_VER)
     246    fprintf (f, "DEC C %d */\n", __DECC_VER);
     247  #else
     248    fprintf (f, "system compiler */\n");
     249  #endif
     250    fprintf (f, "\n");
     251  
     252    /* Tune mpfr_mul (threshold is in limbs, but it doesn't matter too much) */
     253    if (verbose)
     254      printf ("Measuring mpfr_mul with mpfr_mul_threshold=%lu...\n",
     255              mpfr_mul_threshold);
     256    tune_simple_func (&mpfr_mul_threshold, speed_mpfr_mul,
     257                      2*GMP_NUMB_BITS+1, 1000);
     258  
     259    /* End of tuning */
     260    time (&end_time);
     261    if (verbose)
     262      printf ("Complete (took %ld seconds).\n", end_time - start_time);
     263  }
     264  
     265  
     266  /* Main function */
     267  int main (int argc, char *argv[])
     268  {
     269    /* Unbuffered so if output is redirected to a file it isn't lost if the
     270       program is killed part way through.  */
     271    setbuf (stdout, NULL);
     272    setbuf (stderr, NULL);
     273  
     274    verbose = argc > 1;
     275  
     276    if (verbose)
     277      printf ("Tuning MPFR (Coffee time?)...\n");
     278  
     279    all ();
     280  
     281    return 0;
     282  }