https://enccs.github.io/intermediate-mpi/derived-datatypes-pt2/#
MPI已经定义的类型
https://rookiehpc.org/mpi/docs/mpi_datatype/index.html
List of named predefined dataypes:
MPI_SIGNED_CHAR / MPI_UNSIGNED_CHAR
MPI_SHORT / MPI_UNSIGNED_SHORT
MPI_INT / MPI_UNSIGNED
MPI_LONG / MPI_UNSIGNED_LONG
MPI_LONG_LONG_INT (a.k.a MPI_LONG_LONG) / MPI_UNSIGNED_LONG_LONG
MPI_CHAR
MPI_WCHAR
MPI_FLOAT
MPI_DOUBLE
MPI_LONG_DOUBLE
MPI_INT8_T / MPI_UINT8_T
MPI_INT16_T / MPI_UINT16_T
MPI_INT32_T / MPI_UINT32_T
MPI_INT64_T / MPI_UINT64_T
MPI_C_BOOL
MPI_C_COMPLEX
MPI_C_FLOAT_COMPLEX
MPI_C_DOUBLE_COMPLEX
MPI_C_LONG_DOUBLE_COMPLEX
MPI_AINT
MPI_COUNT
MPI_OFFSET
MPI_BYTE
MPI_PACKED
List of datatypes for reduction functions MPI_MINLOC and MPI_MAXLOC:
MPI_SHORT_INT
MPI_LONG_INT
MPI_FLOAT_INT
MPI_DOUBLE_INT
MPI_LONG_DOUBLE_INT
MPI_2INT
自定义结构体类型举例
struct Pair {
int first;
char second;
};
// build up the typemap for Pair
// the type signature for Pair
MPI_Datatype typesig[2] = {MPI_INT, MPI_CHAR};
// how many of each type in a "block" of Pair
int block_lengths[2] = {1, 1};
// displacements of data members in Pair
MPI_Aint displacements[2],base_address;
// why not use pointer arithmetic directly? We cannot use pointer arithmetic to compute displacements. Always keep in mind that your program might be deployed on heterogeneous architectures: you have to program for correctness and portability.
MPI_Get_address(&my_pair.first, base_address);
displacements[0] = 0;
MPI_Get_address(&my_pair.second, &displacements[1]);
// ! note, can NOT use -
displacements[1] = MPI_Aint_diff(displacements[1], base_address);
// create and commit the new type
MPI_Datatype mpi_pair;
MPI_Type_create_struct(2, block_lengths, displacements, typesig, &mpi_pair);
MPI_Type_commit(&mpi_pair);
// clean up after use
MPI_Type_free(&mpi_pair);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>
#define STRLEN 25
struct Pokemon {
// name of pokemon attacking
char name[STRLEN];
// life points
double life_points;
// damage done by the attack
int damage;
// strength multiplier
double multiplier;
};
int main(int argc, char *argv[]) {
int rank;
int size;
struct Pokemon charizard;
MPI_Init(&argc, &argv);
MPI_Comm comm = MPI_COMM_WORLD;
MPI_Comm_size(comm, &size);
MPI_Comm_rank(comm, &rank);
MPI_Datatype typesig[4] = {MPI_CHAR, MPI_DOUBLE, MPI_INT, MPI_DOUBLE};
int block_lengths[4] = {STRLEN, 1, 1, 1};
MPI_Aint base_address, displacements[4];
MPI_Get_address(&charizard.name, &displacements[0]);
base_address = displacements[0];
displacements[0] = displacements[0] - base_address;
MPI_Get_address(&charizard.life_points, &displacements[1]);
displacements[1] = displacements[1] - base_address;
MPI_Get_address(&charizard.damage, &displacements[2]);
displacements[2] = displacements[2] - base_address;
MPI_Get_address(&charizard.multiplier, &displacements[3]);
displacements[3] = displacements[3] - base_address;
MPI_Datatype mpi_pokemon;
MPI_Type_create_struct(4, block_lengths, displacements, typesig,
&mpi_pokemon);
MPI_Type_commit(&mpi_pokemon);
if (rank == 0) {
sprintf(charizard.name, "Charizard");
charizard.life_points = 180.0;
charizard.damage = 60;
charizard.multiplier = 0.89;
MPI_Bcast(&charizard, 1, mpi_pokemon, 0, comm);
} else {
// matching broadcast on all other processes.
MPI_Bcast(&charizard, 1, mpi_pokemon, 0, comm);
// did we get it right?
printf("rank %d:\n", rank);
printf(" pokemon = %s\n", charizard.name);
printf(" life_points = %2.2f\n", charizard.life_points);
printf(" damage = %d\n", charizard.damage);
printf(" multiplier = %2.2f\n", charizard.multiplier);
}
MPI_Type_free(&mpi_pokemon);
MPI_Finalize();
return EXIT_SUCCESS;
}