Ejemplo n.º 1
0
int PX(local_size_remap_3dto2d_transposed)(
    int rnk_n, const INT *n, INT howmany, 
    MPI_Comm comm_cart_3d, 
    unsigned transp_flag, unsigned trafo_flag,
    INT *local_ni, INT *local_i_start,
    INT *local_no, INT *local_o_start 
    )
{
  INT mem=1, mem_tmp;
  int p0, p1, q0, q1, rnk_pm;
  INT nb, nt, N0, N1, h0, h1, hm, blk0, blk1;
  INT local_nm[3];
  INT iblk[3], mblk[3], oblk[3], pn[3];
  MPI_Comm icomms[3], mcomms[3], ocomms[3];
  MPI_Comm comm_q0, comm_q1;

  /* remap only works for 3d data on 3d procmesh */
  if(rnk_n != 3)
    return 0;

  MPI_Cartdim_get(comm_cart_3d, &rnk_pm);
  if(rnk_pm != 3)
    return 0;

  PX(get_procmesh_dims_2d)(comm_cart_3d, &p0, &p1, &q0, &q1);

  PX(physical_dft_size)(rnk_n, n, trafo_flag,
      pn);

  /* handle r2c and c2r like c2c */
  if(trafo_flag & PFFTI_TRAFO_RDFT)
    trafo_flag = PFFTI_TRAFO_C2C;

  init_blks_comms_local_size(pn, comm_cart_3d,
      iblk, mblk, oblk, icomms, mcomms, ocomms,
      local_ni, local_nm, local_no);

  /* n0/p0 x n1/p1 x n2/(q0*q1) -> n2/(q0*q1) x n0/p0 x n1/p1 */
  nb = local_ni[0] * local_ni[1];
  nt = local_ni[2];
 
  mem_tmp = PX(local_size_sertrafo)(
        nb, 1, &nt, howmany, trafo_flag);
  mem = MAX(mem, mem_tmp);

  /* n2/(q0*q1) x n0/p0 x n1/p1 -> n2/q0 x n0/p0 x n1/(p1*q1) */
  N0 = local_ni[1]; h0 = 1;
  N1 = local_nm[2]; h1 = local_ni[0];
  blk0 = mblk[1];
  blk1 = iblk[2];
  hm = 1; /* set hm to 1 since mem will be in units of real/complex */

  PX(split_cart_procmesh_for_3dto2d_remap_q1)(comm_cart_3d, &comm_q1);
  mem_tmp = PX(local_size_global_transp)(
      N0, N1, h0, h1, hm, blk0, blk1, comm_q1);
  mem = MAX(mem, mem_tmp);
  MPI_Comm_free(&comm_q1);

  /* n2/q0 x n0/p0 x n1/(p1*q1) -> n2 x n0/(p0*q0) x n1/(p1*q1) */
  N0 = local_nm[0]; h0 = local_nm[1];
  N1 = local_no[2]; h1 = 1;
  blk0 = oblk[0];
  blk1 = mblk[2];
  hm = 1; /* set hm to 1 since mem will be in units of real/complex */

  PX(split_cart_procmesh_for_3dto2d_remap_q0)(comm_cart_3d, &comm_q0);
  mem_tmp = PX(local_size_global_transp)(
      N0, N1, h0, h1, hm, blk0, blk1, comm_q0);
  mem = MAX(mem, mem_tmp);
  MPI_Comm_free(&comm_q0);

  /* n2 x n0/(p0*q0) x n1/(p1*q1) -> n0/(p0*q0) x n1/(p1*q1) x n2 */
  nb = local_no[2];
  nt = local_no[0] * local_no[1];
  
  mem_tmp = PX(local_size_sertrafo)(
        nb, 1, &nt, howmany, trafo_flag);
  mem = MAX(mem, mem_tmp);

  /* take care of transposed data ordering */
  if(transp_flag & PFFT_TRANSPOSED_OUT){
    get_local_n_3d(pn, iblk, icomms, local_ni);
    get_local_start_3d(pn, iblk, icomms, local_i_start);
    get_local_n_3d(pn, oblk, ocomms, local_no);
    get_local_start_3d(pn, oblk, ocomms, local_o_start);
  } else {
    get_local_n_3d(pn, iblk, icomms, local_no);
    get_local_start_3d(pn, iblk, icomms, local_o_start);
    get_local_n_3d(pn, oblk, ocomms, local_ni);
    get_local_start_3d(pn, oblk, ocomms, local_i_start);
  }

  /* free communicators */
  for(int t=0; t<3; t++){
    MPI_Comm_free(&icomms[t]);
    MPI_Comm_free(&mcomms[t]);
    MPI_Comm_free(&ocomms[t]);
  }

  return mem;
} 
Ejemplo n.º 2
0
/* ouput is written to 'in', also for outofplace */
remap_3dto2d_plan PX(plan_remap_3dto2d_transposed)(
    int rnk_n, const INT *n, INT howmany, 
    MPI_Comm comm_cart_3d, R *in_user, R *out_user, 
    unsigned transp_flag, unsigned trafo_flag,
    unsigned opt_flag, unsigned io_flag, unsigned fftw_flags 
    )
{
  int rnk_pm;
  INT nb, nt, N0, N1, h0, h1, hm, blk0, blk1;
  INT local_ni[3], local_nm[3], local_no[3];
  INT iblk[3], mblk[3], oblk[3], pn[3];
  MPI_Comm icomms[3], mcomms[3], ocomms[3];
  MPI_Comm comm_q0, comm_q1;
  R *in=in_user, *out=out_user;
  remap_3dto2d_plan ths;

  /* remap only works for 3d data on 3d procmesh */
  if(rnk_n != 3)
    return NULL;

  MPI_Cartdim_get(comm_cart_3d, &rnk_pm);
  if(rnk_pm != 3)
    return NULL;

  ths = remap_3dto2d_mkplan();

  PX(physical_dft_size)(rnk_n, n, trafo_flag,
      pn);

  /* handle r2c and c2r like c2c */
  if(trafo_flag & PFFTI_TRAFO_RDFT)
    trafo_flag = PFFTI_TRAFO_C2C;

  init_blks_comms_local_size(pn, comm_cart_3d,
      iblk, mblk, oblk, icomms, mcomms, ocomms,
      local_ni, local_nm, local_no);

  /* n0/p0 x n1/p1 x n2/(q0*q1) -> n2/(q0*q1) x n0/p0 x n1/p1 */
  nb = local_ni[0] * local_ni[1];
  nt = local_ni[2];
 
  /* plan TRANSPOSED_IN in opposite direction */
  if(transp_flag & PFFT_TRANSPOSED_IN){
    if(~io_flag & PFFT_DESTROY_INPUT)
      in = out; /* default: compute in-place plans on 'out' in order to preserve inputs */
    ths->local_transp[1] = PX(plan_sertrafo)(
        nb, 1, &nt, howmany, out, in, 0, NULL,
        trafo_flag| PFFTI_TRAFO_SKIP, transp_flag, 0,
        opt_flag, fftw_flags);
  } else {
    ths->local_transp[0] = PX(plan_sertrafo)(
        nb, 1, &nt, howmany, in, out, 0, NULL,
        trafo_flag| PFFTI_TRAFO_SKIP, transp_flag, 0,
        opt_flag, fftw_flags);
    if(~io_flag & PFFT_DESTROY_INPUT)
      in = out; /* default: compute in-place plans on 'out' in order to preserve inputs */
  }

  /* n2/(q0*q1) x n0/p0 x n1/p1 -> n2/q0 x n0/p0 x n1/(p1*q1) */
  N0 = local_ni[1]; h0 = 1;
  N1 = local_nm[2]; h1 = local_ni[0];
  blk0 = mblk[1];
  blk1 = iblk[2];
  hm = howmany * (trafo_flag & PFFTI_TRAFO_C2C) ? 2 : 1;

  PX(split_cart_procmesh_for_3dto2d_remap_q1)(comm_cart_3d, &comm_q1);
  if(transp_flag & PFFT_TRANSPOSED_IN)
    ths->global_remap[1] = PX(plan_global_transp)(
        N1, N0, h1, h0, hm, blk1, blk0,
        comm_q1, in, out, PFFT_TRANSPOSED_OUT, fftw_flags);
  else
    ths->global_remap[0] = PX(plan_global_transp)(
        N0, N1, h0, h1, hm, blk0, blk1,
        comm_q1, out, in, PFFT_TRANSPOSED_IN, fftw_flags);
  MPI_Comm_free(&comm_q1);

  /* n2/q0 x n0/p0 x n1/(p1*q1) -> n2 x n0/(p0*q0) x n1/(p1*q1) */
  N0 = local_nm[0]; h0 = local_nm[1];
  N1 = local_no[2]; h1 = 1;
  blk0 = oblk[0];
  blk1 = mblk[2];
  hm = howmany * (trafo_flag & PFFTI_TRAFO_C2C) ? 2 : 1;

  PX(split_cart_procmesh_for_3dto2d_remap_q0)(comm_cart_3d, &comm_q0);
  if(transp_flag & PFFT_TRANSPOSED_IN)
    ths->global_remap[0] = PX(plan_global_transp)(
        N1, N0, h1, h0, hm, blk1, blk0,
        comm_q0, out, in, PFFT_TRANSPOSED_OUT, fftw_flags);
  else
    ths->global_remap[1] = PX(plan_global_transp)(
        N0, N1, h0, h1, hm, blk0, blk1,
        comm_q0, in, out, PFFT_TRANSPOSED_IN, fftw_flags);
  MPI_Comm_free(&comm_q0);

  /* n2 x n0/(p0*q0) x n1/(p1*q1) -> n0/(p0*q0) x n1/(p1*q1) x n2 */
  nb = local_no[2];
  nt = local_no[0] * local_no[1];
  
  if(transp_flag & PFFT_TRANSPOSED_IN){
    if(~io_flag & PFFT_DESTROY_INPUT){
      /* restore pointers to 'in_user' and 'out_user' in order to compute the first step out-of-place */
      in = in_user;
    }

    ths->local_transp[0] = PX(plan_sertrafo)(
        nb, 1, &nt, howmany, in, out, 0, NULL,
        trafo_flag| PFFTI_TRAFO_SKIP, transp_flag, 0,
        opt_flag, fftw_flags);
  } else {
    ths->local_transp[1] = PX(plan_sertrafo)(
        nb, 1, &nt, howmany, out, in, 0, NULL,
        trafo_flag| PFFTI_TRAFO_SKIP, transp_flag, 0,
        opt_flag, fftw_flags);
  }

  /* free communicators */
  for(int t=0; t<3; t++){
    MPI_Comm_free(&icomms[t]);
    MPI_Comm_free(&mcomms[t]);
    MPI_Comm_free(&ocomms[t]);
  }

  return ths;
} 
Ejemplo n.º 3
0
FORT_DLL_SPEC void FORT_CALL mpi_cartdim_get_ ( MPI_Fint *v1, MPI_Fint *v2, MPI_Fint *ierr ){
    *ierr = MPI_Cartdim_get( (MPI_Comm)(*v1), v2 );
}
Ejemplo n.º 4
0
  void Communication::prepare(p3m_float box_l[3]) {
    P3M_DEBUG(printf( "  P3M::Communication::prepare() started...\n"));

    /* Test whether the communicator is cartesian and correct dimensionality */
    bool comm_is_cart = false;
    int status;

    MPI_Topo_test(mpicomm_orig, &status);
    if (status == MPI_CART) {
      /* Communicator is cartesian, so test dimensionality */
      int ndims;
      MPI_Cartdim_get(mpicomm_orig, &ndims);
      if (ndims == 3) {
        /* Correct dimensionality, so get grid and test periodicity */
        int periodicity[3];
        MPI_Cart_get(mpicomm_orig, 3, node_grid,
                     periodicity, node_pos);
        if (periodicity[0] && periodicity[1] && periodicity[2]) {
          /* If periodicity is correct, we can just use this communicator */
          mpicomm = mpicomm_orig;
          /* get the rank */
          MPI_Comm_rank(mpicomm, &rank);
          comm_is_cart = true;
        }
      }
    }

    /* otherwise, we have to set up the cartesian communicator */
    if (!comm_is_cart) {
      P3M_DEBUG(printf( "    Setting up cartesian communicator...\n"));

      node_grid[0] = 0;
      node_grid[1] = 0;
      node_grid[2] = 0;

      /* compute node grid */
      MPI_Dims_create(size, 3, node_grid);

#ifdef P3M_ENABLE_INFO
      if (onMaster())
    	  printf("    node_grid=%dx%dx%d\n", node_grid[0], node_grid[1], node_grid[2]);
#endif

      /* create communicator */
      int periodicity[3] = {1, 1, 1};
      MPI_Cart_create(mpicomm_orig, 3, node_grid,
                      periodicity, 1, &mpicomm);

      /* get the rank */
      MPI_Comm_rank(mpicomm, &rank);
      /* get node pos */
      MPI_Cart_coords(mpicomm, rank, 3, node_pos);
    }
    
    /* fetch neighborhood info */
    for (int dir = 0; dir < 3; dir++) {
      MPI_Cart_shift(mpicomm, dir, 1,
                     &node_neighbors[2*dir],
                     &node_neighbors[2*dir+1]);
      P3M_DEBUG_LOCAL(printf( "    %d: dir=%d: n1=%d n2=%d\n", rank, dir, \
                              node_neighbors[2*dir],		\
                              node_neighbors[2*dir+1]));
    }

    /* init local points */
    for (int i=0; i< 3; i++) {
      local_box_l[i] = 0.0;
      my_left[i] = 0.0;
      my_right[i] = 0.0;
    }

    /* compute box limits */
    for(p3m_int i = 0; i < 3; i++) {
      local_box_l[i] = box_l[i]/(p3m_float)node_grid[i];
      my_left[i]   = node_pos[i]    *local_box_l[i];
      my_right[i]  = (node_pos[i]+1)*local_box_l[i];
    }
    P3M_DEBUG(printf("    local_box_l=" F3FLOAT "\n"                      \
                     "    my_left=" F3FLOAT "\n"                          \
                     "    my_right=" F3FLOAT "\n",                        \
                     local_box_l[0],                                \
                     local_box_l[1],                                \
                     local_box_l[2],                                \
                     my_left[0], my_left[1], my_left[2], \
                     my_right[0], my_right[1], my_right[2] \
                     ));

    P3M_DEBUG(printf("  P3M::Communication::prepare() finished.\n"));
  }
Ejemplo n.º 5
0
int main( int argc, char **argv )
{
    int              rank, size, i;
    int              errors=0;
    int              dims[NUM_DIMS];
    int              periods[NUM_DIMS];
    int              coords[NUM_DIMS];
    int              new_coords[NUM_DIMS];
    int              reorder = 0;
    MPI_Comm         comm_temp, comm_cart, new_comm;
    int              topo_status;
    int              ndims;
    int              new_rank;
    int              remain_dims[NUM_DIMS];
    int              newnewrank;

    MPI_Init( &argc, &argv );

    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
    MPI_Comm_size( MPI_COMM_WORLD, &size );

    /* Clear dims array and get dims for topology */
    for(i=0;i<NUM_DIMS;i++) { dims[i] = 0; periods[i] = 0; }
    MPI_Dims_create ( size, NUM_DIMS, dims );

    /* Make a new communicator with a topology */
    MPI_Cart_create ( MPI_COMM_WORLD, 2, dims, periods, reorder, &comm_temp );
    MPI_Comm_dup ( comm_temp, &comm_cart );

    /* Determine the status of the new communicator */
    MPI_Topo_test ( comm_cart, &topo_status );
    if (topo_status != MPI_CART) errors++;

    /* How many dims do we have? */
    MPI_Cartdim_get( comm_cart, &ndims );
    if ( ndims != NUM_DIMS ) errors++;

    /* Get the topology, does it agree with what we put in? */
    for(i=0;i<NUM_DIMS;i++) { dims[i] = 0; periods[i] = 0; }
    MPI_Cart_get ( comm_cart, NUM_DIMS, dims, periods, coords );

    /* Check that the coordinates are correct */
#if NUM_DIMS == 2
    if (rank != coords[1] + coords[0] * dims[1]) {
	errors++;
	fprintf( stderr, 
"Did not get expected coordinate (row major required by MPI standard 6.2)\n" );
    }
#endif
    /* Does the mapping from coords to rank work? */
    MPI_Cart_rank ( comm_cart, coords, &new_rank );
    if ( new_rank != rank ) errors++;

    /* Does the mapping from rank to coords work */
    MPI_Cart_coords ( comm_cart, rank, NUM_DIMS, new_coords );
    for (i=0;i<NUM_DIMS;i++) 
      if ( coords[i] != new_coords[i] ) 
	errors++;

    /* Let's shift in each dimension and see how it works!   */
    /* Because it's late and I'm tired, I'm not making this  */
    /* automatically test itself.                            */
    for (i=0;i<NUM_DIMS;i++) {
      int source, dest;
      MPI_Cart_shift(comm_cart, i, 1, &source, &dest);
#ifdef VERBOSE      
      printf ("[%d] Shifting %d in the %d dimension\n",rank,1,i);
      printf ("[%d]    source = %d  dest = %d\n",rank,source,dest); 
#endif
    }

    /* Subdivide */
    remain_dims[0] = 0; 
    for (i=1; i<NUM_DIMS; i++) remain_dims[i] = 1;
    MPI_Cart_sub ( comm_cart, remain_dims, &new_comm );

    /* Determine the status of the new communicator */
    MPI_Topo_test ( new_comm, &topo_status );
    if (topo_status != MPI_CART) errors++;

    /* How many dims do we have? */
    MPI_Cartdim_get( new_comm, &ndims );
    if ( ndims != NUM_DIMS-1 ) errors++;

    /* Get the topology, does it agree with what we put in? */
    for(i=0;i<NUM_DIMS-1;i++) { dims[i] = 0; periods[i] = 0; }
    MPI_Cart_get ( new_comm, ndims, dims, periods, coords );
    
    /* Does the mapping from coords to rank work? */
    MPI_Comm_rank ( new_comm, &newnewrank );
    MPI_Cart_rank ( new_comm, coords, &new_rank );
    if ( new_rank != newnewrank ) errors++;

    /* Does the mapping from rank to coords work */
    MPI_Cart_coords ( new_comm, new_rank, NUM_DIMS -1, new_coords );
    for (i=0;i<NUM_DIMS-1;i++) 
      if ( coords[i] != new_coords[i] ) 
	errors++;

    /* We're at the end */
    MPI_Comm_free( &new_comm );
    MPI_Comm_free( &comm_temp );
    MPI_Comm_free( &comm_cart );
    Test_Waitforall( );
    if (errors) printf( "[%d] done with %d ERRORS!\n", rank,errors );
    MPI_Finalize();
    return 0;
}
Ejemplo n.º 6
0
/*
    Check that the MPI implementation properly handles zero-dimensional
    Cartesian communicators - the original standard implies that these
    should be consistent with higher dimensional topologies and thus
    these should work with any MPI implementation.  MPI 2.1 made this
    requirement explicit.
*/
int main(int argc, char *argv[])
{
    int errs = 0;
    int size, rank, ndims;
    MPI_Comm comm, newcomm;

    MTest_Init(&argc, &argv);

    /* Create a new cartesian communicator in a subset of the processes */
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    if (size < 2) {
        fprintf(stderr, "This test needs at least 2 processes\n");
        MPI_Abort(MPI_COMM_WORLD, 1);
    }

    MPI_Cart_create(MPI_COMM_WORLD, 0, NULL, NULL, 0, &comm);

    if (comm != MPI_COMM_NULL) {
        int csize;
        MPI_Comm_size(comm, &csize);
        if (csize != 1) {
            errs++;
            fprintf(stderr, "Sizes is wrong in cart communicator.  Is %d, should be 1\n", csize);
        }

        /* This function is not meaningful, but should not fail */
        MPI_Dims_create(1, 0, NULL);

        ndims = -1;
        MPI_Cartdim_get(comm, &ndims);
        if (ndims != 0) {
            errs++;
            fprintf(stderr, "MPI_Cartdim_get: ndims is %d, should be 0\n", ndims);
        }

        /* this function should not fail */
        MPI_Cart_get(comm, 0, NULL, NULL, NULL);

        MPI_Cart_rank(comm, NULL, &rank);
        if (rank != 0) {
            errs++;
            fprintf(stderr, "MPI_Cart_rank: rank is %d, should be 0\n", rank);
        }

        /* this function should not fail */
        MPI_Cart_coords(comm, 0, 0, NULL);

        MPI_Cart_sub(comm, NULL, &newcomm);
        ndims = -1;
        MPI_Cartdim_get(newcomm, &ndims);
        if (ndims != 0) {
            errs++;
            fprintf(stderr, "MPI_Cart_sub did not return zero-dimensional communicator\n");
        }

        MPI_Barrier(comm);

        MPI_Comm_free(&comm);
        MPI_Comm_free(&newcomm);
    } else if (rank == 0) {
        errs++;
        fprintf(stderr, "Communicator returned is null!");
    }

    MTest_Finalize(errs);


    return MTestReturnValue(errs);
}