MPI_Aint_diff is undefined

I'm trying to run the following code in my PC but I get MPI_Aint_diff undefined. I included the correct platform of mpi library but still I'm getting this error. Amy help is appreciated.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>
 
struct person_t
{
    int age;
    double height;
    char name[10];
};
 
int main(int argc, char* argv[])
{
    MPI_Init(&argc, &argv);
 
    // Get the number of processes and check only 2 processes are used
    int size;
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    if(size != 2)
    {
        printf("This application is meant to be run with 2 processes.\n");
        MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
    }
 
    // Create the datatype
    MPI_Datatype person_type;
    int lengths[3] = { 1, 1, 10 };
 
    MPI_Aint displacements[3];
    struct person_t dummy_person;
    MPI_Aint base_address;
    MPI_Get_address(&dummy_person, &base_address);
    MPI_Get_address(&dummy_person.age, &displacements[0]);
    MPI_Get_address(&dummy_person.height, &displacements[1]);
    MPI_Get_address(&dummy_person.name[0], &displacements[2]);
    displacements[0] = MPI_Aint_diff(displacements[0], base_address);
    displacements[1] = MPI_Aint_diff(displacements[1], base_address);
    displacements[2] = MPI_Aint_diff(displacements[2], base_address);
 
    MPI_Datatype types[3] = { MPI_INT, MPI_DOUBLE, MPI_CHAR };
    MPI_Type_create_struct(3, lengths, displacements, types, &person_type);
    MPI_Type_commit(&person_type);
 
    // Get my rank and do the corresponding job
    enum rank_roles { SENDER, RECEIVER };
    int my_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
    switch(my_rank)
    {
        case SENDER:
        {
            // Send the message
            struct person_t buffer;
            buffer.age = 20;
            buffer.height = 1.83;
            strncpy(buffer.name, "Tom", 9);
            buffer.name[9] = '\0';
            printf("MPI process %d sends person:\n\t- age = %d\n\t- height = %f\n\t- name = %s\n", my_rank, buffer.age, buffer.height, buffer.name);
            MPI_Send(&buffer, 1, person_type, RECEIVER, 0, MPI_COMM_WORLD);
            break;
        }
        case RECEIVER:
        {
            // Receive the message
            struct person_t received;
            MPI_Recv(&received, 1, person_type, SENDER, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
            printf("MPI process %d received person:\n\t- age = %d\n\t- height = %f\n\t- name = %s\n", my_rank, received.age, received.height, received.name);
            break;
        }
    }
 
    MPI_Finalize();
 
    return EXIT_SUCCESS;
}
Last edited on
I believe that MPI_Aint_diff arrived with MPI 3.0 (maybe 3.1). Anyway, if running with Microsoft MPI then you are probably using MPI 2

To define your own MPI datatypes for structs you can try this instead.
Please try to keep your examples simple, without unnecessary extra fluff.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include <cstring>
#include "mpi.h"
using namespace std;

struct person_t
{
   int age;
   double height;
   char name[10]{};

   friend ostream & operator <<( ostream &out, const person_t &p )
   {
      out << "\n\tage    = " << p.age
          << "\n\theight = " << p.height
          << "\n\tname   = " << p.name << '\n';
      return out;
   }
};
 
int main(int argc, char* argv[])
{
   MPI_Init( &argc, &argv );
   int size, rank;
   MPI_Comm_size( MPI_COMM_WORLD, &size );
   MPI_Comm_rank( MPI_COMM_WORLD, &rank );
 
   // Create the datatype
   MPI_Datatype person_type;
   person_t p;
   MPI_Datatype types        [3] = {          MPI_INT,          MPI_DOUBLE,          MPI_CHAR };
   int          lengths      [3] = {                1,                   1,                10 };
   MPI_Aint     displacements[3] = { (MPI_Aint)&p.age, (MPI_Aint)&p.height, (MPI_Aint)&p.name };
   for ( int i = 1; i < 3; i++ ) displacements[i] -= displacements[0];
   displacements[0] = 0;
   
   MPI_Type_create_struct( 3, lengths, displacements, types, &person_type );
   MPI_Type_commit( &person_type );
 
   // Get my rank and do the corresponding job
   if ( rank == 0 )
   {
      struct person_t buffer;
      buffer.age = 20;
      buffer.height = 1.83;
      strcpy( buffer.name, "Tom" );
      cout << rank << " sends person:" << buffer;
      MPI_Send( &buffer, 1, person_type, 1, 0, MPI_COMM_WORLD );
   }
   else
   {
      struct person_t received;
      MPI_Recv( &received, 1, person_type, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE );
      cout << rank << " receives person:" << received;
    }

   MPI_Type_free( &person_type );
   MPI_Finalize();
}



"C:\Program Files\Microsoft MPI\bin"\mpiexec -n 2 test.exe
0 sends person:
	age    = 20
	height = 1.83
	name   = Tom
1 receives person:
	age    = 20
	height = 1.83
	name   = Tom

Last edited on
@lastchance Thanks for your answer
You might want to tidy up your creation of a new MPI datatype (by putting it in a separate function, near to the definition of your struct).

Tidier version below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include "mpi.h"
using namespace std;


struct person_t
{
   int age;
   double height;
   char name[10]{};

   friend ostream & operator <<( ostream &out, const person_t &p )
   {
      out << "\n\tage    = " << p.age
          << "\n\theight = " << p.height
          << "\n\tname   = " << p.name << '\n';
      return out;
   }
};
 

void make_person_datatype( MPI_Datatype &newtype )
{
   person_t p;
   MPI_Datatype types        [3] = {          MPI_INT,          MPI_DOUBLE,          MPI_CHAR };
   int          lengths      [3] = {                1,                   1,                10 };
   MPI_Aint     displacements[3] = { (MPI_Aint)&p.age, (MPI_Aint)&p.height, (MPI_Aint)&p.name };
   for ( int i = 2; i >= 0; i-- ) displacements[i] -= displacements[0];
   MPI_Type_create_struct( 3, lengths, displacements, types, &newtype );
}


int main(int argc, char* argv[])
{
   int size, rank;
   MPI_Init( &argc, &argv );
   MPI_Comm_size( MPI_COMM_WORLD, &size );
   MPI_Comm_rank( MPI_COMM_WORLD, &rank );
 
   // Create the datatype
   MPI_Datatype person_type;
   make_person_datatype( person_type );
   MPI_Type_commit( &person_type );
 
   // Send / receive
   int tag = 0, sender = 0, receiver = 1;
   if ( rank == sender )
   {
      person_t buffer{ 20, 1.83, "Tom" };
      cout << rank << " sends person:" << buffer;
      MPI_Send( &buffer, 1, person_type, receiver, tag, MPI_COMM_WORLD );
   }
   else if ( rank == receiver )
   {
      person_t received;
      MPI_Recv( &received, 1, person_type, sender, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE );
      cout << rank << " receives person:" << received;
    }

   MPI_Type_free( &person_type );
   MPI_Finalize();
}



C:\c++>"C:\Program Files\Microsoft MPI\bin"\mpiexec -n 2 test

0 sends person:
	age    = 20
	height = 1.83
	name   = Tom
1 receives person:
	age    = 20
	height = 1.83
	name   = Tom


@lastchance, I am looking for a way to look at different processors and does a userdefined reduction. I have three vectors in each processors. one of them is of double type and the other two are integer. I could simply flatten them into 1d vector if they were of same type and send a pointer buffer into the user defined reduction function but they are not. I thought about something like defining union or variant but in this case MPI won't understand the data type. I tried to define my mpi datatype but the problem is the size of these three vectors are different in different processors, So I will end up with different data types in different processors. I wonder how one can define a user defined operation in mpi when the input data is not row data and also it's not possible to be flattened into 1d data.
Last edited on
Your data can always be flattened into 1d arrays - you can send ints and doubles separately.

You will probably have to send (separately):
- the array size information (if different on each processor)
- the int arrays
- the double arrays

With sensible housekeeping you will probably only have to send the first two once, and store connectivity information. Only your doubles are likely to change from iteration to iteration.
@lastchance Thanks for the answer.
Your data can always be flattened into 1d arrays - you can send ints and doubles separately.


you mean something like this,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void my_sum_function(void* inputBuffer1,void * inputBuffer2,
void *inputBuffer3, void* outputBuffer, int* len, MPI_Datatype* datatype)
{
    VecDbl_t* input1 = (VecDbl_t*)inputBuffer1;
    VecInt_t* input2 = (VecInt_t*)inputBuffer2;
    VecInt_t* input3 = (VecInt_t*)inputBuffer3;
    double* output = (double*)outputBuffer;

 
    for (int i = 0; i < (*input2).size(); i++) {

        output[(*input2)[i]] += (*input1)[i];
    }
}
Last edited on
@lastchance I didn't get how how can I send ints and doubles separately to the mpi user defined reduction function. Could you please help me with this.
Topic archived. No new replies allowed.