-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathgather2d.cpp
135 lines (125 loc) · 3.5 KB
/
gather2d.cpp
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <cstdio>
#include <mpi.h>
#include <cassert>
#include <vector>
const int L = 8;
struct MPIinfo {
int rank;
int procs;
int GX, GY;
int local_grid_x, local_grid_y;
int local_size_x, local_size_y;
};
void init(std::vector<int> &local_data, MPIinfo &mi) {
const int offset = mi.local_size_x * mi.local_size_y * mi.rank;
for (int iy = 0; iy < mi.local_size_y; iy++) {
for (int ix = 0; ix < mi.local_size_x; ix++) {
int index = (ix + 1) + (iy + 1) * (mi.local_size_x + 2);
int value = ix + iy * mi.local_size_x + offset;
local_data[index] = value;
}
}
}
void dump_local_sub(std::vector<int> &local_data, MPIinfo &mi) {
printf("rank = %d\n", mi.rank);
for (int iy = 0; iy < mi.local_size_y + 2; iy++) {
for (int ix = 0; ix < mi.local_size_x + 2; ix++) {
unsigned int index = ix + iy * (mi.local_size_x + 2);
printf(" %03d", local_data[index]);
}
printf("\n");
}
printf("\n");
}
void dump_local(std::vector<int> &local_data, MPIinfo &mi) {
for (int i = 0; i < mi.procs; i++) {
MPI_Barrier(MPI_COMM_WORLD);
if (i == mi.rank) {
dump_local_sub(local_data, mi);
}
}
}
void dump_global(std::vector<int> &global_data) {
for (int iy = 0; iy < L; iy++) {
for (int ix = 0; ix < L; ix++) {
printf(" %03d", global_data[ix + iy * L]);
}
printf("\n");
}
printf("\n");
}
void reordering(std::vector<int> &v, MPIinfo &mi) {
std::vector<int> v2(v.size());
std::copy(v.begin(), v.end(), v2.begin());
const int lx = mi.local_size_x;
const int ly = mi.local_size_y;
int i = 0;
for (int r = 0; r < mi.procs; r++) {
int rx = r % mi.GX;
int ry = r / mi.GX;
int sx = rx * lx;
int sy = ry * ly;
for (int iy = 0; iy < ly; iy++) {
for (int ix = 0; ix < lx; ix++) {
int index = (sx + ix) + (sy + iy) * L;
v[index] = v2[i];
i++;
}
}
}
}
void gather(std::vector<int> &local_data, MPIinfo &mi) {
const int lx = mi.local_size_x;
const int ly = mi.local_size_y;
std::vector<int> sendbuf(lx * ly);
// 「のりしろ」を除いたデータのコピー
for (int iy = 0; iy < ly; iy++) {
for (int ix = 0; ix < lx; ix++) {
int index_from = (ix + 1) + (iy + 1) * (lx + 2);
int index_to = ix + iy * lx;
sendbuf[index_to] = local_data[index_from];
}
}
std::vector<int> recvbuf;
if (mi.rank == 0) {
recvbuf.resize(lx * ly * mi.procs);
}
MPI_Gather(sendbuf.data(), lx * ly, MPI_INT, recvbuf.data(), lx * ly, MPI_INT, 0, MPI_COMM_WORLD);
if (mi.rank == 0) {
printf("Before reordering\n");
dump_global(recvbuf);
reordering(recvbuf, mi);
printf("After reordering\n");
dump_global(recvbuf);
}
}
void setup_info(MPIinfo &mi) {
int rank = 0;
int procs = 0;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &procs);
int d2[2] = {};
MPI_Dims_create(procs, 2, d2);
mi.rank = rank;
mi.procs = procs;
mi.GX = d2[0];
mi.GY = d2[1];
mi.local_grid_x = rank % mi.GX;
mi.local_grid_y = rank / mi.GX;
mi.local_size_x = L / mi.GX;
mi.local_size_y = L / mi.GY;
}
int main(int argc, char **argv) {
MPI_Init(&argc, &argv);
MPIinfo mi;
setup_info(mi);
// ローカルデータの確保
std::vector<int> local_data((mi.local_size_x + 2) * (mi.local_size_y + 2), 0);
// ローカルデータの初期化
init(local_data, mi);
// ローカルデータの表示
dump_local(local_data, mi);
// ローカルデータを集約してグローバルデータに
gather(local_data, mi);
MPI_Finalize();
}