1 /* Tune various threshold of MPFR
3 Copyright 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4 Contributed by the Arenaire and Cacao projects, INRIA.
6 This file is part of the GNU MPFR Library.
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.
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.
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 http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
26 #define MPFR_NEED_LONGLONG_H
27 #include "mpfr-impl.h"
29 /* extracted from mulders.c */
30 #ifdef MPFR_MULHIGH_TAB_SIZE
31 static short mulhigh_ktab[MPFR_MULHIGH_TAB_SIZE];
33 static short mulhigh_ktab[] = {MPFR_MULHIGH_TAB};
34 #define MPFR_MULHIGH_TAB_SIZE \
35 ((mp_size_t) (sizeof(mulhigh_ktab) / sizeof(mulhigh_ktab[0])))
39 #define _PROTO __GMP_PROTO
44 /* s->size: precision of both input and output
45 s->xp : Mantissa of first input
46 s->yp : mantissa of second input */
48 #define SPEED_MPFR_FUNC(mean_fun) do { \
54 MPFR_TMP_DECL (marker); \
56 SPEED_RESTRICT_COND (s->size >= MPFR_PREC_MIN); \
57 SPEED_RESTRICT_COND (s->size <= MPFR_PREC_MAX); \
58 MPFR_TMP_MARK (marker); \
60 size = (s->size-1)/GMP_NUMB_BITS+1; \
61 s->xp[size-1] |= MPFR_LIMB_HIGHBIT; \
62 MPFR_TMP_INIT1 (s->xp, x, s->size); \
63 MPFR_SET_EXP (x, 0); \
65 MPFR_TMP_INIT (wp, w, s->size, size); \
67 speed_operand_src (s, s->xp, size); \
68 speed_operand_dst (s, wp, size); \
69 speed_cache_fill (s); \
74 mean_fun (w, x, MPFR_RNDN); \
76 t = speed_endtime (); \
78 MPFR_TMP_FREE (marker); \
82 #define SPEED_MPFR_OP(mean_fun) do { \
88 MPFR_TMP_DECL (marker); \
90 SPEED_RESTRICT_COND (s->size >= MPFR_PREC_MIN); \
91 SPEED_RESTRICT_COND (s->size <= MPFR_PREC_MAX); \
92 MPFR_TMP_MARK (marker); \
94 size = (s->size-1)/GMP_NUMB_BITS+1; \
95 s->xp[size-1] |= MPFR_LIMB_HIGHBIT; \
96 MPFR_TMP_INIT1 (s->xp, x, s->size); \
97 MPFR_SET_EXP (x, 0); \
98 s->yp[size-1] |= MPFR_LIMB_HIGHBIT; \
99 MPFR_TMP_INIT1 (s->yp, y, s->size); \
100 MPFR_SET_EXP (y, 0); \
102 MPFR_TMP_INIT (wp, w, s->size, size); \
104 speed_operand_src (s, s->xp, size); \
105 speed_operand_src (s, s->yp, size); \
106 speed_operand_dst (s, wp, size); \
107 speed_cache_fill (s); \
109 speed_starttime (); \
112 mean_fun (w, x, y, MPFR_RNDN); \
114 t = speed_endtime (); \
116 MPFR_TMP_FREE (marker); \
121 /* First we include all the functions we want to tune inside this program.
122 We can't use GNU MPFR library since the THRESHOLD can't vary */
125 mpfr_prec_t mpfr_mul_threshold = MPFR_MUL_THRESHOLD;
126 static double speed_mpfr_mul (struct speed_params *s) {
127 SPEED_MPFR_OP (mpfr_mul);
132 /************************************************
133 * Common functions (inspired by GMP function) *
134 ************************************************/
135 #define THRESHOLD_WINDOW 16
136 #define THRESHOLD_FINAL_WINDOW 128
137 static double domeasure (mpfr_prec_t *threshold,
138 double (*func) (struct speed_params *),
141 struct speed_params s;
145 s.align_xp = s.align_yp = s.align_wp = 64;
147 size = (p - 1)/GMP_NUMB_BITS+1;
148 s.xp = malloc (2*size*sizeof (mp_limb_t));
151 fprintf (stderr, "Can't allocate memory.\n");
154 mpn_random (s.xp, size);
156 mpn_random (s.yp, size);
157 t = speed_measure (func, &s);
160 fprintf (stderr, "Failed to measure function!\n");
167 /* Tune a function with a simple THRESHOLD
168 The function doesn't depend on another threshold.
169 It assumes that it uses algo1 if p < THRESHOLD
171 if algo2 is better for low prec, and algo1 better for high prec,
172 the behaviour of this function is undefined. */
174 tune_simple_func (mpfr_prec_t *threshold,
175 double (*func) (struct speed_params *),
176 mpfr_prec_t pstart, mpfr_prec_t pend)
179 mpfr_prec_t p = pstart;
184 measure = domeasure (threshold, func, p);
185 printf ("prec=%lu mpfr_mul=%e ", p, measure);
186 n = 1 + (p - 1) / GMP_NUMB_BITS;
187 if (n <= MPFR_MUL_THRESHOLD)
188 k = MUL_FFT_THRESHOLD + 1;
189 else if (n < MPFR_MULHIGH_TAB_SIZE)
194 printf ("[mpn_mul_basecase]\n");
196 printf ("[mpfr_mulhigh_n_basecase]\n");
197 else if (k > MUL_FFT_THRESHOLD)
198 printf ("[mpn_mul_n]\n");
200 printf ("[mpfr_mulhigh_n]\n");
205 /*******************************************************
206 * Tune all the threshold of MPFR *
207 * Warning: tune the function in their dependent order!*
208 *******************************************************/
213 time_t start_time, end_time;
218 printf ("Using: %s\n", speed_time_string);
219 printf ("speed_precision %d", speed_precision);
220 if (speed_unittime == 1.0)
221 printf (", speed_unittime 1 cycle");
223 printf (", speed_unittime %.2e secs", speed_unittime);
224 if (speed_cycletime == 1.0 || speed_cycletime == 0.0)
225 printf (", CPU freq unknown\n");
227 printf (", CPU freq %.2f MHz\n\n", 1e-6/speed_cycletime);
231 tp = localtime (&start_time);
232 fprintf (f, "/* Generated by MPFR's tuneup.c, %d-%02d-%02d, ",
233 tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday);
236 fprintf (f, "icc %d.%d.%d */\n", __ICC / 100, __ICC / 10 % 10, __ICC % 10);
237 #elif defined(__GNUC__)
238 fprintf (f, "gcc %d.%d */\n", __GNUC__, __GNUC_MINOR__);
239 #elif defined (__SUNPRO_C)
240 fprintf (f, "Sun C %d.%d */\n", __SUNPRO_C / 0x100, __SUNPRO_C % 0x100);
241 #elif defined (__sgi) && defined (_COMPILER_VERSION)
242 fprintf (f, "MIPSpro C %d.%d.%d */\n",
243 _COMPILER_VERSION / 100,
244 _COMPILER_VERSION / 10 % 10,
245 _COMPILER_VERSION % 10);
246 #elif defined (__DECC) && defined (__DECC_VER)
247 fprintf (f, "DEC C %d */\n", __DECC_VER);
249 fprintf (f, "system compiler */\n");
253 /* Tune mpfr_mul (threshold is in limbs, but it doesn't matter too much) */
255 printf ("Measuring mpfr_mul with mpfr_mul_threshold=%lu...\n",
257 tune_simple_func (&mpfr_mul_threshold, speed_mpfr_mul,
258 2*GMP_NUMB_BITS+1, 1000);
263 printf ("Complete (took %ld seconds).\n", end_time - start_time);
268 int main (int argc, char *argv[])
270 /* Unbuffered so if output is redirected to a file it isn't lost if the
271 program is killed part way through. */
272 setbuf (stdout, NULL);
273 setbuf (stderr, NULL);
278 printf ("Tuning MPFR (Coffee time?)...\n");