Subject: Buffer descriptor generalization

From: [email-masked] (Ricardo Schmutzer von Oldershausen)
Date: Wed, 30 Jun 93 12:17:09 AST

Hello !

I studied James Cownie's extension for communication buffers (described
in the draft of June 20) this weekend and even tried to write some code
(actually a skeleton) of how you could implement buffers with the extension.
Doing this I came along a "little detail" (or I may be missing
something... ):

Which is the main difference between bound and unbound buffers ?

Bound buffers describe a variable in memory.
Therefore the start argument is used as a pointer to a memory location.

Unbound buffers describe a type (usually a structure or array; I agree
with the restriction that a unbound buffer should only describe a 
composite variable).  As we describe a type, no memory location should
be involved. Therefore unbound buffers need to save the offsets of
each element of the structure to the beginning of the structure (or
to the first element of the structure, if you want).  I will call this
the "base address".
As the MPI_APPEND_* functions receive a pointer (the start argument),
the offset must be constructed using a KNOWN base address: 

offset = start - base 

The base address is the address of the first element of the structure.
This address should be known as it is supplied in the first MPI_APPEND_*
function (well, if it isn't the first, you can find it because it is
the lowest start address supplied).

But, and here I come to my "little problem", what happens if we do NOT
want to transmit the first element of the structure ?

Example:

Let's suppose your program uses the same structure as described in the
3. example of the draft:

struct foostruct {
    int i;
    double d[5];
    char b;
};

struct foostruct foo[100];

but you want to transmit only the array of doubles and the character:

MPI_BUFFER t;
MPI_BUFFER fb;

mpi_create_buffer(&t, MPI_EPHEMERAL);
mpi_create_buffer(&fb, MPI_PERSISTENT);

/* describe the data type in t using only d and b */
mpi_append_contiguous(t, &((struct foostruct *)0)->d, 1, MPI_DOUBLE);
mpi_append_contiguous(t, &((struct foostruct *)0)->c, 1, MPI_BYTE);

/* describe foo itself */
mpi_append_contiguous(fb, &foo, 100, t);
mpi_commit(fb);

Did somebody tell the buffer t that the pointers are based on NULL pointers,
i.e. that the base address is NULL ?
Acording to the above description the base address is taken to be the 
lowest start address supplied, here it is the address of the array d.
So, the structure actually described is:

struct foostruct {
    double d[5];
    char b;
};

Note that the above problem arises independently if we describe struct
foostruct with NULL pointers or with pointers to a variable of the same
type, and independently of which alternative of the proposed extension 
we use (distinguishing syntactically between bound and unbound buffers
or not).

I do not know if there is some simple solution to solve the above problem,
but it seems to me that there are two:

1. Restrict that unbound buffers may be described only with NULL
   pointers (in this case the base address is always NULL, and the
   above example would work).

2. Demand that the start argument of the first description of unbound
   buffers MUST be the base address.  The above example would have to
   be rewritten as:

/* describe the data type suppling first the base address */
/* Note that count is 0 in the first MPI_APPEND_*         */
mpi_append_contiguous(t, &((struct foostruct *)0)->i, 0, MPI_INT);
mpi_append_contiguous(t, &((struct foostruct *)0)->d, 1, MPI_DOUBLE);
mpi_append_contiguous(t, &((struct foostruct *)0)->c, 1, MPI_BYTE);

I do not like the first solution, because not everybody will be happy
having to use NULL pointers (how would you do this in FORTRAN ?!), so
the second solution seems to be better.

===========================================================================

Comments about the first second alternative described in the draft:

As bound buffers describe variables and unbound buffers types, we
should distinguish between bound and unbound buffers (who knows if
later on, somebody finds another restriction of unbound buffers),
therefore I prefer the second alternative.

But as it is a little bit difficult to create a unbound buffer with
the MPI_UNBIND function (create a first buffer, describe it, create a
second buffer, call MPI_UNBIND and finally free the first buffer), I 
would suggest to include a new argument to the MPI_CREATE_BUFFER function
that can take two values: MPI_BOUND and MPI_UNBOUND indicating if we want
to describe a bound or unbound buffer:

MPI_CREATE_BUFFER(buffer, type, persistence)

OUT buffer:     buffer handle
IN type:        state type of buffer MPI_BOUND or MPI_UNBOUND
IN persistence: buffer persistence

The start pointers supplied to the MPI_APPEND_* functions describing 
the unbound buffer should be restricted to be:

a) all based on NULL pointers of the same type or
b) all based on a pointer to a single composite variable

The first MPI_APPEND_* function must be given a pointer to:

a) the first element of the composite type or
b) the first element of the composite variable

independent if it should be transmited or not (in the later case a count
of 0 should be supplied to the MPI_APPEND_CONTIGUOUS function).

The unbound buffer should be commited (the saved start pointers could be
replaced by the corresponding offsets taking the first start pointer as
the base address). This also keeps all MPI_APPEND_* functions describing
the unbound buffer easily identifiable to verify the above restrictions.

MPI_APPEND_* functions should receive only commited unbound buffers
as datatypes.

If the unbound buffer is declared ephemeral, it should be freed after
it's first use in a MPI_APPEND_* function.

Regards,

Ricardo
-- 
+----------------------+---------------------------------+--------------+
| Ricardo A. Schmutzer | Internet: [email-masked]    | Conectividad |
| PUC, Santiago, Chile |                                 | Distr. Comp. |
+----------------------+---------------------------------+--------------+

---

From: [email-masked] (Ricardo Schmutzer von Oldershausen)
Date: Mon, 5 Jul 93 12:25:09 AST

Hello ...

Please, do NOT read the first part of my previous post !

I feel rather silly, because it is nonsense, and the answer
to my (nonexistent) problem is rather simple as the structure
I described is not contiguous:

MPI_BUFFER t, tt, fb;

mpi_append_contiguous(t, &foo[0].d, 5, MPI_DOUBLE);
mpi_append_contiguous(t, &foo[0].b, 1, MPI_BYTE);

/* don't we need to mpi_create first the tt buffer ? */
/* the example 3 of the draft doesn't create it ...  */
mpi_unbind(t, tt);

mpi_append_hvec(fb, &foo[0].d[0], 100, sizeof(struct foostruct), 1, tt);

mpi_commit(fb);

Therefore it is not necesary to include always the first element of
the structure as I thought...  Sorry for the slip...

Ricardo.
-- 
To err is human, to really fool things around requires a computer !
+----------------------+---------------------------------+--------------+
| Ricardo A. Schmutzer | Internet: [email-masked]    | Conectividad |
| PUC, Santiago, Chile |                                 | Distr. Comp. |
+----------------------+---------------------------------+--------------+