[Gmp-commit] /var/hg/gmp: Improved search for optimal p.
mercurial at gmplib.org
mercurial at gmplib.org
Wed May 25 22:17:02 CEST 2011
details: /var/hg/gmp/rev/86955a410da3
changeset: 14201:86955a410da3
user: Niels M?ller <nisse at lysator.liu.se>
date: Wed May 25 22:16:58 2011 +0200
description:
Improved search for optimal p.
diffstat:
ChangeLog | 5 ++
tune/tune-gcd-p.c | 132 ++++++++++++++++++++++++++++++++++++++---------------
2 files changed, 98 insertions(+), 39 deletions(-)
diffs (188 lines):
diff -r 61ab2d89493a -r 86955a410da3 ChangeLog
--- a/ChangeLog Tue May 24 11:11:12 2011 +0200
+++ b/ChangeLog Wed May 25 22:16:58 2011 +0200
@@ -1,3 +1,8 @@
+2011-05-25 Niels Möller <nisse at lysator.liu.se>
+
+ * tune/tune-gcd-p.c (search): New function to search for minimum.
+ (main): Replaced slow linear search.
+
2011-05-24 Niels Möller <nisse at lysator.liu.se>
* tune/Makefile.am (EXTRA_PROGRAMS): Added tune-gcd-p. Also added
diff -r 61ab2d89493a -r 86955a410da3 tune/tune-gcd-p.c
--- a/tune/tune-gcd-p.c Tue May 24 11:11:12 2011 +0200
+++ b/tune/tune-gcd-p.c Wed May 25 22:16:58 2011 +0200
@@ -30,6 +30,58 @@
#include "speed.h"
+/* Search for minimum over a range. FIXME: Implement golden-section /
+ fibonacci search*/
+static int
+search (double *minp, double (*f)(void *, int), void *ctx, int start, int end)
+{
+ int x[4];
+ double y[4];
+
+ int best_i;
+
+ x[0] = start;
+ x[3] = end;
+
+ y[0] = f(ctx, x[0]);
+ y[3] = f(ctx, x[3]);
+
+ for (;;)
+ {
+ int i;
+ int length = x[3] - x[0];
+
+ x[1] = x[0] + length/3;
+ x[2] = x[0] + 2*length/3;
+
+ y[1] = f(ctx, x[1]);
+ y[2] = f(ctx, x[2]);
+
+#if 0
+ printf("%d: %f, %d: %f, %d:, %f %d: %f\n",
+ x[0], y[0], x[1], y[1], x[2], y[2], x[3], y[3]);
+#endif
+ for (best_i = 0, i = 1; i < 4; i++)
+ if (y[i] < y[best_i])
+ best_i = i;
+
+ if (length <= 4)
+ break;
+
+ if (best_i >= 2)
+ {
+ x[0] = x[1];
+ y[0] = y[1];
+ }
+ else
+ {
+ x[3] = x[2];
+ y[3] = y[2];
+ }
+ }
+ *minp = y[best_i];
+ return x[best_i];
+}
static int
compare_double(const void *ap, const void *bp)
@@ -66,16 +118,38 @@
res = median(time_measurement, 5); \
} while (0)
-int
-main(int argc, char **argv)
+struct bench_data
{
- gmp_randstate_t rands;
mp_size_t n;
mp_ptr ap;
mp_ptr bp;
mp_ptr up;
mp_ptr vp;
mp_ptr gp;
+};
+
+static double
+bench_gcd (void *ctx, int p)
+{
+ struct bench_data *data = ctx;
+ double t;
+
+ p_table[data->n] = p;
+ TIME(t, {
+ MPN_COPY (data->up, data->ap, data->n);
+ MPN_COPY (data->vp, data->bp, data->n);
+ mpn_gcd (data->gp, data->up, data->n, data->vp, data->n);
+ });
+
+ return t;
+}
+
+int
+main(int argc, char **argv)
+{
+ gmp_randstate_t rands; struct bench_data data;
+ mp_size_t n;
+
TMP_DECL;
/* Unbuffered so if output is redirected to a file it isn't lost if the
@@ -87,14 +161,14 @@
TMP_MARK;
- ap = TMP_ALLOC_LIMBS (P_TABLE_SIZE);
- bp = TMP_ALLOC_LIMBS (P_TABLE_SIZE);
- up = TMP_ALLOC_LIMBS (P_TABLE_SIZE);
- vp = TMP_ALLOC_LIMBS (P_TABLE_SIZE);
- gp = TMP_ALLOC_LIMBS (P_TABLE_SIZE);
+ data.ap = TMP_ALLOC_LIMBS (P_TABLE_SIZE);
+ data.bp = TMP_ALLOC_LIMBS (P_TABLE_SIZE);
+ data.up = TMP_ALLOC_LIMBS (P_TABLE_SIZE);
+ data.vp = TMP_ALLOC_LIMBS (P_TABLE_SIZE);
+ data.gp = TMP_ALLOC_LIMBS (P_TABLE_SIZE);
- mpn_random (ap, P_TABLE_SIZE);
- mpn_random (bp, P_TABLE_SIZE);
+ mpn_random (data.ap, P_TABLE_SIZE);
+ mpn_random (data.bp, P_TABLE_SIZE);
memset (p_table, 0, sizeof(p_table));
@@ -105,40 +179,20 @@
double best_time;
double lehmer_time;
- if (ap[n-1] == 0)
- ap[n-1] = 1;
+ if (data.ap[n-1] == 0)
+ data.ap[n-1] = 1;
- if (bp[n-1] == 0)
- bp[n-1] = 1;
+ if (data.bp[n-1] == 0)
+ data.bp[n-1] = 1;
- p_table[n] = 0;
- TIME(lehmer_time, {
- MPN_COPY (up, ap, n);
- MPN_COPY (vp, bp, n);
- mpn_gcd (gp, up, n, vp, n);
- });
+ data.n = n;
- best_time = lehmer_time;
- best_p = 0;
+ lehmer_time = bench_gcd (&data, 0);
- for (p = n * 0.48; p < n * 0.77; p++)
- {
- double t;
+ best_p = search (&best_time, bench_gcd, &data, 10, n-10);
+ if (best_time > lehmer_time)
+ best_p = 0;
- p_table[n] = p;
-
- TIME(t, {
- MPN_COPY (up, ap, n);
- MPN_COPY (vp, bp, n);
- mpn_gcd (gp, up, n, vp, n);
- });
-
- if (t < best_time)
- {
- best_time = t;
- best_p = p;
- }
- }
printf("%6d %6d %5.3g", n, best_p, (double) best_p / n);
if (best_p > 0)
{
More information about the gmp-commit
mailing list