00001 #ifndef SGV_TREE_BUILDERS_HPP_
00002 #define SGV_TREE_BUILDERS_HPP_
00003
00004 #include "mpib_coll.h"
00005 #include "comm_tree.hpp"
00006 #include <functional>
00007 #include <algorithm>
00008
00009 namespace MPIB {
00010
00028 namespace SGv {
00029 using namespace comm_tree;
00030
00035 class Binomial_builder {
00036 public:
00037 void build(int size, int root, int rank, int* counts,
00038 Graph& g, Vertex& r, Vertex& u, Vertex& v)
00039 {
00040 r = add_vertex(g);
00041 put(vertex_index, g, r, root);
00042 if (rank == root) {
00043 v = r;
00044 }
00045
00046 deque<pair<Vertex, pair<int, int> > > subtrees;
00047
00048 for (int tmp = size - 1, bin = 1, index = 1; tmp > 0; tmp /= 2, bin *= 2) {
00049 if (tmp % 2) {
00050 subtrees.push_back(make_pair(r, make_pair(index, bin)));
00051 index += bin;
00052 }
00053 }
00054
00055 while (!subtrees.empty()) {
00056 pair<Vertex, pair<int, int> >& subtree = subtrees.front();
00057 Vertex s = subtree.first;
00058 Vertex t = add_vertex(g);
00059
00060 int index = subtree.second.first;
00061 int target = root + index;
00062 if (target >= size)
00063 target -= size;
00064 put(vertex_index, g, t, target);
00065 if (target == rank) {
00066 u = s;
00067 v = t;
00068 }
00069 pair<Edge, bool> e = add_edge(s, t, g);
00070 int bin = subtree.second.second;
00071 subtrees.pop_front();
00072 index += bin;
00073 for (bin /= 2; bin > 0; bin /= 2) {
00074 index -= bin;
00075 subtrees.push_front(make_pair(t, make_pair(index, bin)));
00076 }
00077 }
00078 }
00079 };
00080
00081 struct second_less: public binary_function<pair<int, int>, pair<int, int>, bool> {
00082 bool operator()(const pair<int, int>& x, const pair<int, int>& y) const {
00083 return x.second < y.second;
00084 }
00085 };
00086
00087 struct second_greater: public binary_function<pair<int, int>, pair<int, int>, bool> {
00088 bool operator()(const pair<int, int>& x, const pair<int, int>& y) const {
00089 return x.second > y.second;
00090 }
00091 };
00092
00098 class Sorted_binomial_builder {
00099 private:
00100 MPIB_sort_order selectedOrder;
00101 public:
00102 Sorted_binomial_builder(MPIB_sort_order _selectedOrder): selectedOrder(_selectedOrder) {}
00103
00104 void build(int size, int root, int rank, int* counts,
00105 Graph& g, Vertex& r, Vertex& u, Vertex& v)
00106 {
00107
00108 vector<pair<int, int> > procs;
00109 for (int i = 0; i < size; i++)
00110 if (i != root)
00111 procs.push_back(make_pair(i, counts[i]));
00112 if (selectedOrder == ASC)
00113 sort(procs.begin(), procs.end(), second_less());
00114 else
00115 sort(procs.begin(), procs.end(), second_greater());
00116 r = add_vertex(g);
00117 put(vertex_index, g, r, root);
00118 if (rank == root) {
00119 v = r ;
00120 }
00121
00122 deque<pair<Vertex, pair<int, int> > > subtrees;
00123
00124 for (int tmp = size - 1, bin = 1, index = 1; tmp > 0; tmp /= 2, bin *= 2) {
00125 if (tmp % 2) {
00126 subtrees.push_back(make_pair(r, make_pair(index, bin)));
00127 index += bin;
00128 }
00129 }
00130
00131 while (!subtrees.empty()) {
00132 pair<Vertex, pair<int, int> >& subtree = subtrees.front();
00133 Vertex s = subtree.first;
00134 Vertex t = add_vertex(g);
00135 int index = subtree.second.first;
00136 int target = procs[index - 1].first;
00137 put(vertex_index, g, t, target);
00138 if (target == rank) {
00139 u = s;
00140 v = t;
00141 }
00142 pair<Edge, bool> e = add_edge(s, t, g);
00143 int bin = subtree.second.second;
00144 subtrees.pop_front();
00145 index += bin;
00146 for (bin /= 2; bin > 0; bin /= 2) {
00147 index -= bin;
00148 subtrees.push_front(make_pair(t, make_pair(index, bin)));
00149 }
00150 }
00151 }
00152 };
00153
00158 class Traff_builder {
00159 public:
00160 void build(int size, int root, int rank, int* counts,
00161 Graph& g, Vertex& r, Vertex& u, Vertex& v)
00162 {
00163
00164 deque<pair<int, int> > procs;
00165 for (int i = 0; i < size; i++)
00166 if (i != root)
00167 procs.push_back(make_pair(i, counts[i]));
00168 sort(procs.begin(), procs.end(), second_greater());
00169 r = add_vertex(g);
00170 put(vertex_index, g, r, root);
00171 if (rank == root)
00172 v = r;
00173
00174 deque<pair<Vertex, deque<int> > > sets;
00175 int sum = 0;
00176 int weight = 0;
00177 for (deque<pair<int, int> >::iterator i = procs.begin(); i != procs.end(); i++) {
00178 if (weight == 0)
00179 sets.push_back(make_pair(r, deque<int>()));
00180 sets.back().second.push_back(i->first);
00181 weight += i->second;
00182 if (weight >= sum) {
00183 sum += weight;
00184 weight = 0;
00185 }
00186 }
00187
00188 while (!sets.empty()) {
00189
00190 Vertex s = sets.front().first;
00191 deque<int>& procs = sets.front().second;
00192 int target = procs.front();
00193 procs.pop_front();
00194 Vertex t = add_vertex(g);
00195 put(vertex_index, g, t, target);
00196 add_edge(s, t, g);
00197 if (rank == target) {
00198 u = s;
00199 v = t;
00200 }
00201
00202 int sum = 0;
00203 int weight = 0;
00204 for (deque<int>::iterator i = procs.begin(); i != procs.end(); i++) {
00205 if (weight == 0)
00206 sets.push_back(make_pair(t, deque<int>()));
00207 int rank = *i;
00208 sets.back().second.push_back(rank);
00209 weight += counts[rank];
00210 if (weight >= sum) {
00211 sum += weight;
00212 weight = 0;
00213 }
00214 }
00215 sets.pop_front();
00216 }
00217 }
00218 };
00219
00220 }
00221 }
00222
00223 #endif