Creating a reduce operation for AutoMap data-types
Quick Links :
Main Page |
AutoMap |
AutoLink |
Mailing List |
License |
Award |
Papers |
Acknowledgments
1) General presentation of reduce operations
Reduce operations are useful to perform a global operation on all the processors of a group. The MPI documentation defines 2 functions that implement the reduce operations :
MPI_Reduce (void * sendbuf, void * recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm COMM)
performs the operation on each process of the group and sends the final result to root
in recvbuf
MPI_Reduce_scatter (void * sendbuf, void * recvbuf, int *revcounts, MPI_Datatype datatype, MPI_Op op, MPI_Comm COMM)
performs the operation on each process of the group and sends the final result to all process
2) Creating a reduce operation
There are some built-in operations that are available in MPI (like MPI_MAX
and MPI_MIN to compute the maximum and the minimum of some values of basic type, MPI_INT
, MPI_LONG
, MPI_SHORT
, MPI_UNSIGNED_SHORT
, MPI_UNSIGNED
, MPI_UNSIGNED_LONG
, MPI_FLOAT
,
MPI_DOUBLE
, MPI_REAL
, MPI_DOUBLE_PRECISION
, MPI_LONG_DOUBLE
, MPI_SUM
and MPI_PROD
, to make the sum and the product of precedent datatypes, and for MPI_COMPLEX
, as well as other logical operations MPI_AND
, MPI_BAND
, MPI_LOR
, MPI_BOR
, MPI_LXOR
).
But there is also the possibility to create one's own operations on one's own MPI_Datatype
. This last feature can be useful when using AutoMap created data-types.
To create a reduce operations use the MPI function, MPI_Op_create(MPI_User_function *function, int commute, MPI_Op *op)
, where :
MPI_User_function *function
is a pointer on a function having for prototype : typedef void MPI_User_function( void * invec, void * inoutvec, int * len, MPI_Datatype *datatype)
int commute
is a boolean indicating whether the operation is commutative or not
MPI_Op *op
is the MPI reduce operation created
To delete a created reduction operation, one just have to use the MPI_op_free( MPI_Op *op)
function, this can be useful to change a reduce function's functionality, but keep the same name for the function.
3) Example of use
Here is an example showing how to proceed to create such a reduce operation. Suppose one wants to create an operation to compare two complex numbers, as such an operations doesn't exist in the MPI basic functions.
The file "struct.h" contains this simple structure (formatted for use with AutoMap) :
/*~ AM_Begin */
struct{
double real, imag;
}_Complex;
typedef struct _Complex Complex/*~AM*/;
/*~ AM_End */
Once the "mpitypes.inc" file has been generated using AutoMap, you can create a reduce operation in your source code. Here is an example showing how to compute the complex with the biggest module for each index of an array.
#include <mpi.h>
#include "struct.h" /* Data-types file */
#include "mpitypes.inc" /* AutoMap generated output from data-types file */
#define true (1==1)
#define false (0==0)
void complexcompare(Complex * in, Complex * inout, int * len, MPI_Datatype * dptr)
{
int i;
Complex c;
for (i = 0; i < *len; i++) {
if (((in->real*in->real) + (in->imag*in->imag)) >
((inout->real*inout->real)+(inout->imag*inout->imag))){
/* compares the module of the complex in *in and the complex in *inout */
*inout = *in;
}
in++;
inout++;
}
}
main(int argc, char* argv[])
{
MPI_Op myOp;
Complex a[3], answer[3];
MPI_Init(&argc, &argv);
/* Initialzes MPI */
Build_MPI_Types();
/* build the Data-types created by AutoMap */
MPI_Op_create((MPI_User_function *) complexcompare, true, &myOp);
/* creates the commutative MPI reduce operation associated
with the function complexcompare under the name myOp */
[...]
MPI_Reduce (a, answer, 100, AutoMap_complex , myOp, 0, MPI_COMM_WORLD);
/* performs the reduce operation over the a array of all the procesors
in the answer array in the processor of rank 0 */
MPI_Finalize();
/* Finalizes MPI */
}
If we consider a run of this program on a 3 nodes architecture, with the following arrays [4.5+0i, -5+0.1*i, 6-5.1i]
on node 0, [2.1+9i, -3.84+3*i, 0.2+0.8i]
on node 1, and [-1.5+0.4i, 7.3+8.1*i, 2.4-1i]
on node 2, the array answer finally obtained in node 0, will be [2.1+9i, 7.3+8.1*i, 6-5.1i]
.
Page created : 1997
Last update : 26 Oct 2001
By> : SAVG