HILA
Loading...
Searching...
No Matches
map_node_layout.cpp
1/// This routine uses internal MPI (or other) commands to remap the
2/// node numbers so that the communications should be optimised.
3///
4/// Implements two calls,
5/// int remap(int i) : given "computed" node index i, returns true mpi rank
6/// the input i is the logical node index, runs fastest to directions x,y,z,(t)
7/// must be compatible with node_rank layout!
8///
9/// int inverse_remap(int i) : inverse of above
10///
11/// Used especially in transformation coordinate -> node_rank, in
12/// lattice_struct::node_rank in
13
14
15#include "plumbing/defs.h"
16#include "plumbing/lattice.h"
17
18#if defined(NODE_LAYOUT_TRIVIAL)
19
20////////////////////////////////////////////////////////////////////
21// This is the trivial version, so that the order is unmodified
22////////////////////////////////////////////////////////////////////
23
25 hila::out0 << "Node remapping: NODE_LAYOUT_TRIVIAL (no reordering)\n";
26 lattice.nodes.map_array = nullptr;
27 lattice.nodes.map_inverse = nullptr;
28}
29
30unsigned lattice_struct::allnodes::remap(unsigned i) const {
31 return i;
32}
33
34unsigned lattice_struct::allnodes::inverse_remap(unsigned i) const {
35 return i;
36}
37
38
39#elif defined(NODE_LAYOUT_BLOCK)
40
41////////////////////////////////////////////////////////////////////
42// Arrange nodes so that NODE_LAYOUT_BLOCK nodes are "close"
43//
44// For example, in 2d and NODE_LAYOUT_BLOCK = 4 the MPI indices run as
45//
46// 1 2 | 5 6 | 9 10
47// 3 4 | 7 8 | 11 12
48// -----+-------+------
49// 13 14 | 17 18 | 21 22
50// 15 16 | 19 20 | 23 24
51//
52////////////////////////////////////////////////////////////////////
53
55
56 hila::out0 << "Node remapping: NODE_LAYOUT_BLOCK with blocksize " << NODE_LAYOUT_BLOCK
57 << '\n';
58
59 // let us allow only factors of 5,3 and 2 in NODE_LAYOUT_BLOCK
60 CoordinateVector blocksize;
61 CoordinateVector blockdivs = lattice.nodes.n_divisions;
62 int nblocks = NODE_LAYOUT_BLOCK;
63 blocksize.fill(1);
64
65 bool found = true;
66 while (found && nblocks > 1) {
67
68 found = false; // if not divisible stop trying
69 foralldir (d) {
70 // divide directions one by one
71 int div;
72 for (div = 2; div <= 5; div++)
73 if (nblocks % div == 0 && blockdivs[d] % div == 0)
74 break;
75 if (div <= 5) {
76 blocksize[d] *= div;
77 blockdivs[d] /= div;
78 nblocks /= div;
79 found = true;
80 }
81 }
82 }
83
84 hila::out0 << "Node block size " << blocksize << " block division " << blockdivs << '\n';
85
86 // now blocksize tells us how many nodes to each direction in block
87 // these are taken in order
88
89 lattice.nodes.map_array =
90 (unsigned *)memalloc(lattice.nodes.number * sizeof(unsigned));
91 // we don't need the inverse at the moment?
92 // lattice.nodes.map_inverse = (unsigned *)memalloc(lattice.nodes.number *
93 // sizeof(unsigned));
94 lattice.nodes.map_inverse = nullptr;
95
96 nblocks = 1;
97 foralldir (d)
98 nblocks *= blocksize[d];
99
100 // Loop over the "logical" node indices (i.e.)
101
102 for (int i = 0; i < lattice.nodes.number; i++) {
103 // lcoord is the coordinate of the logical node,
104 // bcoord the block coord and icoord coord inside block
105 CoordinateVector lcoord, bcoord, icoord;
106 int idiv = i;
107 foralldir (d) {
108 lcoord[d] = idiv % lattice.nodes.n_divisions[d];
109 idiv /= lattice.nodes.n_divisions[d];
110
111 bcoord[d] = lcoord[d] / blocksize[d];
112 icoord[d] = lcoord[d] % blocksize[d];
113 }
114
115 // ii - index within a block
116 // bi - index of a block
117 int ii, bi, im, bm;
118 ii = bi = 0;
119 im = bm = 1;
120 foralldir(d) {
121 ii += icoord[d] * im;
122 im *= blocksize[d];
123
124 bi += bcoord[d] * bm;
125 bm *= blockdivs[d];
126 }
127
128 // hila::out0 << lcoord << bcoord << icoord << '\n';
129 // hila::out0 << "ii " << ii << " bi " << bi << '\n';
130
131 lattice.nodes.map_array[i] = bi * nblocks + ii;
132 }
133}
134
135/// And the call interface for remapping
136
137unsigned lattice_struct::allnodes::remap(unsigned i) const {
138 return lattice.nodes.map_array[i];
139}
140
141unsigned lattice_struct::allnodes::inverse_remap(unsigned idx) const {
142 for (int i = 0; i < lattice.nodes.number; i++)
143 if (lattice.nodes.map_array[i] == idx)
144 return i;
145
146 return 1 << 30; // big number, crash
147}
148
149
150#else
151
152NODE_LAYOUT_BLOCK or NODE_LAYOUT_TRIVIAL must be defined
153
154#endif
const auto & fill(const S rhs)
Matrix fill.
Definition matrix.h:937
#define foralldir(d)
Macro to loop over (all) Direction(s)
Definition coordinates.h:78
This file defines all includes for HILA.
std::ostream out0
This writes output only from main process (node 0)
#define NODE_LAYOUT_BLOCK
Definition params.h:62
unsigned remap(unsigned i) const
And the call interface for remapping.