00001 #ifndef SGV_TREE_ALGORITHMS_HPP_
00002 #define SGV_TREE_ALGORITHMS_HPP_
00003
00004 #include "libmpib_coll.h"
00005 #include "comm_tree.hpp"
00006 #include "mpib_coll.h"
00007 #include <boost/graph/graphviz.hpp>
00008 #include <limits.h>
00009
00010 namespace MPIB {
00011
00013 namespace SGv {
00014 using namespace comm_tree;
00015
00017 int tag = 0;
00018
00023 class Assembler {
00024 private:
00026 const map<int, int>& rank2index;
00028 const int* counts;
00030 const int* displs;
00032 int& count;
00034 int* lengths;
00036 int* indices;
00037 public:
00038 Assembler(const map<int, int>& _rank2index, const int* _counts, const int* _displs,
00039 int& _count, int* _lengths, int* _indices):
00040 rank2index(_rank2index), counts(_counts), displs(_displs),
00041 count(_count), lengths(_lengths), indices(_indices)
00042 {
00043 count = 0;
00044 }
00045 void preorder(Vertex vertex, Tree& tree) {
00046 int index = rank2index.find(get(vertex_index, tree, vertex))->second;
00047 lengths[count] = counts[index];
00048 indices[count] = displs[index];
00049 count++;
00050 }
00051 void inorder(Vertex vertex, Tree& tree) {}
00052 void postorder(Vertex vertex, Tree& tree) {}
00053 };
00054
00059 class Indexer {
00060 private:
00062 const int* rscounts;
00064 int& index;
00066 map<int, int>& rank2index;
00068 int* counts;
00070 int* displs;
00071 int& count;
00073 public:
00074 Indexer(const int* _rscounts, int& _index, map<int, int>& _rank2index, int* _counts, int* _displs, int& _count):
00075 rscounts(_rscounts), index(_index), rank2index(_rank2index), counts(_counts), displs(_displs), count(_count)
00076 {
00077 index = 0;
00078 count = 0;
00079 }
00080 void preorder(Vertex vertex, Tree& tree) {
00081 int rank = get(vertex_index, tree, vertex);
00082 rank2index[rank] = index;
00083 counts[index] = rscounts[rank];
00084 displs[index] = index == 0 ? 0 : displs[index - 1] + counts[index - 1];
00085 count += counts[index];
00086 index++;
00087 }
00088 void inorder(Vertex vertex, Tree& tree) {}
00089 void postorder(Vertex vertex, Tree& tree) {}
00090 };
00091
00093 class Vertex_writer {
00094 private:
00095 Graph& graph;
00096 const int* counts;
00097 public:
00098 Vertex_writer(Graph& _graph, const int* _counts): graph(_graph), counts(_counts) {}
00099 void operator()(std::ostream& out, const Vertex& v) const {
00100 int rank = get(vertex_index, graph, v);
00101 out << "[label = \"" << rank << " (" << counts[rank] << ")\"]";
00102 }
00103 };
00104
00106 class Edge_writer {
00107 private:
00108 Graph& graph;
00109 const int* counts;
00110
00112 class Indexer {
00113 private:
00114 const int* counts;
00115 int& count;
00116 public:
00117 Indexer(const int* _counts, int& _count): counts(_counts), count(_count) {
00118 count = 0;
00119 }
00120 void preorder(Vertex vertex, Tree& tree) {
00121 count += counts[get(vertex_index, tree, vertex)];
00122 }
00123 void inorder(Vertex vertex, Tree& tree) {}
00124 void postorder(Vertex vertex, Tree& tree) {}
00125 };
00126
00127 public:
00128 Edge_writer(Graph& _graph, const int* _counts):
00129 graph(_graph), counts(_counts) {}
00130 void operator()(std::ostream& out, const Edge& e) const {
00131 Vertex v = target(e, graph);
00132 int count;
00133 Tree tree(graph, v);
00134 traverse_tree(v, tree, Indexer(counts, count));
00135 out << "[label = \"" << count << "\"]";
00136 }
00137 };
00138 }
00139 }
00140
00145 template <typename Builder>
00146 int MPIB_Scatterv_tree_algorithm(Builder builder, MPIB_child_traverse_order order,
00147 void* sendbuf, int* sendcounts, int* displs, MPI_Datatype sendtype,
00148 void* recvbuf, int recvcount, MPI_Datatype recvtype,
00149 int root, MPI_Comm _comm)
00150 {
00151 using namespace MPIB::SGv;
00152
00153 MPI_Comm comm = _comm;
00154 if (mpib_coll_sgv == 0)
00155 MPI_Comm_dup(_comm, &comm);
00156
00157 int tag = 0;
00158 if (mpib_coll_sgv == 2) {
00159 if (++tag == INT_MAX)
00160 tag = 0;
00161 tag = tag;
00162 }
00163
00164 int size;
00165 MPI_Comm_size(comm, &size);
00166 int* counts = (int*)malloc(sizeof(int) * size);
00167 MPI_Aint sendext;
00168 MPI_Type_extent(sendtype, &sendext);
00169 int rank;
00170 MPI_Comm_rank(comm, &rank);
00171 if (rank == root || mpib_coll_sgv == 3) {
00172 for (int i = 0; i < size; i++)
00173 counts[i] = sendcounts[i] * sendext;
00174 }
00175 if (mpib_coll_sgv == 1)
00176 MPI_Bcast(counts, size, MPI_INT, root, comm);
00177
00178 Graph graph;
00179 Vertex r, u, v;
00180 if (rank == root || mpib_coll_sgv == 1 || mpib_coll_sgv == 3)
00181 builder.build(size, root, rank, counts, graph, r, u, v);
00182 if ((rank == root) && mpib_coll_verbose)
00183 write_graphviz(cout, graph, Vertex_writer(graph, counts), Edge_writer(graph, counts));
00184
00185 map<int, int> rank2index;
00186 char* buffer = NULL;
00187 int* _counts = (int*)malloc(sizeof(int) * size);
00188 int* _displs = (int*)malloc(sizeof(int) * size);
00189 if (rank == root) {
00190
00191 for (int i = 0; i < size; i++) {
00192 rank2index[i] = i;
00193 _counts[i] = sendcounts[i] * sendext;
00194 _displs[i] = displs[i] * sendext;
00195 }
00196 buffer = (char*)sendbuf;
00197 } else {
00198
00199 if (mpib_coll_sgv == 0 || mpib_coll_sgv == 2) {
00200 MPI_Status status;
00201 MPI_Probe(MPI_ANY_SOURCE, tag, comm, &status);
00202 int length;
00203 MPI_Get_count(&status, MPI_CHAR, &length);
00204 buffer = (char*)malloc(sizeof(char) * (length - sizeof(int) * size));
00205 MPI_Datatype dt;
00206 int lengths[2] = {length - sizeof(int) * size, size};
00207 MPI_Aint indices[2] = {0, (char*)counts - buffer};
00208 MPI_Datatype types[2] = {MPI_CHAR, MPI_INT};
00209 MPI_Type_struct(2, lengths, indices, types, &dt);
00210 MPI_Type_commit(&dt);
00211 MPI_Recv(buffer, 1, dt, status.MPI_SOURCE, status.MPI_TAG, comm, MPI_STATUS_IGNORE);
00212 MPI_Type_free(&dt);
00213 builder.build(size, root, rank, counts, graph, r, u, v);
00214 }
00215
00216 Tree tree = Tree(graph, r);
00217 int index;
00218 int count;
00219 traverse_tree(v, tree,
00220 Indexer(counts, index, rank2index, _counts, _displs, count));
00221
00222 if (mpib_coll_sgv == 1 || mpib_coll_sgv == 3) {
00223 buffer = (char*)malloc(sizeof(char) * count);
00224 MPI_Recv(buffer, count, MPI_CHAR, get(vertex_index, graph, u), 0, comm, MPI_STATUS_IGNORE);
00225 }
00226 }
00227
00228 MPI_Aint recvext;
00229 MPI_Type_extent(recvtype, &recvext);
00230 memcpy(recvbuf, buffer + _displs[rank2index[rank]], recvcount * recvext);
00231
00232 Tree tree = Tree(graph, r);
00233 int subtree_size = rank2index.size();
00234 int count;
00235 int* lengths = (int*)malloc(sizeof(int) * subtree_size);
00236 int* indices = (int*)malloc(sizeof(int) * subtree_size);
00237 MPI_Datatype* dts = (MPI_Datatype*)malloc(sizeof(MPI_Datatype) * subtree_size);
00238 MPI_Request* reqs = (MPI_Request*)malloc(sizeof(MPI_Request) * subtree_size);
00239 int child_counter;
00240 Adjacency_iterator ai, ai_end;
00241 tie(ai, ai_end) = adjacent_vertices(v, graph);
00242 for(child_counter = 0; ai != ai_end; child_counter++) {
00243 Vertex t = (order == R2L) ? *(--ai_end) : *(ai++);
00244
00245 traverse_tree(t, tree,
00246 Assembler(rank2index, _counts, _displs, count, lengths, indices));
00247
00248 if (mpib_coll_sgv == 0 || mpib_coll_sgv == 2) {
00249 lengths[count] = sizeof(int) * size;
00250 indices[count] = (char*)counts - buffer;
00251 count++;
00252 }
00253
00254 MPI_Type_indexed(count, lengths, indices, MPI_CHAR, &dts[child_counter]);
00255 MPI_Type_commit(&dts[child_counter]);
00256 MPI_Isend(buffer, 1, dts[child_counter], get(vertex_index, graph, t), 0, comm, &reqs[child_counter]);
00257 }
00258 free(lengths);
00259 free(indices);
00260 MPI_Waitall(child_counter, reqs, MPI_STATUSES_IGNORE);
00261 free(reqs);
00262 for (int i = 0; i < child_counter; i++)
00263 MPI_Type_free(&dts[i]);
00264 free(dts);
00265 if (rank != root)
00266 free(buffer);
00267 free(_counts);
00268 free(_displs);
00269 free(counts);
00270 if (mpib_coll_sgv == 0)
00271 MPI_Comm_free(&comm);
00272 return MPI_SUCCESS;
00273 }
00274
00279 template <typename Builder>
00280 int MPIB_Gatherv_tree_algorithm(Builder builder, MPIB_child_traverse_order order,
00281 void* sendbuf, int sendcount, MPI_Datatype sendtype,
00282 void* recvbuf, int* recvcounts, int* displs, MPI_Datatype recvtype,
00283 int root, MPI_Comm _comm)
00284 {
00285 using namespace MPIB::SGv;
00286
00287 MPI_Comm comm = _comm;
00288 if (mpib_coll_sgv == 0)
00289 MPI_Comm_dup(_comm, &comm);
00290
00291 int tag = 0;
00292 if (mpib_coll_sgv == 2) {
00293 if (++tag == INT_MAX)
00294 tag = 0;
00295 tag = tag;
00296 }
00297
00298 int size;
00299 MPI_Comm_size(comm, &size);
00300 int* counts = (int*)malloc(sizeof(int) * size);
00301 MPI_Aint recvext;
00302 MPI_Type_extent(recvtype, &recvext);
00303 int rank;
00304 MPI_Comm_rank(comm, &rank);
00305 if (rank == root || mpib_coll_sgv == 3) {
00306 for (int i = 0; i < size; i++)
00307 counts[i] = recvcounts[i] * recvext;
00308 }
00309 if (mpib_coll_sgv == 1)
00310 MPI_Bcast(counts, size, MPI_INT, root, comm);
00311
00312 Graph graph;
00313 Vertex r, u, v;
00314 if (rank == root || mpib_coll_sgv == 1 || mpib_coll_sgv == 3)
00315 builder.build(size, root, rank, counts, graph, r, u, v);
00316 if ((rank == root) && mpib_coll_verbose)
00317 write_graphviz(cout, graph, Vertex_writer(graph, counts), Edge_writer(graph, counts));
00318
00319 map<int, int> rank2index;
00320 char* buffer = NULL;
00321 int count;
00322 int* _counts = (int*)malloc(sizeof(int) * size);
00323 int* _displs = (int*)malloc(sizeof(int) * size);
00324 if (rank == root) {
00325
00326 for (int i = 0; i < size; i++) {
00327 rank2index[i] = i;
00328 _counts[i] = recvcounts[i] * recvext;
00329 _displs[i] = displs[i] * recvext;
00330 }
00331 buffer = (char*)recvbuf;
00332 } else {
00333
00334 if (mpib_coll_sgv == 0 || mpib_coll_sgv == 2) {
00335 MPI_Recv(counts, size, MPI_INT, MPI_ANY_SOURCE, tag, comm, MPI_STATUS_IGNORE);
00336 builder.build(size, root, rank, counts, graph, r, u, v);
00337 }
00338
00339 Tree tree = Tree(graph, r);
00340 int index;
00341 traverse_tree(v, tree,
00342 Indexer(counts, index, rank2index, _counts, _displs, count));
00343 buffer = (char*)malloc(sizeof(char) * count);
00344 }
00345
00346 MPI_Aint sendext;
00347 MPI_Type_extent(sendtype, &sendext);
00348 memcpy(buffer + _displs[rank2index[rank]], sendbuf, sendcount * sendext);
00349
00350 if (mpib_coll_sgv == 0 || mpib_coll_sgv == 2) {
00351 Adjacency_iterator ai, ai_end;
00352 tie(ai, ai_end) = adjacent_vertices(v, graph);
00353 while (ai != ai_end)
00354 MPI_Send(counts, size, MPI_INT, get(vertex_index, graph, (order == R2L) ? *(--ai_end) : *(ai++)), tag, comm);
00355 }
00356
00357 Tree tree = Tree(graph, r);
00358 int subtree_size = rank2index.size() - 1;
00359 int c;
00360 int* lengths = (int*)malloc(sizeof(int) * subtree_size);
00361 int* indices = (int*)malloc(sizeof(int) * subtree_size);
00362 MPI_Datatype* dts = (MPI_Datatype*)malloc(sizeof(MPI_Datatype) * subtree_size);
00363 MPI_Request* reqs = (MPI_Request*)malloc(sizeof(MPI_Request) * subtree_size);
00364 int child_counter;
00365 Adjacency_iterator ai, ai_end;
00366 tie(ai, ai_end) = adjacent_vertices(v, graph);
00367 for(child_counter = 0; ai != ai_end; child_counter++) {
00368 Vertex t = (order == R2L) ? *(--ai_end) : *(ai++);
00369
00370 traverse_tree(t, tree,
00371 Assembler(rank2index, _counts, _displs, c, lengths, indices));
00372
00373 MPI_Type_indexed(c, lengths, indices, MPI_CHAR, &dts[child_counter]);
00374 MPI_Type_commit(&dts[child_counter]);
00375 MPI_Irecv(buffer, 1, dts[child_counter], get(vertex_index, graph, t), 0, comm, &reqs[child_counter]);
00376 }
00377 free(lengths);
00378 free(indices);
00379 MPI_Waitall(child_counter, reqs, MPI_STATUSES_IGNORE);
00380 free(reqs);
00381 for (int i = 0; i < child_counter; i++)
00382 MPI_Type_free(&dts[i]);
00383 free(dts);
00384
00385 if (rank != root)
00386 MPI_Send(buffer, count, MPI_CHAR, get(vertex_index, graph, u), 0, comm);
00387 if (rank != root)
00388 free(buffer);
00389 free(_counts);
00390 free(_displs);
00391 free(counts);
00392 if (mpib_coll_sgv == 0)
00393 MPI_Comm_free(&comm);
00394 return MPI_SUCCESS;
00395 }
00396
00397 #endif