I'm trying to write a routine which unpicks user defined datatypes
using MPI_Type_get_{envelope,contents}.  I'm having a problem that
a derived type returned by a call of MPI_Type_get_contents, when handed
onwards to MPI_Type_get_envelope, causes the system to bomb:

[suse10:15004] *** An error occurred in MPI_Type_get_envelope
[suse10:15004] *** on communicator MPI_COMM_WORLD
[suse10:15004] *** MPI_ERR_INTERN: internal error
[suse10:15004] *** MPI_ERRORS_ARE_FATAL (goodbye)

Close inspection of the MPI2 specification for MPI_Type_get_envelope
does not appear to reveal any limitations on the types or 
committedness-state of types that may be passed to MPI_Type_get_envelope.

This is with Open MPI 1.0.1 on SuSE 10.0 (x86), built from source.
This build otherwise appears to work and has run various MPI apps
successfully over the past month.

A test case is attached.  What am I doing wrong?

J
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "mpi.h"

/* Generate a _contiguous type */
static MPI_Datatype tycon_Contiguous ( int count, MPI_Datatype t )
{
   MPI_Datatype t2;  
   int          r = MPI_Type_contiguous( count, t, &t2 );
   assert(r == MPI_SUCCESS);
   return t2;
}

/* Generate a simple 2-element _struct type w/ given tys and
   displacements */
static MPI_Datatype tycon_Struct2 ( MPI_Datatype t1, int disp1, 
                                    MPI_Datatype t2, int disp2 )
{
   int          blocklens[2];
   MPI_Aint     disps[2];
   MPI_Datatype tys[2];
   MPI_Datatype tres;
   int          r;
   blocklens[0] = blocklens[1] = 1;
   disps[0] = disp1;
   disps[1] = disp2;
   tys[0] = t1;
   tys[1] = t2;
   r = MPI_Type_struct( 2, blocklens, disps, tys, &tres );
   assert(r == MPI_SUCCESS);
   return tres;
}

/* Generate a simple struct type, then try to unravel it with
   MPI_Type_get_{envelope,contents}. */

int main ( int argc, char** argv )
{
    int rank, size, r;
    MPI_Datatype t1, t2;

    MPI_Init( &argc, &argv );
    MPI_Comm_size( MPI_COMM_WORLD, &size );
    MPI_Comm_rank( MPI_COMM_WORLD, &rank );

    if (rank == 0) {

    t1 = tycon_Contiguous(4, MPI_DOUBLE);
    /* t1 = {(double,0),(double,8),(double,16),(double,24)} */

    t2 = tycon_Struct2(t1, 0, MPI_CHAR, 48);
    /* t2 = {(double,0),(double,8),(double,16),(double,24), (char,48)} */

    /* Disassemble the struct type (t2). */
    int n_ints, n_addrs, n_dtys, combiner;
    r = MPI_Type_get_envelope( t2, &n_ints, &n_addrs, &n_dtys, &combiner );
    assert(r == MPI_SUCCESS);

    assert(n_ints == 3 && n_addrs == 2 && n_dtys == 2);
    assert(combiner == MPI_COMBINER_STRUCT);

    int*          ints  = malloc(n_ints * sizeof(int));
    MPI_Aint*     addrs = malloc(n_addrs * sizeof(MPI_Aint));
    MPI_Datatype* dtys  = malloc(n_dtys * sizeof(MPI_Datatype));
    r = MPI_Type_get_contents( t2, n_ints, n_addrs, n_dtys,
                                   ints, addrs, dtys );
    assert(r == MPI_SUCCESS);

    /* Peer at the first element of the struct, which is (a copy of)
       t1. */
    assert(dtys[1] == MPI_CHAR);
    printf("before second MPI_Type_get_envelope\n");
    /* XXXXXXX this is the call that dies */
    r = MPI_Type_get_envelope( dtys[0], 
                               &n_ints, &n_addrs, &n_dtys, &combiner );
    /* XXXXXXX we never get here */
    printf("after second MPI_Type_get_envelope\n");
    assert(r == MPI_SUCCESS);     

    } /* rank==0 */

    MPI_Finalize();
    return 0;
}

Reply via email to