Hello all,
First off, please excuse the attached code as I may be naïve in my
attempts to implement my own MPI_OP.
I am attempting to create my own MPI_OP to use with MPI_Allreduce. I
have been able to find very little examples off the net of creating MPI_OPs. My
present references are "MPI The complete reference Volume 1 2nd edition" and
some rather good slides I found at
http://www.mpi-hd.mpg.de/personalhomes/stiff/MPI/ . I am attaching my "proof of
concept" code which fails with:
[kyron:14074] *** Process received signal ***
[kyron:14074] Signal: Segmentation fault (11)
[kyron:14074] Signal code: Address not mapped (1)
[kyron:14074] Failing at address: 0x801da600
[kyron:14074] [ 0] [0x6ffa6440]
[kyron:14074] [ 1]
/home/kyron/openmpi_i686/lib/openmpi/mca_coll_tuned.so(ompi_coll_tuned_allreduce_intra_recursivedoubling+0x700)
[0x6fbb0dd0]
[kyron:14074] [ 2]
/home/kyron/openmpi_i686/lib/openmpi/mca_coll_tuned.so(ompi_coll_tuned_allreduce_intra_dec_fixed+0xb2)
[0x6fbae9a2]
[kyron:14074] [ 3]
/home/kyron/openmpi_i686/lib/libmpi.so.0(PMPI_Allreduce+0x1a6) [0x6ff61e86]
[kyron:14074] [ 4] AllReduceTest(main+0x180) [0x8048ee8]
[kyron:14074] [ 5] /lib/libc.so.6(__libc_start_main+0xe3) [0x6fcbd823]
[kyron:14074] *** End of error message ***
Eric Thibodeau
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>
#define V_LEN 10 //Vector Length
#define E_CNT 10 //Element count
MPI_Op MPI_MySum; //Custom Sum function
MPI_Datatype MPI_MyType;//We need this MPI Datatype to make MPI aware of our custom structure
int i,j,true=1;
int totalnodes,mynode;
typedef struct CustomType_t {
float feat[V_LEN]; //Some vector of float
float distc; //An independant float value
int number; //A counter of a different type
} CustomType;
CustomType *SharedStruct;
void construct_MyType(void){
CustomType p;
int BlockLengths[3] = {V_LEN,1,1};
MPI_Aint Displacement[3];
MPI_Datatype types[3] = {MPI_FLOAT, MPI_FLOAT, MPI_INT};
/* Compute relative displacements w/r to the Type's begining address
* using portable technique
* */
MPI_Get_address(&p.feat[0],&Displacement[0]);
MPI_Get_address(&p.distc ,&Displacement[1]);
MPI_Get_address(&p.number ,&Displacement[2]);
// It is good practice to include this in case
// the compiler pads your data structure
/* BlockLengths[3] = 1; types[3] = MPI_UB;
Displacement[3] = sizeof(CustomType); */
MPI_Type_create_struct(3, BlockLengths, Displacement, types, &MPI_MyType);
MPI_Type_commit(&MPI_MyType); // important!!
return;
}
void MySum(CustomType *cin, CustomType *cinout, int *len, MPI_Datatype *dptr)
{
int i,j;
// Some sanity check
printf("\nIn MySum, Node %d with len=\n",mynode,*len);
if(*dptr != MPI_MyType)
{
printf("Invalid datatype\n");
MPI_Abort(MPI_COMM_WORLD, 3);
}
for(i=0; i < *len; i++)
{
cinout[i].distc +=cin[i].distc;
cinout[i].number+=cin[i].number;
for(j=0; j<V_LEN; j++)
cinout[i].feat[j]+=cin[i].feat[j];
}
}
void PrintStruct(void)
{
//We print the result from all nodes:
printf("Node %d has the following in SharedStruct:\n",mynode);
for(i=0; i<E_CNT; i++)
{
printf("D:%2.1f #:%d Vect:",SharedStruct[i].distc,SharedStruct[i].number);
for(j=0; j<V_LEN; j++)
printf("%f,",SharedStruct[i].feat[j]);
printf("\n");
}
printf("========= Node %d =========\n",mynode);
}
main(int argc, char *argv[])
{
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &totalnodes);
MPI_Comm_rank(MPI_COMM_WORLD, &mynode);
// Create the MPI_MyType Type
construct_MyType();
// Create the MPI_MySum Operator
MPI_Op_create((MPI_User_function*)MySum, true, &MPI_MySum);
SharedStruct= (CustomType *)malloc(E_CNT * sizeof(CustomType)); //The dist and number part of the structure never get used at the moment...
SharedStruct[0].distc=mynode+1.0;
SharedStruct[0].number=mynode;
for(i=0; i<V_LEN; i++) SharedStruct[0].feat[i]=mynode+i;
// To speed up the process we replicate the process using memcpy:
for(i=1; i<E_CNT; i++)
memcpy((void*)&SharedStruct[i],(void*)SharedStruct,sizeof(CustomType));
//Print Before:
PrintStruct();
// We add the content of all nodes _on_ all nodes:
MPI_Allreduce(MPI_IN_PLACE, SharedStruct, E_CNT, MPI_MyType, MPI_MySum, MPI_COMM_WORLD);
//Print After:
PrintStruct();
}