Clean up Info and code in group-and-sort

This commit is contained in:
Alejandro Gallo 2021-11-08 16:24:31 +01:00
parent 52d13992ef
commit bfbbf75b0f

109
atrip.org
View File

@ -1735,8 +1735,6 @@ size_t isOnNode(size_t tuple, size_t nodes) { return tuple % nodes; }
struct Info { struct Info {
size_t nNodes; size_t nNodes;
size_t Nv;
size_t np;
size_t nodeId; size_t nodeId;
}; };
@ -1758,30 +1756,27 @@ std::vector<size_t> getTupleNodes(ABCTuple t, size_t nNodes) {
#+end_src #+end_src
**** Distribution **** Distribution
wording: home element = element which is located on the given node wording: home element = element which is located on the given node
1. we distribute the tuples such that each tuple has at least one 'home element' 1. we distribute the tuples such that each tuple has at least one 'home element'
2. we sort each tuple in a way that the 'home element' are the fastest indices 2. we sort each tuple in a way that the 'home element' are the fastest indices
3. we sort the list of tuples on every node 3. we sort the list of tuples on every node
4. we resort the tuples that for every tuple abc the following holds: a<b<c 4. we resort the tuples that for every tuple abc the following holds: a<b<c
#+begin_src c++ :tangle (atrip-tuples-h) #+begin_src c++ :tangle (atrip-tuples-h)
std::vector<ABCTuple> ABCTuples specialDistribution(Info const& info, ABCTuples const& allTuples) {
specialDistribution(Info info, std::vector<ABCTuple> const& allTuples) {
std::vector<ABCTuple> nodeTuples; ABCTuples nodeTuples;
size_t nNodes(info.nNodes); size_t const nNodes(info.nNodes);
size_t np(info.np);
size_t N(allTuples.size());
// nodeid tuple list std::map< size_t /* nodeId */, ABCTuples >
std::map<size_t, std::vector<ABCTuple> > container1d; container1d, container2d, container3d;
std::map<size_t, std::vector<ABCTuple> > container2d;
std::map<size_t, std::vector<ABCTuple> > container3d;
// build container-n-d's // build container-n-d's
for (auto const& t: allTuples) { for (auto const& t: allTuples) {
// one which node(s) are the tuple elements located... // one which node(s) are the tuple elements located...
// put them into the right container // put them into the right container
auto _nodes = getTupleNodes(t, nNodes); auto const _nodes = getTupleNodes(t, nNodes);
switch (_nodes.size()) { switch (_nodes.size()) {
case 1: case 1:
container1d[_nodes[0]].push_back(t); container1d[_nodes[0]].push_back(t);
@ -1812,7 +1807,7 @@ specialDistribution(Info info, std::vector<ABCTuple> const& allTuples) {
std::cout << "\tBuilding 2-d containers\n"; std::cout << "\tBuilding 2-d containers\n";
// DISTRIBUTE 2-d containers // DISTRIBUTE 2-d containers
//the tuples which are located at two nodes are half/half given to these nodes //the tuples which are located at two nodes are half/half given to these nodes
for (auto &m: container2d) { for (auto const& m: container2d) {
auto const& _tuplesVec = m.second; auto const& _tuplesVec = m.second;
const const
@ -1892,22 +1887,21 @@ specialDistribution(Info info, std::vector<ABCTuple> const& allTuples) {
* the 'home elements' are the fastest index. * the 'home elements' are the fastest index.
* 1:yyy 2:yyn(x) 3:yny(x) 4:ynn(x) 5:nyy 6:nyn(x) 7:nny 8:nnn * 1:yyy 2:yyn(x) 3:yny(x) 4:ynn(x) 5:nyy 6:nyn(x) 7:nny 8:nnn
*/ */
size_t myNode = info.nodeId;
for (auto &nt: nodeTuples){ for (auto &nt: nodeTuples){
if ( isOnNode(nt[0], nNodes) == myNode ){ // 1234 if ( isOnNode(nt[0], nNodes) == info.nodeId ){ // 1234
if ( isOnNode(nt[2], nNodes) != myNode ){ // 24 if ( isOnNode(nt[2], nNodes) != info.nodeId ){ // 24
size_t const x(nt[0]); size_t const x(nt[0]);
nt[0] = nt[2]; // switch first and last nt[0] = nt[2]; // switch first and last
nt[2] = x; nt[2] = x;
} }
else if ( isOnNode(nt[1], nNodes) != myNode){ // 3 else if ( isOnNode(nt[1], nNodes) != info.nodeId){ // 3
size_t const x(nt[0]); size_t const x(nt[0]);
nt[0] = nt[1]; // switch first two nt[0] = nt[1]; // switch first two
nt[1] = x; nt[1] = x;
} }
} else { } else {
if ( isOnNode(nt[1], nNodes) == myNode // 56 if ( isOnNode(nt[1], nNodes) == info.nodeId // 56
&& isOnNode(nt[2], nNodes) != myNode && isOnNode(nt[2], nNodes) != info.nodeId
) { // 6 ) { // 6
size_t const x(nt[1]); size_t const x(nt[1]);
nt[1] = nt[2]; // switch last two nt[1] = nt[2]; // switch last two
@ -1960,32 +1954,22 @@ std::vector<ABCTuple> main(MPI_Comm universe, size_t Nv) {
std::vector<ABCTuple> result; std::vector<ABCTuple> result;
const auto nodeNames(getNodeNames(universe)); auto const nodeNames(getNodeNames(universe));
auto nodeNamesUnique(nodeNames); size_t const nNodes = unique(nodeNames).size();
{
const auto& last = std::unique(nodeNamesUnique.begin(),
nodeNamesUnique.end());
nodeNamesUnique.erase(last, nodeNamesUnique.end());
}
// we pick one rank from every node
auto const nodeInfos = getNodeInfos(nodeNames); auto const nodeInfos = getNodeInfos(nodeNames);
size_t const nNodes = nodeNamesUnique.size();
// We want to construct a communicator which only contains of one // We want to construct a communicator which only contains of one
// element per node // element per node
bool const makeDistribution bool const computeDistribution
= nodeInfos[rank].localRank == 0; = nodeInfos[rank].localRank == 0;
std::vector<ABCTuple> std::vector<ABCTuple>
nodeTuples = makeDistribution nodeTuples
? specialDistribution(Info { nNodes = computeDistribution
, Nv ? specialDistribution(Info{nNodes, nodeInfos[rank].nodeId},
, np getAllTuplesList(Nv))
, nodeInfos[rank].nodeId : std::vector<ABCTuple>()
}, ;
getAllTuplesList(Nv))
: std::vector<ABCTuple>()
;
LOG(1,"Atrip") << "got nodeTuples\n"; LOG(1,"Atrip") << "got nodeTuples\n";
@ -2009,7 +1993,7 @@ We have to communicate this quantity among all nodes.
#+begin_src c++ :tangle (atrip-tuples-h) #+begin_src c++ :tangle (atrip-tuples-h)
const size_t size_t const
tuplesPerRankLocal tuplesPerRankLocal
= nodeTuples.size() / nodeInfos[rank].ranksPerNode = nodeTuples.size() / nodeInfos[rank].ranksPerNode
+ size_t(nodeTuples.size() % nodeInfos[rank].ranksPerNode != 0) + size_t(nodeTuples.size() % nodeInfos[rank].ranksPerNode != 0)
@ -2056,7 +2040,8 @@ and add some fake tuples at the end as padding.
size_t const totalTuples size_t const totalTuples
= tuplesPerRankGlobal * nodeInfos[rank].ranksPerNode; = tuplesPerRankGlobal * nodeInfos[rank].ranksPerNode;
if (makeDistribution) { if (computeDistribution) {
// pad with FAKE_TUPLEs
nodeTuples.insert(nodeTuples.end(), nodeTuples.insert(nodeTuples.end(),
totalTuples - nodeTuples.size(), totalTuples - nodeTuples.size(),
FAKE_TUPLE); FAKE_TUPLE);
@ -2113,48 +2098,6 @@ Therefore, the =displacements= are simply the vector
and the =sendCounts= vector is simply the constant vector and the =sendCounts= vector is simply the constant vector
=tuplesPerRankLocal= of size =ranksPerNode=. =tuplesPerRankLocal= of size =ranksPerNode=.
TODO: Remove
#+begin_src c++
{
std::vector<int> const
sendCounts(nodeInfos[rank].ranksPerNode, tuplesPerRankLocal);
std::vector<int>
displacements(nodeInfos[rank].ranksPerNode);
std::iota(displacements.begin(),
displacements.end(),
tuplesPerRankLocal);
// important!
result.resize(tuplesPerRankLocal);
// construct mpi type for abctuple
MPI_Datatype MPI_ABCTUPLE;
MPI_Type_vector(nodeTuples[0].size(), 1, 1, MPI_UINT64_T, &MPI_ABCTUPLE);
MPI_Type_commit(&MPI_ABCTUPLE);
LOG(1,"Atrip") << "scattering tuples \n";
MPI_Scatterv(nodeTuples.data(),
sendCounts.data(),
displacements.data(),
MPI_ABCTUPLE,
result.data(),
tuplesPerRankLocal,
MPI_ABCTUPLE,
0,
INTRA_COMM);
// free type
MPI_Type_free(&MPI_ABCTUPLE);
}
#+end_src
and now we have to make sure that the size of the result
is the same with every rank in the universe communicator,
inserting fake tuples where needed
#+begin_src c++ :tangle (atrip-tuples-h) #+begin_src c++ :tangle (atrip-tuples-h)
LOG(1,"Atrip") << "scattering tuples \n"; LOG(1,"Atrip") << "scattering tuples \n";