Example #1
0
int main (int argc, char ** argv)
{
  mps_context * s = mps_context_new ();
  mps_thread_pool * pool = mps_thread_pool_new (s, 0);
  int i[N_THREADS];
  int j;

  for(j = 0; j < N_THREADS; j++)
    i[j] = j;
  j = 0;

  printf (" => Created a thread pool with %d threads\n", pool->n);

  printf (" => Asking the threads to print an integer (from 0 to %d)...\n", N_THREADS - 1);
  
  for (j = 0; j < N_THREADS; j++)
    mps_thread_pool_assign (s, pool, (mps_thread_work) work, i + j);

  mps_thread_pool_wait (s, pool);
  printf ("\n => All the threads have completed their work\n");

  printf (" => Doing it again (testing re-usability of the thread pool)\n");

  for (j = 0; j < N_THREADS; j++)
    mps_thread_pool_assign (s, pool, (mps_thread_work) work, i + j);

  mps_thread_pool_wait (s, pool);

  printf ("\n => Trying to stop all the threads..."); 
  mps_thread_pool_free (s, pool); 
  printf ("done\n"); 
}
Example #2
0
/**
 * @brief Improve all the approximations up to prec_out digits.
 *
 * For each approximation compute the value of sigma such that, given some
 * approximations \f$x_j\f$ of the roots, \f$r_j\f$ the values of the
 * inclusion radii and \f$d_i\f$ the number of correct digits:
 * \f[
 *   e_j < e_0 * \sigma^{2^j} \qquad \sigma=\frac{k}{k-1}=\frac{1}{1-t} \qquad k=\frac{1}{t}
 * \f]
 * and
 * \f[
 *   t = \min_j |z_i-z_j|-r_j
 * \f]
 * Then compute the number of digits needed for the j-th
 * iteration i.e., if \f$cond\f$ is the conditioning of the root:
 * \f[
 *   d_j = \log(\frac{e_j}{|x|}) + cond
 * \f]
 * where
 * \f[
 *   \log(\frac{e_j}{|x|}) = (f+g){2j} \qquad
 *   cond = \log(\frac{rad}{\epsilon})
 * \f]
 * and
 * \f[
 *   cond \approx \lVert p \rVert (1+ \frac{|x_i|}{a_n \prod_{j \neq i} |x_i-x_j|}
 * \f]
 * and
 * \f[
 *   cond \approx \frac{r_i}{\epsilon |x_i|}
 * \f]
 * for user-defined polynomials.
 *
 * <code>s->mpwp</code> denotes the number of bits of the current working
 * precision.
 *
 * @param ctx The mps_context associated with the computation.
 */
MPS_PRIVATE void
mps_improve (mps_context * ctx)
{
  int i;
  long int current_precision = 0L;
  int approximated_roots = 0;
  mps_polynomial * p = ctx->active_poly;
  rdpe_t * root_conditioning = NULL;

  ctx->operation = MPS_OPERATION_REFINEMENT;

  /* We need to be able to evaluate the Newton correction in a point
   * in order to perform the refinement. This is not necessary true
   * for custom polynomial types, so add a check in here */
  if (p->mnewton == NULL && p->density != MPS_DENSITY_USER)
    return;

  /* Set lastphase to mp */
  ctx->lastphase = mp_phase;

  /* Determine the conditioning of the roots */
  root_conditioning = evaluate_root_conditioning (ctx, p, ctx->root, ctx->n);

  /* We adopt the strategy of various iterations refinements on
   * the approximations by setting the precision of the input
   * polynomial in an increasing sequence. */

  /* We start by determining the minimum precision at which we can
   * extract some information. */
  current_precision = LONG_MAX;
  for (i = 0; i < ctx->n; i++)
    {
      if (ctx->root[i]->wp < current_precision)
        current_precision = ctx->root[i]->wp;

      if (MPS_ROOT_STATUS_IS_APPROXIMATED (ctx->root[i]->status) ||
	  ctx->root[i]->inclusion == MPS_ROOT_INCLUSION_OUT)
        approximated_roots++;
    }

  /* Start by iterating on the roots that are not approximated, and
   * continue until we get all of them. */
  while (approximated_roots < ctx->n)
    {
      mps_polynomial_raise_data (ctx, p, current_precision);

      MPS_DEBUG (ctx, "Step of improvement");

      for (i = 0; i < ctx->n; i++)
        if (ctx->root[i]->status == MPS_ROOT_STATUS_ISOLATED && 
	    ctx->root[i]->inclusion != MPS_ROOT_INCLUSION_OUT)
          {
            /* Evaluate the necessary precision to iterate on this root.
             * If the the current polynomial precision is enough, iterate on it.
             * Otherwise, let it for the next round. */
            long int necessary_precision = get_approximated_bits (ctx->root[i]) + log2 (ctx->n) +
                                           rdpe_log (root_conditioning[i]) / LOG2;

            if (necessary_precision < current_precision)
              {
                __improve_root_data * data = mps_new (__improve_root_data);
                data->ctx = ctx;
                data->p = p;
                data->root = ctx->root[i];
                data->precision = current_precision;

                mps_thread_pool_assign (ctx, NULL, improve_root_wrapper, data);
              }
          }

      mps_thread_pool_wait (ctx, ctx->pool);

      for (i = 0; i < ctx->n; i++)
        if (!MPS_ROOT_STATUS_IS_APPROXIMATED (ctx->root[i]->status) &&
            get_approximated_bits (ctx->root[i]) >= ctx->output_config->prec)
          {
            ctx->root[i]->status = MPS_ROOT_STATUS_APPROXIMATED;
            approximated_roots++;

            if (ctx->debug_level & MPS_DEBUG_IMPROVEMENT)
              MPS_DEBUG (ctx, "Approximated roots = %d", approximated_roots);
          }

      /* Increase precision to reach the desired number of approximated roots */
      current_precision = 2 * current_precision;

      /* Check if we have gone too far with the precision, and we have gone over
       * the maximum precision allowed for this polynomial. */
      if (current_precision > p->prec && p->prec != 0)
        {
          ctx->over_max = true;
          goto cleanup;
        }

      /* Increase data prec max that will be useful to the end user to know
       * the precision needed to hold these approximations. */
      ctx->data_prec_max.value = current_precision;

      if (ctx->debug_level & MPS_DEBUG_IMPROVEMENT)
        MPS_DEBUG (ctx, "Increasing precision to %ld", current_precision);
    }

cleanup:

  free (root_conditioning);
}
Example #3
0
/**
 * @brief Drop-in threaded replacement for the stock mpolzer.
 */
MPS_PRIVATE void
mps_thread_mpolzer (mps_context * s, int *it, mps_boolean * excep, int required_zeros)
{
  int i, nzeros = 0, n_threads = s->n_threads;

  *it = 0;
  *excep = false;

  /* Check if we have already approxmiated roots */
  for (i = 0; i < s->n; i++)
    if (!s->root[i]->again)
      nzeros++;
  if (nzeros == s->n)
    {
      return;
    }

  /* Lower the number of threads if there are a lot of approximated roots */
  if (s->n_threads > (s->n - nzeros))
    n_threads = s->n - nzeros;
  else
    n_threads = s->n_threads;

  MPS_DEBUG_WITH_INFO (s, "Spawning %d worker", n_threads);

  mps_thread_worker_data *data;

  /* Allocate and the init mutexes needed by the routine */
  pthread_mutex_t *roots_mutex =
    (pthread_mutex_t*)mps_malloc (sizeof(pthread_mutex_t) * s->n);
  pthread_mutex_t *aberth_mutex =
    (pthread_mutex_t*)mps_malloc (sizeof(pthread_mutex_t) * s->n);
  pthread_mutex_t global_aberth_mutex = PTHREAD_MUTEX_INITIALIZER;

  for (i = 0; i < s->n; i++)
    {
      pthread_mutex_init (&aberth_mutex[i], NULL);
      pthread_mutex_init (&roots_mutex[i], NULL);
    }

  /* Create a new work queue */
  mps_thread_job_queue *queue = mps_thread_job_queue_new (s);

  data = (mps_thread_worker_data*)mps_malloc (sizeof(mps_thread_worker_data)
                                              * n_threads);

  /* Set data to be passed to every thread and actually spawn the threads. */
  for (i = 0; i < n_threads; i++)
    {
      data[i].it = it;
      data[i].nzeros = &nzeros;
      data[i].s = s;
      data[i].excep = excep;
      data[i].thread = i;
      data[i].n_threads = n_threads;
      data[i].aberth_mutex = aberth_mutex;
      data[i].global_aberth_mutex = &global_aberth_mutex;
      data[i].queue = queue;
      data[i].roots_mutex = roots_mutex;
      data[i].required_zeros = required_zeros;
      mps_thread_pool_assign (s, s->pool, mps_thread_mpolzer_worker, data + i);
    }

  /* Wait for the threads to complete */
  mps_thread_pool_wait (s, s->pool);

  /* Free data and exit */
  free (data);
  for (i = 0; i < s->n; i++)
    {
      pthread_mutex_destroy (&roots_mutex[i]);
      pthread_mutex_destroy (&aberth_mutex[i]);
    }
  free (roots_mutex);
  free (aberth_mutex);
  mps_thread_job_queue_free (queue);
}
Example #4
0
/**
 * @brief Multithread version of mps_dpolzer ().
 */
MPS_PRIVATE void
mps_thread_dpolzer (mps_context * s, int *it, mps_boolean * excep, int required_zeros)
{
  mps_thread_worker_data *data;
  pthread_mutex_t *aberth_mutex, *roots_mutex;
  int i, nzeros = 0;

  /* initialize the iteration counter */
  *it = 0;
  *excep = false;

  /* count the number of approximations in the root neighbourhood */
  for (i = 0; i < s->n; i++)
    if (!s->root[i]->again)
      nzeros++;
  if (nzeros == s->n)
    return;

  /* Prepare queue */
  mps_thread_job_queue *queue = mps_thread_job_queue_new (s);

  /* Allocate space for thread data */
  data = (mps_thread_worker_data*)mps_malloc (sizeof(mps_thread_worker_data)
                                              * s->n_threads);

  /* Allocate mutexes and init them */
  aberth_mutex = (pthread_mutex_t*)mps_malloc (sizeof(pthread_mutex_t) * s->n);
  roots_mutex = (pthread_mutex_t*)mps_malloc (sizeof(pthread_mutex_t) * s->n);
  for (i = 0; i < s->n; i++)
    {
      if (s->pool->n > 1)
	{
	  pthread_mutex_init (&aberth_mutex[i], NULL);
	  pthread_mutex_init (&roots_mutex[i], NULL);
	}
    }

  /* Start spawning thread */
  for (i = 0; i < s->n_threads; i++)
    {
      data[i].aberth_mutex = aberth_mutex;
      data[i].excep = excep;
      data[i].it = it;
      data[i].n_threads = s->n_threads;
      data[i].nzeros = &nzeros;
      data[i].queue = queue;
      data[i].roots_mutex = roots_mutex;
      data[i].s = s;
      data[i].thread = i;
      data[i].required_zeros = required_zeros;
      mps_thread_pool_assign (s, s->pool, mps_thread_dpolzer_worker, data + i);
    }

  /* Wait for the thread to complete */
  mps_thread_pool_wait (s, s->pool);

  free (aberth_mutex);
  free (roots_mutex);
  free (data);
  mps_thread_job_queue_free (queue);
}
Example #5
0
/**
 * @brief Drop-in replacement for the stock fpolzer routine.
 * This version adds multithread support.
 */
MPS_PRIVATE void
mps_thread_fpolzer (mps_context * s, int *it, mps_boolean * excep, int required_zeros)
{
  int i, nzeros = 0, n_threads = s->n_threads;

  mps_thread_worker_data *data;
  pthread_mutex_t *aberth_mutex =
    (pthread_mutex_t*)mps_malloc (sizeof(pthread_mutex_t) * s->n);
  pthread_mutex_t *roots_mutex =
    (pthread_mutex_t*)mps_malloc (sizeof(pthread_mutex_t) * s->n);

  for (i = 0; i < s->n; i++)
    {
      pthread_mutex_init (roots_mutex + i, NULL);
      pthread_mutex_init (aberth_mutex + i, NULL);
    }

  /* Create a new job queue */
  mps_thread_job_queue *queue = mps_thread_job_queue_new (s);

  *it = 0;
  *excep = false;

  /* count the number of approximations in the root neighbourhood */
  for (i = 0; i < s->n; i++)
    if (!s->root[i]->again)
      nzeros++;
  if (nzeros == s->n)
    {
      free (roots_mutex);
      free (aberth_mutex);
      mps_thread_job_queue_free (queue);
      return;
    }

  data = (mps_thread_worker_data*)mps_malloc (sizeof(mps_thread_worker_data)
                                              * n_threads);

  for (i = 0; i < n_threads; i++)
    {
      data[i].it = it;
      data[i].nzeros = &nzeros;
      data[i].s = s;
      data[i].excep = excep;
      data[i].thread = i;
      data[i].n_threads = n_threads;
      data[i].aberth_mutex = aberth_mutex;
      data[i].roots_mutex = roots_mutex;
      data[i].queue = queue;
      data[i].required_zeros = required_zeros;
      /* pthread_create (&threads[i], NULL, &mps_thread_fpolzer_worker, */
      /* data + i); */
      mps_thread_pool_assign (s, s->pool, mps_thread_fpolzer_worker, data + i);
    }

  mps_thread_pool_wait (s, s->pool);

  free (data);
  free (roots_mutex);
  free (aberth_mutex);
  mps_thread_job_queue_free (queue);
}