mirror of
https://github.com/vale981/arb
synced 2025-03-05 09:21:38 -05:00
multithreaded numerical integration
This commit is contained in:
parent
bccb6ce632
commit
1c618abfae
4 changed files with 161 additions and 28 deletions
|
@ -63,10 +63,28 @@ void gl_init()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute GL node and weight of index k for n = gl_steps[i]. Cached. */
|
/* Compute GL node and weight of index k for n = gl_steps[i]. Cached. */
|
||||||
void
|
typedef struct
|
||||||
acb_calc_gl_node(arb_t x, arb_t w, slong i, slong k, slong prec)
|
|
||||||
{
|
{
|
||||||
slong n, kk, jj, wp;
|
arb_ptr nodes;
|
||||||
|
arb_ptr weights;
|
||||||
|
slong n;
|
||||||
|
slong wp;
|
||||||
|
}
|
||||||
|
nodes_work_t;
|
||||||
|
|
||||||
|
static void
|
||||||
|
nodes_worker(slong jj, nodes_work_t * work)
|
||||||
|
{
|
||||||
|
arb_hypgeom_legendre_p_ui_root(work->nodes + jj, work->weights + jj, work->n, jj, work->wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if k >= 0, compute the node and weight of index k */
|
||||||
|
/* if k < 0, compute the first (n+1)/2 nodes and weights (the others are given by symmetry) */
|
||||||
|
void
|
||||||
|
acb_calc_gl_node(arb_ptr x, arb_ptr w, slong i, slong k, slong prec)
|
||||||
|
{
|
||||||
|
slong n, kk, wp;
|
||||||
|
int all;
|
||||||
|
|
||||||
if (i < 0 || i >= GL_STEPS || prec < 2)
|
if (i < 0 || i >= GL_STEPS || prec < 2)
|
||||||
flint_abort();
|
flint_abort();
|
||||||
|
@ -76,16 +94,15 @@ acb_calc_gl_node(arb_t x, arb_t w, slong i, slong k, slong prec)
|
||||||
|
|
||||||
n = gl_steps[i];
|
n = gl_steps[i];
|
||||||
|
|
||||||
if (k < 0 || k >= n)
|
if (k >= n)
|
||||||
flint_abort();
|
flint_abort();
|
||||||
|
|
||||||
if (2 * k < n)
|
all = (k < 0);
|
||||||
kk = k;
|
|
||||||
else
|
|
||||||
kk = n - 1 - k;
|
|
||||||
|
|
||||||
if (gl_cache->gl_prec[i] < prec)
|
if (gl_cache->gl_prec[i] < prec)
|
||||||
{
|
{
|
||||||
|
nodes_work_t work;
|
||||||
|
|
||||||
if (gl_cache->gl_prec[i] == 0)
|
if (gl_cache->gl_prec[i] == 0)
|
||||||
{
|
{
|
||||||
gl_cache->gl_nodes[i] = _arb_vec_init((n + 1) / 2);
|
gl_cache->gl_nodes[i] = _arb_vec_init((n + 1) / 2);
|
||||||
|
@ -94,21 +111,86 @@ acb_calc_gl_node(arb_t x, arb_t w, slong i, slong k, slong prec)
|
||||||
|
|
||||||
wp = FLINT_MAX(prec, gl_cache->gl_prec[i] * 2 + 30);
|
wp = FLINT_MAX(prec, gl_cache->gl_prec[i] * 2 + 30);
|
||||||
|
|
||||||
for (jj = 0; 2 * jj < n; jj++)
|
work.nodes = gl_cache->gl_nodes[i];
|
||||||
{
|
work.weights = gl_cache->gl_weights[i];
|
||||||
arb_hypgeom_legendre_p_ui_root(gl_cache->gl_nodes[i] + jj,
|
work.n = n;
|
||||||
gl_cache->gl_weights[i] + jj, n, jj, wp);
|
work.wp = wp;
|
||||||
}
|
|
||||||
|
flint_parallel_do((do_func_t) nodes_worker, &work, (n + 1) / 2, -1, FLINT_PARALLEL_STRIDED);
|
||||||
|
|
||||||
gl_cache->gl_prec[i] = wp;
|
gl_cache->gl_prec[i] = wp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (all)
|
||||||
|
{
|
||||||
|
for (k = 0; k < (n + 1) / 2; k++)
|
||||||
|
{
|
||||||
|
arb_set_round(x + k, gl_cache->gl_nodes[i] + k, prec);
|
||||||
|
arb_set_round(w + k, gl_cache->gl_weights[i] + k, prec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (2 * k < n)
|
||||||
|
kk = k;
|
||||||
|
else
|
||||||
|
kk = n - 1 - k;
|
||||||
|
|
||||||
if (2 * k < n)
|
if (2 * k < n)
|
||||||
arb_set_round(x, gl_cache->gl_nodes[i] + kk, prec);
|
arb_set_round(x, gl_cache->gl_nodes[i] + kk, prec);
|
||||||
else
|
else
|
||||||
arb_neg_round(x, gl_cache->gl_nodes[i] + kk, prec);
|
arb_neg_round(x, gl_cache->gl_nodes[i] + kk, prec);
|
||||||
|
|
||||||
arb_set_round(w, gl_cache->gl_weights[i] + kk, prec);
|
arb_set_round(w, gl_cache->gl_weights[i] + kk, prec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
slong n;
|
||||||
|
slong prec;
|
||||||
|
arb_srcptr x;
|
||||||
|
arb_srcptr w;
|
||||||
|
acb_srcptr delta;
|
||||||
|
acb_srcptr mid;
|
||||||
|
acb_ptr v;
|
||||||
|
acb_calc_func_t f;
|
||||||
|
void * param;
|
||||||
|
}
|
||||||
|
gl_work_t;
|
||||||
|
|
||||||
|
static void
|
||||||
|
gl_worker(slong k, gl_work_t * args)
|
||||||
|
{
|
||||||
|
arb_t x, w;
|
||||||
|
acb_t t;
|
||||||
|
slong k2;
|
||||||
|
|
||||||
|
slong prec = args->prec;
|
||||||
|
slong n = args->n;
|
||||||
|
acb_ptr v = args->v;
|
||||||
|
|
||||||
|
arb_init(x);
|
||||||
|
arb_init(w);
|
||||||
|
acb_init(t);
|
||||||
|
|
||||||
|
if (2 * k < n)
|
||||||
|
k2 = k;
|
||||||
|
else
|
||||||
|
k2 = n - 1 - k;
|
||||||
|
|
||||||
|
acb_mul_arb(t, args->delta, args->x + k2, prec);
|
||||||
|
|
||||||
|
if (k2 != k)
|
||||||
|
acb_neg(t, t);
|
||||||
|
|
||||||
|
acb_add(t, t, args->mid, prec);
|
||||||
|
args->f(v + k, t, args->param, 0, prec);
|
||||||
|
acb_mul_arb(v + k, v + k, args->w + k2, prec);
|
||||||
|
|
||||||
|
arb_clear(x);
|
||||||
|
arb_clear(w);
|
||||||
|
acb_clear(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -236,6 +318,7 @@ acb_calc_integrate_gl_auto_deg(acb_t res, slong * eval_count,
|
||||||
/* Evaluate best found Gauss-Legendre quadrature rule. */
|
/* Evaluate best found Gauss-Legendre quadrature rule. */
|
||||||
if (status == ARB_CALC_SUCCESS)
|
if (status == ARB_CALC_SUCCESS)
|
||||||
{
|
{
|
||||||
|
slong nt;
|
||||||
arb_t x, w;
|
arb_t x, w;
|
||||||
arb_init(x);
|
arb_init(x);
|
||||||
arb_init(w);
|
arb_init(w);
|
||||||
|
@ -259,6 +342,42 @@ acb_calc_integrate_gl_auto_deg(acb_t res, slong * eval_count,
|
||||||
if (gl_steps[i] == best_n)
|
if (gl_steps[i] == best_n)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
nt = flint_get_num_threads();
|
||||||
|
|
||||||
|
if (nt >= 2 && best_n >= 2)
|
||||||
|
{
|
||||||
|
gl_work_t work;
|
||||||
|
acb_ptr v;
|
||||||
|
arb_ptr x, w;
|
||||||
|
|
||||||
|
v = _acb_vec_init(best_n);
|
||||||
|
w = _arb_vec_init((best_n + 1) / 2);
|
||||||
|
x = _arb_vec_init((best_n + 1) / 2);
|
||||||
|
|
||||||
|
acb_calc_gl_node(x, w, i, -1, prec);
|
||||||
|
|
||||||
|
work.n = best_n;
|
||||||
|
work.x = x;
|
||||||
|
work.w = w;
|
||||||
|
work.prec = prec;
|
||||||
|
work.delta = delta;
|
||||||
|
work.mid = mid;
|
||||||
|
work.v = v;
|
||||||
|
work.f = f;
|
||||||
|
work.param = param;
|
||||||
|
|
||||||
|
flint_parallel_do((do_func_t) gl_worker, &work, best_n, -1, FLINT_PARALLEL_STRIDED);
|
||||||
|
|
||||||
|
acb_add(s, v, v + 1, prec);
|
||||||
|
for (k = 2; k < best_n; k++)
|
||||||
|
acb_add(s, s, v + k, prec);
|
||||||
|
|
||||||
|
_acb_vec_clear(v, best_n);
|
||||||
|
_arb_vec_clear(x, (best_n + 1) / 2);
|
||||||
|
_arb_vec_clear(w, (best_n + 1) / 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
acb_zero(s);
|
acb_zero(s);
|
||||||
|
|
||||||
for (k = 0; k < best_n; k++)
|
for (k = 0; k < best_n; k++)
|
||||||
|
@ -269,6 +388,7 @@ acb_calc_integrate_gl_auto_deg(acb_t res, slong * eval_count,
|
||||||
f(v, wide, param, 0, prec);
|
f(v, wide, param, 0, prec);
|
||||||
acb_addmul_arb(s, v, w, prec);
|
acb_addmul_arb(s, v, w, prec);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
eval_count[0] += best_n;
|
eval_count[0] += best_n;
|
||||||
|
|
||||||
|
|
|
@ -351,6 +351,8 @@ int main()
|
||||||
acb_calc_integrate_opt_t opt;
|
acb_calc_integrate_opt_t opt;
|
||||||
int integral;
|
int integral;
|
||||||
|
|
||||||
|
flint_set_num_threads(1 + n_randint(state, 3));
|
||||||
|
|
||||||
acb_init(ans);
|
acb_init(ans);
|
||||||
acb_init(res);
|
acb_init(res);
|
||||||
acb_init(a);
|
acb_init(a);
|
||||||
|
@ -712,7 +714,7 @@ int main()
|
||||||
}
|
}
|
||||||
|
|
||||||
flint_randclear(state);
|
flint_randclear(state);
|
||||||
flint_cleanup();
|
flint_cleanup_master();
|
||||||
flint_printf("PASS\n");
|
flint_printf("PASS\n");
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -655,6 +655,7 @@ Invoking the program without parameters shows usage::
|
||||||
-deg n - use quadrature degree up to n
|
-deg n - use quadrature degree up to n
|
||||||
-eval n - limit number of function evaluations to n
|
-eval n - limit number of function evaluations to n
|
||||||
-depth n - limit subinterval queue size to n
|
-depth n - limit subinterval queue size to n
|
||||||
|
-threads n - use parallel computation with n threads
|
||||||
|
|
||||||
Implemented integrals:
|
Implemented integrals:
|
||||||
I0 = int_0^100 sin(x) dx
|
I0 = int_0^100 sin(x) dx
|
||||||
|
|
|
@ -780,6 +780,7 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
acb_t s, t, a, b;
|
acb_t s, t, a, b;
|
||||||
mag_t tol;
|
mag_t tol;
|
||||||
|
slong num_threads;
|
||||||
slong prec, goal;
|
slong prec, goal;
|
||||||
slong N;
|
slong N;
|
||||||
ulong k;
|
ulong k;
|
||||||
|
@ -821,7 +822,8 @@ int main(int argc, char *argv[])
|
||||||
flint_printf("-verbose2 - show more information\n");
|
flint_printf("-verbose2 - show more information\n");
|
||||||
flint_printf("-deg n - use quadrature degree up to n\n");
|
flint_printf("-deg n - use quadrature degree up to n\n");
|
||||||
flint_printf("-eval n - limit number of function evaluations to n\n");
|
flint_printf("-eval n - limit number of function evaluations to n\n");
|
||||||
flint_printf("-depth n - limit subinterval queue size to n\n\n");
|
flint_printf("-depth n - limit subinterval queue size to n\n");
|
||||||
|
flint_printf("-threads n - use parallel computation with n threads\n\n");
|
||||||
flint_printf("Implemented integrals:\n");
|
flint_printf("Implemented integrals:\n");
|
||||||
for (integral = 0; integral < NUM_INTEGRALS; integral++)
|
for (integral = 0; integral < NUM_INTEGRALS; integral++)
|
||||||
flint_printf("I%d = %s\n", integral, descr[integral]);
|
flint_printf("I%d = %s\n", integral, descr[integral]);
|
||||||
|
@ -835,6 +837,7 @@ int main(int argc, char *argv[])
|
||||||
twice = 0;
|
twice = 0;
|
||||||
goal = 0;
|
goal = 0;
|
||||||
havetol = havegoal = 0;
|
havetol = havegoal = 0;
|
||||||
|
num_threads = 1;
|
||||||
|
|
||||||
acb_init(a);
|
acb_init(a);
|
||||||
acb_init(b);
|
acb_init(b);
|
||||||
|
@ -895,7 +898,14 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
options->use_heap = 1;
|
options->use_heap = 1;
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(argv[i], "-threads"))
|
||||||
|
{
|
||||||
|
num_threads = atol(argv[i+1]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_threads >= 2)
|
||||||
|
flint_set_num_threads(num_threads);
|
||||||
|
|
||||||
if (!havegoal)
|
if (!havegoal)
|
||||||
goal = prec;
|
goal = prec;
|
||||||
|
@ -1276,7 +1286,7 @@ int main(int argc, char *argv[])
|
||||||
acb_clear(t);
|
acb_clear(t);
|
||||||
mag_clear(tol);
|
mag_clear(tol);
|
||||||
|
|
||||||
flint_cleanup();
|
flint_cleanup_master();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue