YAC 3.21.0
Yet Another Coupler
Loading...
Searching...
No Matches
mpi_handshake.c
Go to the documentation of this file.
1// Copyright (c) 2024 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#ifdef HAVE_CONFIG_H
6#include "config.h"
7#endif
8
9#include <mpi.h>
10#include <string.h>
11#include <limits.h>
12#include <stdint.h>
13
14#include "yac_mpi_common.h"
15#include "utils_common.h"
16
17void yac_mpi_handshake(MPI_Comm comm, size_t n, char const** group_names,
18 MPI_Comm * group_comms) {
19 int is_intercomm;
20 yac_mpi_call(MPI_Comm_test_inter(comm, &is_intercomm), comm);
21 YAC_ASSERT(!is_intercomm, "inter-communicators are not supported");
22
23 // STEP 1: Version exchange
24 enum {MPI_HANDSHAKE_VERSION = 1};
25 int version = MPI_HANDSHAKE_VERSION;
27 MPI_Allreduce(MPI_IN_PLACE, &version, 1, MPI_INT, MPI_MIN, comm),
28 comm);
30 version == MPI_HANDSHAKE_VERSION,
31 "Version check failed. YAC only supports MPI handshake version %d",
32 MPI_HANDSHAKE_VERSION);
33
34 int rank, size;
35 MPI_Comm_rank(comm, &rank);
36 MPI_Comm_size(comm, &size);
37 for (size_t i = 0; i < n; ++i) group_comms[i] = MPI_COMM_NULL;
38
39 while(1){
40 // STEP 2: determine broadcasting rank
41 size_t group_idx = SIZE_MAX;
42 for (size_t i = 0; (i < n) && (group_idx == SIZE_MAX); ++i)
43 if (group_comms[i] == MPI_COMM_NULL) group_idx = i;
44 int broadcasting_rank = group_idx != SIZE_MAX ? rank : size;
46 MPI_Allreduce(MPI_IN_PLACE, &broadcasting_rank, 1, MPI_INT, MPI_MIN, comm),
47 comm);
48 YAC_ASSERT(broadcasting_rank >= 0 && broadcasting_rank <= size,
49 "broadcasting rank cannot be negativ or greater than communicator size.");
50 if(broadcasting_rank == size) break;
51
52 // STEP 3: broadcast group name
53 int groupnamelen = 0;
54 if(broadcasting_rank == rank){
55 size_t len = strlen(group_names[group_idx]);
56 YAC_ASSERT(len <= INT_MAX, "group name is too long");
57 groupnamelen = (int)len;
58 }
60 MPI_Bcast(&groupnamelen, 1, MPI_INT, broadcasting_rank, comm),
61 comm);
62 char * groupname = xmalloc((size_t)(groupnamelen + 1) * sizeof(*groupname));
63 if(broadcasting_rank == rank){
64 strcpy(groupname, group_names[group_idx]);
65 }
67 MPI_Bcast(groupname, groupnamelen, MPI_CHAR, broadcasting_rank, comm),
68 comm);
69 groupname[groupnamelen] = '\0';
70
71 // STEP 4: split communicator
72 group_idx = SIZE_MAX;
73 for (size_t i = 0; (i < n) && (group_idx == SIZE_MAX); ++i)
74 if (!strcmp(groupname, group_names[i])){
75 YAC_ASSERT_F(group_comms[i] == MPI_COMM_NULL,
76 "Group communicator for group '%s' was already created, "
77 "but was broadcasted again.", groupname);
78 group_idx = i;
79 }
80 free(groupname);
81 MPI_Comm new_comm;
83 MPI_Comm_split(comm, (group_idx != SIZE_MAX)?0:MPI_UNDEFINED, rank, &new_comm),
84 comm);
85 if(group_idx != SIZE_MAX)
86 group_comms[group_idx] = new_comm;
87 }
88}
89
90/*
91 * Local Variables:
92 * c-basic-offset: 2
93 * coding: utf-8
94 * indent-tabs-mode: nil
95 * show-trailing-whitespace: t
96 * require-trailing-newline: t
97 * End:
98 */
#define YAC_ASSERT(exp, msg)
void yac_mpi_handshake(MPI_Comm comm, size_t n, char const **group_names, MPI_Comm *group_comms)
#define xmalloc(size)
Definition ppm_xfuncs.h:66
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:39
#define yac_mpi_call(call, comm)