gint main (gint argc, gchar ** argv)
{
  gint ret = 0;

  VsgPRTree2d *tree;

  VsgVector2d lb;
  VsgVector2d ub;
  GTimer *timer = NULL;

  MPI_Init (&argc, &argv);

  MPI_Comm_size (MPI_COMM_WORLD, &sz);
  MPI_Comm_rank (MPI_COMM_WORLD, &rk);

  vsg_init_gdouble ();

  parse_args (argc, argv);

  if (nc_padding > 0)
    {
      if (_verbose && rk == 0)
        g_printerr ("%d: NodeCounter padding: %d\n", rk, nc_padding);
      _nc_padding_buffer = g_malloc (nc_padding * sizeof (char));
    }

  points = g_ptr_array_new ();

  lb.x = -1.; lb.y = -1.;
  ub.x = 1.; ub.y = 1.;

  /* create the tree */
  tree =
    vsg_prtree2d_new_full (&lb, &ub,
                           (VsgPoint2dLocFunc) vsg_vector2d_vector2d_locfunc,
                           (VsgPoint2dDistFunc) vsg_vector2d_dist,
                           NULL, _maxbox);

  if (_hilbert)
    {
      /* configure for hilbert curve order traversal */
      vsg_prtree2d_set_children_order_hilbert (tree);
    }

  if (_verbose)
    {
      MPI_Barrier (MPI_COMM_WORLD);
      g_printerr ("%d: set_parallel begin\n", rk);
    }

  vsg_prtree2d_set_parallel (tree, &pconfig);

  if (_verbose)
    {
      MPI_Barrier (MPI_COMM_WORLD);
      g_printerr ("%d: set_parallel ok\n", rk);
    }

  if (_verbose)
    {
      MPI_Barrier (MPI_COMM_WORLD);
      g_printerr ("%d: fill begin\n", rk);
    }

  _fill (tree, _np);

/*   /\* try one exterior point *\/ */
/*   if (sz > 1) */
/*     { */
/*       if (rk == 1) */
/*         { */
/*           Pt *pt; */

/*           _ref_count += _np+1; */

/*           pt = pt_alloc (TRUE, NULL); */
/*           pt->vector.x = ub.x+1.; */
/*           pt->vector.y = ub.y+1.; */
/*           pt->weight = _np+1; */

/*           vsg_prtree2d_insert_point (tree, pt); */
/*         } */
/*       else */
/*         { */
/*           _ref_count += _np+1; */
/*         } */

/*       vsg_prtree2d_migrate_flush (tree); */
/*       _distribute (tree); */
/*     } */


  if (_verbose)
    {
      MPI_Barrier (MPI_COMM_WORLD);
      g_printerr ("%d: fill ok\n", rk);
    }

  if (_do_write)
    {
      gchar fn[1024];
      FILE *f;

      sprintf (fn, "comm-%03d.svg", rk);
      f = fopen (fn, "w");

      fprintf (f, "\n<g style=\"stroke-width:0.01; stroke:black; " \
               "fill:none\">\n");
      fclose (f);
    }

  if (_verbose)
    {
      g_printerr ("%d: near/far traversal begin\n", rk);
          MPI_Barrier (MPI_COMM_WORLD);
      timer = g_timer_new ();
    }

  /* accumulate the point counts across the tree */
  _do_upward_pass (tree);

  /* do some near/far traversal */
  vsg_prtree2d_near_far_traversal (tree, (VsgPRTree2dFarInteractionFunc) _far,
                                   (VsgPRTree2dInteractionFunc) _near,
                                   &ret);
  /* accumulate from top to leaves */
  vsg_prtree2d_traverse (tree, G_PRE_ORDER, (VsgPRTree2dFunc) _down, NULL);

  if (_verbose)
    {
      MPI_Barrier (MPI_COMM_WORLD);

      g_printerr ("%d: near/far traversal ok elapsed=%f seconds\n", rk,
                  g_timer_elapsed (timer, NULL));

      g_timer_destroy (timer);
    }

  if (_do_write)
    {
      gchar fn[1024];
      FILE *f;

      MPI_Barrier (MPI_COMM_WORLD);

      g_sprintf (fn, "prtree2parallel-%03d.txt", rk);
      f = fopen (fn, "w");
      vsg_prtree2d_write (tree, f);
      fclose (f);

      _tree_write (tree, "prtree2parallel-");
    }

  if (_do_write)
    {
      gchar fn[1024];
      FILE *f;

      sprintf (fn, "comm-%03d.svg", rk);
      f = fopen (fn, "a");
      fprintf (f, "</g>\n");
      fclose (f);
    }

  if (_verbose)
    {
      gint near_count_sum, far_count_sum;
      MPI_Barrier (MPI_COMM_WORLD);
      g_printerr ("%d: processor msg stats fw=%d bw=%d\n",
                  rk, _fw_count, _bw_count);
      g_printerr ("%d: processor call stats near=%d far=%d\n",
                  rk, _near_count, _far_count);

      MPI_Reduce (&_near_count, &near_count_sum, 1, MPI_INT, MPI_SUM, 0,
                  MPI_COMM_WORLD);
      MPI_Reduce (&_far_count, &far_count_sum, 1, MPI_INT, MPI_SUM, 0,
                  MPI_COMM_WORLD);
      if (rk == 0)
        {
          g_printerr ("%d: mean call stats near=%f far=%f\n",
                      rk, (1.*near_count_sum)/sz, (1.*far_count_sum)/sz);
        }
    }

  /* check correctness of results */
  g_ptr_array_foreach (points, (GFunc) _check_pt_count,
                       &_ref_count);

  /* destroy the points */
  g_ptr_array_foreach (points, empty_array, NULL);
  g_ptr_array_free (points, TRUE);

  /* destroy the tree */
  vsg_prtree2d_free (tree);

  if (nc_padding > 0) g_free (_nc_padding_buffer);

  MPI_Finalize ();

  return ret;
}
Example #2
0
gint main (gint argc, gchar ** argv)
{
  gint ret = 0;

  VsgVector2d lb = {-1., -1.};
  VsgVector2d ub = {1., 1.};

  VsgPRTree2d *tree;
  VsgPRTree2d *treeref;
  gint i;
  gint ref_far_count;

  vsg_init_gdouble ();

  parse_args (argc, argv);

#ifdef VSG_HAVE_MPI
  if (_mpi)
    {
      MPI_Init (&argc, &argv);

      MPI_Comm_size (MPI_COMM_WORLD, &sz);
      MPI_Comm_rank (MPI_COMM_WORLD, &rk);

      if (counts != NULL)
        {
          gint i = 0;
          gint tmp = 0;

          while (counts[i+1] != NULL && i<rk) i ++;

	  if (sscanf (counts[i], "%u", &tmp) == 1)
            _expect_far_count = tmp;
	  else
	    test_printerr ("Invalid expected far count list (--expect-far-counts)\n");

          g_strfreev (counts);
        }
    }
#endif

  points_array = g_ptr_array_new ();

  if (rk == 0) _fill (&_npoints, points_array);
  else _npoints = 0;

  pointsref_array = g_ptr_array_sized_new (_npoints);
  for (i=0; i<_npoints; i++)
    {
      Pt *ptref = pt_alloc (TRUE, pointsref_array);
      memcpy (ptref, (Pt *) g_ptr_array_index (points_array, i), sizeof (Pt));
    }

  /* create the trees */
  tree =
    vsg_prtree2d_new_full (&lb, &ub,
                           (VsgPoint2dLocFunc) vsg_vector2d_vector2d_locfunc,
                           (VsgPoint2dDistFunc) vsg_vector2d_dist,
                           NULL, _maxbox);
  treeref = vsg_prtree2d_clone (tree);

  vsg_prtree2d_set_nf_isleaf (tree, _nf_isleaf_virtual_maxbox,
                              &_virtual_maxbox);

  vsg_parallel_vtable_set (&pconfig.node_data,
                           node_counter_alloc, NULL,
                           node_counter_destroy, NULL);
  vsg_prtree2d_set_node_data_vtable (tree, &pconfig.node_data);

  vsg_parallel_vtable_set (&prefconfig.node_data,
                           node_counter_alloc, NULL,
                           node_counter_destroy, NULL);
  vsg_prtree2d_set_node_data_vtable (treeref, &prefconfig.node_data);

#ifdef VSG_HAVE_MPI

  if (_mpi)
    {
      vsg_parallel_vtable_set (&pconfig.point,
                               pt_alloc, points_array,
                               pt_destroy, points_array);

      vsg_parallel_vtable_set (&prefconfig.point,
                               pt_alloc, pointsref_array,
                               pt_destroy, pointsref_array);

      vsg_parallel_vtable_set_parallel (&pconfig.point,
                                        pt_migrate_pack, NULL,
                                        pt_migrate_unpack, NULL,
                                        NULL, NULL,
                                        pt_visit_fw_pack, NULL,
                                        pt_visit_fw_unpack, NULL,
                                        NULL, NULL,
                                        pt_visit_bw_pack, NULL,
                                        pt_visit_bw_unpack, NULL,
                                        pt_visit_bw_reduce, NULL);

      vsg_parallel_vtable_set_parallel (&pconfig.node_data,
                                        nc_migrate_pack, NULL,
                                        nc_migrate_unpack, NULL,
                                        NULL, NULL,
                                        nc_visit_fw_pack, NULL,
                                        nc_visit_fw_unpack, NULL,
                                        nc_visit_fw_reduce, NULL,
                                        nc_visit_bw_pack, NULL,
                                        nc_visit_bw_unpack, NULL,
                                        nc_visit_bw_reduce, NULL);

      vsg_parallel_vtable_set_parallel (&prefconfig.point,
                                        pt_migrate_pack, NULL,
                                        pt_migrate_unpack, NULL,
                                        NULL, NULL,
                                        pt_visit_fw_pack, NULL,
                                        pt_visit_fw_unpack, NULL,
                                        NULL, NULL,
                                        pt_visit_bw_pack, NULL,
                                        pt_visit_bw_unpack, NULL,
                                        pt_visit_bw_reduce, NULL);

      vsg_parallel_vtable_set_parallel (&prefconfig.node_data,
                                        nc_migrate_pack, NULL,
                                        nc_migrate_unpack, NULL,
                                        NULL, NULL,
                                        nc_visit_fw_pack, NULL,
                                        nc_visit_fw_unpack, NULL,
                                        nc_visit_fw_reduce, NULL,
                                        nc_visit_bw_pack, NULL,
                                        nc_visit_bw_unpack, NULL,
                                        nc_visit_bw_reduce, NULL);

      vsg_prtree_parallel_config_set_communicator (&pconfig, MPI_COMM_WORLD);
      vsg_prtree_parallel_config_set_communicator (&prefconfig, MPI_COMM_WORLD);

      vsg_prtree2d_set_parallel (tree, &pconfig);

      vsg_prtree2d_set_parallel (treeref, &prefconfig);
    }
#endif

  /* insert points */
  for (i=0; i<_npoints; i++)
    {
      if (_verbose)
	{
	  test_printerr ("points[%d]: ", i);
	  vsg_vector2d_write (g_ptr_array_index (points_array, i), stderr);
	  g_printerr ("\n");
	}

      vsg_prtree2d_insert_point (tree, g_ptr_array_index (points_array, i));
      vsg_prtree2d_insert_point (treeref,
                                 g_ptr_array_index (pointsref_array, i));
    }

#ifdef VSG_HAVE_MPI
  if (_mpi)
    {
      vsg_prtree2d_migrate_flush (tree);
      vsg_prtree2d_migrate_flush (treeref);

      vsg_prtree2d_distribute_contiguous_leaves (tree);
      vsg_prtree2d_distribute_contiguous_leaves (treeref);
    }
#endif

  if (_write)
    {
      gchar fn[128];
      FILE *f;

      g_sprintf (fn, "tree-%03d.txt", rk);
      f = fopen (fn, "w");
      vsg_prtree2d_write (tree, f);
      fclose (f);
      g_sprintf (fn, "treeref-%03d.txt", rk);
      f = fopen (fn, "w");
      vsg_prtree2d_write (treeref, f);
      fclose (f);
    }

  /* compute neaf/far interactions for treeref */
  _far_count = 0;
  _do_upward_pass (treeref);
  vsg_prtree2d_near_far_traversal (treeref, (VsgPRTree2dFarInteractionFunc) _far,
                                   (VsgPRTree2dInteractionFunc) _near,
                                   &ret);
  vsg_prtree2d_traverse (treeref, G_PRE_ORDER, (VsgPRTree2dFunc) _down, NULL);
  ref_far_count = _far_count;

  /* compute neaf/far interactions for tree */
  _far_count = 0;
  _do_upward_pass (tree);
  vsg_prtree2d_near_far_traversal (tree, (VsgPRTree2dFarInteractionFunc) _far,
                                   (VsgPRTree2dInteractionFunc) _near,
                                   &ret);
  vsg_prtree2d_traverse (tree, G_PRE_ORDER, (VsgPRTree2dFunc) _down, NULL);

#ifdef VSG_HAVE_MPI
  if (_mpi)
    {
      /* migrate points back to processor 0 before checking */
      vsg_prtree2d_distribute_concentrate (tree, 0);
      vsg_prtree2d_distribute_concentrate (treeref, 0);
    }
#endif

  /* check results */
  for (i=0; i<points_array->len; i++)
    {
      Pt *pt = g_ptr_array_index (points_array, i);
      /* FIXME: what if pointsref and points are no longer in the same order? */
      Pt *ptref = g_ptr_array_index (pointsref_array, i);

      if (pt->count != ptref->count)
        {
          test_printerr ("error pt[");
          vsg_vector2d_write (&pt->vector, stderr);
          g_printerr ("]=%ld ptref[", pt->count);
          vsg_vector2d_write (&ptref->vector, stderr);
          g_printerr ("]=%ld\n", ptref->count);
        }
      else if (_verbose)
        {
          test_printerr ("correct comparison [");
          vsg_vector2d_write (&pt->vector, stderr);
          g_printerr ("]=%ld ptref[", pt->count);
          vsg_vector2d_write (&ptref->vector, stderr);
          g_printerr ("]=%ld\n", ptref->count);
        }
    }

  if ((_expect_far_count >= 0) && (_expect_far_count != _far_count))
    test_printerr ("far_count=%d != expected far_count=%d (ref=%d)\n",
                   _far_count, _expect_far_count, ref_far_count);
  else if (_verbose)
    test_printerr ("far_count=%d == expected far_count=%d (ref=%d)\n",
                   _far_count, _expect_far_count, ref_far_count);

  /* remove the points */
  for (i=0; i<points_array->len; i++)
    {
      vsg_prtree2d_remove_point (tree, g_ptr_array_index (points_array, i));
      vsg_prtree2d_remove_point (treeref,
                                 g_ptr_array_index (pointsref_array, i));
    }

  /* destroy the trees */
  vsg_prtree2d_free (tree);
  vsg_prtree2d_free (treeref);

  for (i=0; i<points_array->len; i++)
    pt_destroy (g_ptr_array_index (points_array, i), FALSE, points_array);

  for (i=0; i<pointsref_array->len; i++)
    pt_destroy (g_ptr_array_index (pointsref_array, i), FALSE, pointsref_array);


  g_ptr_array_free (points_array, TRUE);
  g_ptr_array_free (pointsref_array, TRUE);

#ifdef VSG_HAVE_MPI
  if (_mpi)
    MPI_Finalize ();
#endif

  return ret;
}