COMBINATORIAL_BLAS 1.6
 
Loading...
Searching...
No Matches
WriteMCLClusters.h
Go to the documentation of this file.
1/****************************************************************/
2/* Parallel Combinatorial BLAS Library (for Graph Computations) */
3/* version 1.6 -------------------------------------------------*/
4/* date: 6/15/2017 ---------------------------------------------*/
5/* authors: Ariful Azad, Aydin Buluc --------------------------*/
6/****************************************************************/
7
8
9
10#include <mpi.h>
11#include <stdint.h>
12#include <sys/time.h>
13#include <iostream>
14#include <fstream>
15#include <string>
16#include <sstream> // Required for stringstreams
17#include <ctime>
18#include <cmath>
19#include "CombBLAS/CombBLAS.h"
20
21namespace combblas {
22
24{
25public:
26 // no reader
27 template <typename c, typename t, typename VT>
28 void save(std::basic_ostream<c,t>& os, std::vector<VT> & strvec, int64_t index)
29 {
30 for (auto it = strvec.begin() ; it != strvec.end(); ++it)
31 os << *it << " ";
32 }
33};
34
35
44template <class IT>
45void WriteMCLClusters(std::string ofName, FullyDistVec<IT, IT> clustIdForVtx, FullyDistVec<IT, std::array<char, MAXVERTNAME> > vtxLabels)
46{
47 auto commGrid = clustIdForVtx.getcommgrid();
48 MPI_Comm World = commGrid->GetWorld();
49 int nprocs = commGrid->GetSize();
50
51 // find the number of clusters
52 IT nclusters = clustIdForVtx.Reduce(maximum<IT>(), (IT) 0 ) ;
53 nclusters ++; // because of zero based indexing for clusters
54
55 std::vector<int> rdispls(nprocs+1);
56 std::vector<int> recvcnt(nprocs);
57 std::vector<int> sendcnt(nprocs,0);
58 std::vector<int> sdispls(nprocs+1);
59 IT ploclen = clustIdForVtx.LocArrSize();
60
61
62 const IT* larr = clustIdForVtx.GetLocArr(); // local part of cluster ids for vertices
63 //just to get the destination processor
65 for(IT i=0; i < ploclen; ++i)
66 {
67 IT locind;
68 int owner = temp.Owner(larr[i], locind);
69 sendcnt[owner]++;
70 }
71 MPI_Alltoall(sendcnt.data(), 1, MPI_INT, recvcnt.data(), 1, MPI_INT, World);
72
73 sdispls[0] = 0;
74 rdispls[0] = 0;
75 for(int i=0; i<nprocs; ++i)
76 {
77 sdispls[i+1] = sdispls[i] + sendcnt[i];
78 rdispls[i+1] = rdispls[i] + recvcnt[i];
79 }
80
81
82 typedef std::array<char, MAXVERTNAME> STRASARRAY;
83 typedef std::pair< IT, STRASARRAY> TYPE2SEND;
84 const STRASARRAY* lVtxLabels = vtxLabels.GetLocArr();
85 std::vector<TYPE2SEND> senddata(ploclen);
86
87
88 // Pack cluster and vertex information to send
89 std::vector<int> count(nprocs, 0);
90 for(IT i=0; i < ploclen; ++i)
91 {
92 IT locind;
93 int owner = temp.Owner(larr[i], locind);
94 int idx = sdispls[owner] + count[owner];
95 count[owner]++;
96 senddata[idx] = TYPE2SEND(locind, lVtxLabels[i]); // sending local cluster ids for the destination processor
97 }
98
100 MPI_Type_contiguous(sizeof(TYPE2SEND), MPI_CHAR, &MPI_CLUST);
102
103 IT totrecv = rdispls[nprocs];
104 std::vector<TYPE2SEND> recvdata(totrecv);
105
106 MPI_Alltoallv(senddata.data(), sendcnt.data(), sdispls.data(), MPI_CLUST, recvdata.data(), recvcnt.data(), rdispls.data(), MPI_CLUST, World);
107
108
109 // Receiver groups vertices by cluster ids
110 std::vector< std::vector<std::string> > vtxGroupbyCC(temp.LocArrSize());
111 for(int i=0; i<totrecv; ++i)
112 {
113 IT clusterID = recvdata[i].first;
114 auto locnull = std::find(recvdata[i].second.begin(), recvdata[i].second.end(), '\0'); // find the null character (or string::end)
115 std::string vtxstr(recvdata[i].second.begin(), locnull);
116 vtxGroupbyCC[clusterID].push_back(vtxstr);
117 }
118
119 // in each cluster sort vertex labels
120#ifdef THREADED
121#pragma omp parallel for
122#endif
123 for(unsigned int i=0; i<vtxGroupbyCC.size(); ++i)
124 {
125 std::sort(vtxGroupbyCC[i].begin(), vtxGroupbyCC[i].end());
126 }
127
128 // Create a vector locally populate it
129 FullyDistVec<IT,std::vector<std::string> > clusters(commGrid, nclusters, std::vector<std::string>{});
130 for(int i=0; i<clusters.LocArrSize(); i++)
131 {
132 clusters.SetLocalElement(i, vtxGroupbyCC[i]);
133 }
134 // do not write header and 1-based
135 clusters.ParallelWrite(ofName, 1, HipMCLClusterSaveHandler(), false);
136
137}
138
139
140
148template <class IT>
150{
151 auto commGrid = clustIdForVtx.getcommgrid();
152 MPI_Comm World = commGrid->GetWorld();
153 int nprocs = commGrid->GetSize();
154 IT lenuntil = clustIdForVtx.LengthUntil();
155
156 // find the number of clusters
157 IT nclusters = clustIdForVtx.Reduce(maximum<IT>(), (IT) 0 ) ;
158 nclusters ++; // because of zero based indexing for clusters
159
160 std::vector<int> rdispls(nprocs+1);
161 std::vector<int> recvcnt(nprocs);
162 std::vector<int> sendcnt(nprocs,0);
163 std::vector<int> sdispls(nprocs+1);
164 IT ploclen = clustIdForVtx.LocArrSize();
165
166
167 const IT* larr = clustIdForVtx.GetLocArr(); // local part of cluster ids for vertices
168 //just to get the destination processor
170 for(IT i=0; i < ploclen; ++i)
171 {
172 IT locind;
173 int owner = temp.Owner(larr[i], locind);
174 sendcnt[owner]++;
175 }
176 MPI_Alltoall(sendcnt.data(), 1, MPI_INT, recvcnt.data(), 1, MPI_INT, World);
177
178 sdispls[0] = 0;
179 rdispls[0] = 0;
180 for(int i=0; i<nprocs; ++i)
181 {
182 sdispls[i+1] = sdispls[i] + sendcnt[i];
183 rdispls[i+1] = rdispls[i] + recvcnt[i];
184 }
185
186
187
188 std::vector<std::pair<IT, IT>> senddata(ploclen);
189 // Pack cluster and vertex information to send
190 std::vector<int> count(nprocs, 0);
191 for(IT i=0; i < ploclen; ++i)
192 {
193 IT locind;
194 int owner = temp.Owner(larr[i], locind);
195 int idx = sdispls[owner] + count[owner];
196 count[owner]++;
197 senddata[idx] = std::make_pair(locind, i+lenuntil+base); // sending local cluster ids for the destination processor
198 }
199
201 MPI_Type_contiguous(sizeof(std::pair<IT, IT>), MPI_CHAR, &MPI_CLUST);
203
204 IT totrecv = rdispls[nprocs];
205 std::vector<std::pair<IT, IT>> recvdata(totrecv);
206
207 MPI_Alltoallv(senddata.data(), sendcnt.data(), sdispls.data(), MPI_CLUST, recvdata.data(), recvcnt.data(), rdispls.data(), MPI_CLUST, World);
208
209
210 // Receiver groups vertices by cluster ids
211 std::vector< std::vector<IT> > vtxGroupbyCC(temp.LocArrSize());
212 for(int i=0; i<totrecv; ++i)
213 {
214 IT clusterID = recvdata[i].first;
215 vtxGroupbyCC[clusterID].push_back(recvdata[i].second);
216 }
217
218 // Create a vector locally populate it
219 FullyDistVec<IT,std::vector<IT> > clusters(commGrid, nclusters, std::vector<IT>{});
220 for(int i=0; i<clusters.LocArrSize(); i++)
221 {
222 clusters.SetLocalElement(i, vtxGroupbyCC[i]);
223 }
224 // do not write header and 1-based
225 clusters.ParallelWrite(ofName, 1, HipMCLClusterSaveHandler(), false);
226
227}
228
229}
230
int64_t IT
void save(std::basic_ostream< c, t > &os, std::vector< VT > &strvec, int64_t index)
int nprocs
Definition comms.cpp:55
void WriteMCLClusters(std::string ofName, FullyDistVec< IT, IT > clustIdForVtx, FullyDistVec< IT, std::array< char, MAXVERTNAME > > vtxLabels)