Your disp arrays are wrong -- they need to be cumulative displacements:
{0, sizeof(double), sizeof(double) * 2, sizeof(double) * 3, ... }
That, or you could just specify 1 type with a count of 4 (or 5) and
have a single displacement (see disclaimer).
Also, you might try using MPI_TYPE_VECTOR -- since you have an array of
all the same type, this is considerably simpler than using
MPI_TYPE_STRUCT. Disclaimer: you can't be absolutely sure that the
compiler will lay it out in memory exactly as it is listed in your
struct definition, but most compilers do. Additionally, you could
change your definition to be:
typedef struct {
double foo[5];
} Grid;
and then you would be guaranteed that they would be laid out in memory
such that MPI_TYPE_VECTOR (or TYPE_STRUCT with one type and a count >
1) would work.
On Sep 28, 2005, at 8:30 AM, L WK wrote:
> Hi all,
> I need you help in self-defined datatype. I have written the following
> code
>
> #include <mpi.h>
> #include <stdio.h>
>
> #define FIVE
>
> #define NCOLS 4
> #define NROWS 4
>
> #ifdef FIVE
> typedef struct
> {
> double r, c, d, v, f;
> } Grid;
> #else
> typedef struct
> {
> double r, c, v, d;
> } Grid;
> #endif
>
> Grid data[NROWS][NCOLS];
>
> int myrank, NODENUM;
> int SIZE;
>
> MPI_Datatype GRID;
> MPI_Datatype ROW;
>
>
> void initialize(int argc, char **argv)
> { int errcode, i, j;
> #ifndef FIVE
> int S=4;
> MPI_Datatype type[4] = { MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE,
> MPI_DOUBLE};
> int blocklen[4] = { 1, 1, 1, 1 };
> MPI_Aint disp[4] = { 0, sizeof(double), sizeof(double),
> sizeof(double)};
> #else
> int S=5;
> MPI_Datatype type[5] = { MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE,
> MPI_DOUBLE, MPI_DOUBLE};
> int blocklen[5] = { 1, 1, 1, 1, 1 };
> MPI_Aint disp[5] = { 0, sizeof(double), sizeof(double),
> sizeof(double), sizeof(double)};
> #endif
>
> errcode = MPI_Init(&argc, &argv);
> if (errcode == MPI_SUCCESS)
> {
> MPI_Comm_rank( MPI_COMM_WORLD, &myrank );
> MPI_Comm_size( MPI_COMM_WORLD, &NODENUM );
>
> SIZE = NROWS/NODENUM;
>
> MPI_Type_struct( S, blocklen, disp, type, &GRID );
> MPI_Type_commit( &GRID );
>
> MPI_Type_vector( NCOLS, 1, 1, GRID, &ROW );
> MPI_Type_commit( &ROW );
>
> for (i=0; i<NROWS; i++)
> {
> for (j=0; j<NCOLS; j++)
> {
> data[i][j].r = (double)(i+1);
> data[i][j].c = (double)(j+1);
> data[i][j].d = 1.0;
> data[i][j].v = (double)(i*NCOLS + j + 1);
> #ifdef FIVE
> data[i][j].f = 2.0;
> #endif
> }
> }
> }
> }
>
>
> void finalize(void)
> {
> MPI_Type_free(&GRID);
> MPI_Type_free(&ROW);
> MPI_Finalize();
> }
>
> int main(int argc, char *argv[])
> {
> initialize(argc, argv);
>
> MPI_Barrier( MPI_COMM_WORLD );
> /* show data here */
>
> if (myrank==0)
> {
> MPI_Send( &data[0][0], 1, ROW, 1, 22, MPI_COMM_WORLD );
> }
> else MPI_Recv( &data[SIZE][0], 1, ROW, 0, 22, MPI_COMM_WORLD,
> MPI_STATUS_IGNORE );
>
> MPI_Barrier( MPI_COMM_WORLD );
> /* show data here */
>
> finalize();
> return 0;
> }
>
> The program is running over two computers. At the beginning, each
> computer holds all the data stored in 'data' array. I am going to
> define
> a new datatype for a row and send the first row of the array from node
> 0
> to node 1. However, the result is not that I wanted. I print the whole
> array at node 1
>
> The original array is
>
> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
>
> if macro 'FIVE' is defined, i.e. five data defined in the struct, I got
>
> 1 2 3 4 5 6 7 8 1 10 11 12 13 14 15 16
> if macro 'FIVE' is undefine, i.e. only four data defined in the struct,
> I got
>
> 1 2 3 4 5 6 7 8 1 2 11 12 13 14 15 16
> But I an intending to get
>
> 1 2 3 4 5 6 7 8 1 2 3 4 <----- a row received from the
> first row on node 0
> 13 14 15 16
>
> _________________________________________________________________
> ÏíÓÃÊÀ½çÉÏ×î´óµÄµç×ÓÓʼþϵͳ¡ª MSN Hotmail¡£ http://www.hotmail.com
> _______________________________________________
> This list is archived at http://www.lam-mpi.org/MailArchives/lam/
--
{+} Jeff Squyres
{+} The Open MPI Project
{+} http://www.open-mpi.org/
|