00001 #ifndef HIERARCHICAL_MODEL_HPP_
00002 #define HIERARCHICAL_MODEL_HPP_
00003
00004 #include <boost/mpi.hpp>
00005 #include <boost/graph/graphviz.hpp>
00006 #include <boost/graph/adjacency_list.hpp>
00007 #include <boost/serialization/deque.hpp>
00008 #include <boost/archive/text_oarchive.hpp>
00009 #include <boost/archive/text_iarchive.hpp>
00010 #include <deque>
00011 #include <utility>
00012 #include "models/cpm.h"
00013
00014 namespace CPM {
00016 namespace hierarchy {
00017 using namespace std;
00018 using namespace boost;
00019
00020 struct vertex_type_t { typedef vertex_property_tag kind; };
00021 struct vertex_model_data_t { typedef vertex_property_tag kind; };
00022 typedef property<vertex_type_t, int, property<vertex_model_data_t, string > > vertex_properties_t;
00023 typedef property < vertex_name_t, string > vertex_p;
00024 typedef adjacency_list < vecS, vecS, directedS, vertex_properties_t > Graph;
00025 typedef graph_traits<Graph>::vertex_descriptor Vertex;
00026 typedef graph_traits<Graph>::edge_descriptor Edge;
00027 typedef graph_traits<Graph>::vertex_iterator Vertex_iterator;
00028 typedef graph_traits<Graph>::adjacency_iterator Adjacency_iterator;
00029
00030 class label_writer {
00031 public:
00032 label_writer(Graph _g) : g(_g) {}
00033 void operator()(ostream& out, const Vertex& v) const {
00034 out << "[type=" << get(vertex_type_t(), g, v ) << ", model_data=\"" << get(vertex_model_data_t(), g, v) << "\"]" ;
00035 }
00036 private:
00037 Graph g;
00038 };
00039
00040 map<pair <int , int> , Vertex > pair2vertex;
00041 map<string, vector<int> > hostname2procs;
00042 map<int, Vertex> rank2vertex;
00043 };
00044 };
00045
00046 using namespace CPM::hierarchy;
00047
00048 bool get_common_parent(Graph graph, Vertex v1, Vertex v2, Vertex& v3) {
00049 Adjacency_iterator ai1, ai_end1, ai2, ai_end2;
00050 tie(ai1, ai_end1) = adjacent_vertices(v1, graph);
00051 tie(ai2, ai_end2) = adjacent_vertices(v2, graph);
00052 bool found = false;
00053
00054 while ((ai1 != ai_end1) && (ai2 != ai_end2)) {
00055
00056 if (*ai1 == *ai2) {
00057 found = true;
00058 v3 = *ai1;
00059 break;
00060 }
00061 else {
00062 tie(ai1, ai_end1) = adjacent_vertices(*ai1, graph);
00063 tie(ai2, ai_end2) = adjacent_vertices(*ai2, graph);
00064 }
00065 }
00066 return found;
00067 }
00068
00079 template <class p2p_model> class H_Model {
00080 private:
00081 Graph graph;
00082
00083 public:
00088 void read_hierarchy_file(istream &is){
00089 dynamic_properties dp;
00090 property_map<Graph, vertex_type_t>::type type =
00091 get(vertex_type_t(), graph);
00092 dp.property("type", type);
00093 property_map<Graph, vertex_model_data_t>::type model_data =
00094 get(vertex_model_data_t(), graph);
00095 dp.property("model_data",model_data);
00096 read_graphviz( is, graph, dp, "type");
00097 }
00098
00099 void write_hierarchy_file(ostream &os){}
00100
00101 void read_model_file(istream &is){}
00102
00103
00104 void write_model_file(ostream &os) {
00105 boost::mpi::communicator world;
00106
00107 os << "#Number of nodes: " << world.size() << "\n";
00108 int i, index;
00109 map<pair<int,int>, pair<int,int> > pair2pair;
00110 p2p_model m;
00111 m.write_header(os);
00112
00113 for(i = 0, index = 0; i < world.size() - 1; i++) {
00114 int j;
00115 for(j = i + 1; j < world.size(); j++, index++) {
00116 Vertex v;
00117 if (! get_common_parent(graph, rank2vertex[i], rank2vertex[j], v)) {
00118 cerr << "could not find common parent to: " << i << " and " << j ;
00119 exit(-1);
00120 }
00121
00122 string model_data = get(vertex_model_data_t(), graph, v);
00123 istringstream is(model_data);
00124 boost::archive::text_iarchive ia(is);
00125 ia >> m;
00126 m.write_elem(i, j, os);
00127 }
00128 }
00129 m.write_footer(os);
00130 }
00131
00132
00133 Graph& getGraph(){return graph;}
00134 };
00135
00136
00137 template <class p2p_model> void H_Model_estimate(MPI_Comm comm, MPIB_msgset msgset, MPIB_precision precision, int parallel, H_Model<p2p_model>* model) {
00138 deque<pair<int,int> > proc_pairs;
00139 generate_benchmark_pairs(model, comm, proc_pairs);
00140 mpi::communicator world;
00141 int rank = world.rank();
00142
00143 for (deque<pair<int,int> >::iterator it = proc_pairs.begin(); it != proc_pairs.end(); it++) {
00144 mpi::request req;
00145 p2p_model m;
00146
00147 if ((rank == it->first) || (rank == it->second)) {
00148 m.estimate(comm, msgset, precision, it->first, it->second);
00149 }
00150
00151 if (rank == it->first)
00152 req = world.isend(0, 0 , m);
00153
00154 if (rank == 0) {
00155 world.recv(it->first, 0, m);
00156 ostringstream os;
00157 boost::archive::text_oarchive oa(os);
00158 oa << m;
00159
00160
00161 Vertex v = pair2vertex[make_pair(it->first, it->second)];
00162 put(vertex_model_data_t(), model->getGraph(), v, os.str());
00163 }
00164 if (rank == it->first)
00165 req.wait();
00166 }
00167 }
00168
00173 void set_parent_model_data(Graph& graph , Vertex& v1, Vertex& v2, deque<pair<int, int> >& proc_pairs) {
00174
00175 Vertex v3;
00176 bool found = get_common_parent(graph, v1, v2, v3);
00177 bool empty = false;
00178 if (found) {
00179 empty = (get(vertex_model_data_t(), graph, v3) == "");
00180 }
00181 else {
00182 fprintf(stderr, "Could not find common parent of vertices");
00183 exit(-1);
00184 }
00185
00186 if (empty) {
00187 string hostname1 = get(vertex_model_data_t(), graph, v1);
00188 string hostname2 = get(vertex_model_data_t(), graph, v2);
00189
00190
00191
00192 if (!hostname1.compare(hostname2)) {
00193 if (hostname2procs[hostname1].size() >=2 ) {
00194 pair<int,int> proc_pair;
00195 proc_pair.first = hostname2procs[hostname1][0];
00196 proc_pair.second = hostname2procs[hostname1][1];
00197 proc_pairs.push_back(proc_pair);
00198 pair2vertex[proc_pair] = v3;
00199 }
00200 }
00201
00202
00203 else {
00204 if ((!hostname2procs[hostname1].empty()) && (!hostname2procs[hostname2].empty())) {
00205 pair<int,int> proc_pair;
00206 proc_pair.first = hostname2procs[hostname1][0];
00207 proc_pair.second = hostname2procs[hostname2][0];
00208 proc_pairs.push_back(proc_pair);
00209 pair2vertex[proc_pair] = v3;
00210 }
00211 }
00212
00213 put(vertex_model_data_t(), graph, v3, "X") ;
00214 }
00215 }
00216
00217 template <class p2p_model>
00218 void generate_benchmark_pairs(H_Model<p2p_model>* model, MPI_Comm comm, deque<pair<int, int> >& proc_pairs) {
00219 int rank, size;
00220 deque<Vertex> bottom_vertices;
00221 mpi::communicator world;
00222 rank = world.rank();
00223 size = world.size();
00224 Graph& graph = model->getGraph();
00225 string proc_name = boost::mpi::environment::processor_name();
00226 if (rank != 0) {
00227 world.send(0, rank, proc_name);
00228 }
00229
00230 else {
00231
00232
00233 Vertex_iterator ai, ai_end;
00234 Adjacency_iterator ai2, ai_end2;
00235 tie(ai,ai_end) = vertices(graph);
00236
00237 while (ai != ai_end) {
00238 int vertex_type = get(vertex_type_t(), graph, *ai);
00239 if (vertex_type == 0) {
00240 bottom_vertices.push_back(*ai);
00241 }
00242 ai++;
00243 }
00244 mpi::status status;
00245 string all_names[size];
00246
00247 all_names[0] = proc_name;
00248 for (int i=1; i<size; i++) {
00249 string tmp;
00250 world.recv(i, i, tmp);
00251 all_names[i] = tmp;
00252 }
00253
00254
00255 for (int i=0; i<size; i++) {
00256 for (std::deque<Vertex>::iterator it = bottom_vertices.begin(); it != bottom_vertices.end(); it++) {
00257 string hostname = get(vertex_model_data_t(), graph, *it);
00258 if (!all_names[i].compare(hostname))
00259 rank2vertex[i] = *it;
00260 }
00261 }
00262
00263
00264 for (int i=0; i<size; i++) {
00265 hostname2procs[all_names[i]].push_back(i);
00266 }
00267
00268 std::deque<Vertex>::iterator it1, it2, it3;
00269 it3 = bottom_vertices.end();
00270
00271 for (it1 = bottom_vertices.begin(); it1 != it3; it1++) {
00272 for (it2 = it1; it2 != it3; it2++) {
00273 set_parent_model_data(graph , *it1, *it2, proc_pairs);
00274 }
00275 }
00276 }
00277 boost::mpi::broadcast(world, proc_pairs, 0);
00278 }
00279
00280
00281 #endif