YetAnotherCoupler 3.5.2
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
12#include "yac_mpi_common.h"
13#include "utils_common.h"
14
15void yac_mpi_handshake(MPI_Comm comm, size_t n, char const** group_names,
16 MPI_Comm * group_comms) {
17 int is_intercomm;
18 yac_mpi_call(MPI_Comm_test_inter(comm, &is_intercomm), comm);
19 YAC_ASSERT(!is_intercomm,
20 "ERROR(yac_mpi_handshake): inter-communicators are not supported");
21
22 // STEP 1: Version exchange
23 enum {MPI_HANDSHAKE_VERSION = 1};
24 int version = MPI_HANDSHAKE_VERSION;
26 MPI_Allreduce(MPI_IN_PLACE, &version, 1, MPI_INT, MPI_MIN, comm),
27 comm);
29 version == MPI_HANDSHAKE_VERSION,
30 "ERROR(yac_mpi_handshake): "
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 "ERROR(yac_mpi_handshake): "
50 "broadcasting rank cannot be negativ or greater than communicator size.");
51 if(broadcasting_rank == size) break;
52
53 // STEP 3: broadcast group name
54 int groupnamelen = 0;
55 if(broadcasting_rank == rank){
56 size_t len = strlen(group_names[group_idx]);
57 YAC_ASSERT(len <= INT_MAX,
58 "ERROR(yac_mpi_handshake): group name is too long");
59 groupnamelen = (int)len;
60 }
62 MPI_Bcast(&groupnamelen, 1, MPI_INT, broadcasting_rank, comm),
63 comm);
64 char * groupname = xmalloc((size_t)(groupnamelen + 1) * sizeof(*groupname));
65 if(broadcasting_rank == rank){
66 strcpy(groupname, group_names[group_idx]);
67 }
69 MPI_Bcast(groupname, groupnamelen, MPI_CHAR, broadcasting_rank, comm),
70 comm);
71 groupname[groupnamelen] = '\0';
72
73 // STEP 4: split communicator
74 group_idx = SIZE_MAX;
75 for (size_t i = 0; (i < n) && (group_idx == SIZE_MAX); ++i)
76 if (!strcmp(groupname, group_names[i])){
77 YAC_ASSERT_F(group_comms[i] == MPI_COMM_NULL,
78 "ERROR(yac_mpi_handshake): "
79 "Group communicator for group '%s' was already created, "
80 "but was broadcasted again.",
81 groupname);
82 group_idx = i;
83 }
84 free(groupname);
85 MPI_Comm new_comm;
87 MPI_Comm_split(comm, (group_idx != SIZE_MAX)?0:MPI_UNDEFINED, rank, &new_comm),
88 comm);
89 if(group_idx != SIZE_MAX)
90 group_comms[group_idx] = new_comm;
91 }
92}
93
94/*
95 * Local Variables:
96 * c-basic-offset: 2
97 * coding: utf-8
98 * indent-tabs-mode: nil
99 * show-trailing-whitespace: t
100 * require-trailing-newline: t
101 * End:
102 */
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:19
#define YAC_ASSERT(exp, msg)
Definition yac_assert.h:16
#define yac_mpi_call(call, comm)