pelib
2.0.0
|
00001 /* 00002 Copyright 2015 Nicolas Melot 00003 00004 This file is part of Pelib. 00005 00006 Pelib is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 Pelib is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with Pelib. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 00021 #include <libxml++/libxml++.h> 00022 #include <exception> 00023 #include <vector> 00024 #include <sstream> 00025 #include <cstdlib> 00026 #include <string> 00027 00028 extern "C"{ 00029 #include <igraph.h> 00030 } 00031 00032 #include <pelib/Schedule.hpp> 00033 #include <pelib/XMLSchedule.hpp> 00034 00035 #include <pelib/Scalar.hpp> 00036 #include <pelib/Vector.hpp> 00037 #include <pelib/Matrix.hpp> 00038 #include <pelib/Set.hpp> 00039 #include <pelib/Task.hpp> 00040 #include <pelib/Taskgraph.hpp> 00041 00042 #include <pelib/CastException.hpp> 00043 #include <pelib/ParseException.hpp> 00044 00045 #include <pelib/AmplInput.hpp> 00046 #include <pelib/Algebra.hpp> 00047 00048 #define debug(expr) cerr << "[" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "] " << #expr << " = \"" << (expr) << "\"." << endl; 00049 00050 using namespace pelib; 00051 using namespace std; 00052 using namespace xmlpp; 00053 00054 XMLSchedule::~XMLSchedule() 00055 { 00056 // Do nothing 00057 } 00058 00059 void 00060 XMLSchedule::dump(ostream& os, const Schedule &data, const Taskgraph &tg, const Platform &pt) const 00061 { 00062 dump(os, &data, &tg, &pt); 00063 } 00064 00065 void 00066 XMLSchedule::dump(ostream& os, const Schedule *sched, const Taskgraph *tg, const Platform *pt) const 00067 { 00068 Schedule::table schedule = sched->getSchedule(); 00069 //float target_makespan = sched->getMakespan(); 00070 set<Task> &tasks = (set<Task>&)tg->getTasks(); 00071 set<string> task_ids; 00072 00073 for(Schedule::table::const_iterator i = schedule.begin(); i != schedule.end(); i++) 00074 { 00075 for(Schedule::sequence::const_iterator j = i->second.begin(); j != i->second.end(); j++) 00076 { 00077 task_ids.insert(j->second.first->getName()); 00078 } 00079 } 00080 00081 os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl 00082 << "<schedule name=\"" << sched->getName() << "\" appname=\"" << sched->getAppName() << "\"" 00083 //<< "makespan=\"" << target_makespan << "\" " 00084 << ">" << endl; 00085 00086 // Finds and set the precision required for this schedule 00087 std::streamsize old_precision = os.precision(); 00088 std::streamsize max_work_precision = 0; 00089 std::streamsize max_freq_precision = 0; 00090 std::streamsize max_start_precision = 0; 00091 for(Schedule::table::const_iterator i = schedule.begin(); i != schedule.end(); i++) 00092 { 00093 float last_start = 0; 00094 float last_time = 0; 00095 for(Schedule::sequence::const_iterator j = i->second.begin(); j != i->second.end(); j++) 00096 { 00097 Task t = *j->second.first; 00098 if(t.getStartTime() > 0) 00099 { 00100 float delta = t.getStartTime() - last_start; 00101 delta = delta - floor(delta); 00102 std::streamsize precision = (std::streamsize)(ceil(-log10(delta)) + 2); 00103 if(precision > max_start_precision) 00104 { 00105 max_start_precision = precision; 00106 } 00107 last_start = t.getStartTime(); 00108 00109 delta = abs(t.getStartTime() - (last_start + last_time)); 00110 delta = delta - floor(delta); 00111 precision = (std::streamsize)(ceil(-log10(delta)) + 1); 00112 if(precision > max_start_precision) 00113 { 00114 max_start_precision = precision; 00115 } 00116 const Task &tgt = *tg->getTasks().find(t); 00117 last_time = tgt.runtime(t.getWidth(), t.getFrequency()); 00118 00119 double work = t.getWorkload() - floor(t.getWorkload()); 00120 precision = (std::streamsize)(ceil(-log10(work)) + 1); 00121 if(precision > max_work_precision) 00122 { 00123 max_work_precision = precision; 00124 } 00125 00126 double freq = t.getFrequency() - floor(t.getFrequency()); 00127 precision = (std::streamsize)(ceil(-log10(freq)) + 1); 00128 if(precision > max_freq_precision) 00129 { 00130 max_freq_precision = precision; 00131 } 00132 00133 /* 00134 os << "<!-- core : " << i->first << " -->" << endl; 00135 os << "<!-- task : " << t.getName() << " -->" << endl; 00136 os << "<!-- start_time = " << t.getStartTime() << " -->" << endl; 00137 os << "<!-- last_start = " << last_start << " -->" << endl; 00138 */ 00139 00140 // update last time 00141 } 00142 } 00143 } 00144 00145 for(Schedule::table::const_iterator i = schedule.begin(); i != schedule.end(); i++) 00146 { 00147 int p = i->first; 00148 os << " <core coreid=\"" << p << "\">" << endl; 00149 Schedule::sequence core_schedule = i->second; 00150 int order = 0; 00151 double start = 0; 00152 00153 for(Schedule::sequence::const_iterator j = i->second.begin(); j != i->second.end(); j++, order++) 00154 { 00155 Task t = *j->second.first; 00156 string taskid = t.getName(); 00157 size_t task_index = std::distance(sched->getTasks().begin(), sched->getTasks().find(t)); 00158 00159 os << " <task name=\"" << taskid << "\" "; 00160 os << setprecision(max_start_precision); 00161 os << "start=\"" << std::fixed << (t.getStartTime() > 0 ? t.getStartTime() : start) << "\" "; 00162 os << setprecision(old_precision); 00163 os << "frequency=\"" << (float)t.getFrequency() << "\" "; 00164 os << "width=\"" << t.getWidth() << "\" "; 00165 os << "workload=\"" << t.getWorkload() << "\""; 00166 os << "/>" << endl; 00167 00168 set<Task>::iterator iter = tasks.begin(); 00169 std::advance(iter, task_index); 00170 t.setMaxWidth(iter->getMaxWidth()); 00171 t.setEfficiencyString(string(iter->getEfficiencyString())); 00172 string eff = string(iter->getEfficiencyString()); 00173 start += t.runtime(t.getWidth(), t.getFrequency()); 00174 } 00175 os << " </core>" << endl; 00176 } 00177 os << setprecision(old_precision); 00178 00179 os << "</schedule>" << endl; 00180 } 00181 00182 Schedule* 00183 XMLSchedule::parse(istream &is) const 00184 { 00185 DomParser* theSchedule = new DomParser(); 00186 //theSchedule->set_throw_messages(false); 00187 //igraph_set_error_handler(igraph_error_handler_t* new_handler); 00188 //Taskgraph tg = taskgraph; 00189 00190 try 00191 { 00192 theSchedule->parse_stream(is); 00193 } catch(xmlpp::parse_error &e) 00194 { 00195 throw ParseException(std::string("xmlpp::parse_error")); 00196 } 00197 00198 // Just like taskgraph conversion 00199 // this involves turning the data structure 00200 // inside out, and to convert from 00201 // the taskids to id 1..n, in a 00202 // deterministic fashion. 00203 // The latter is slightly more complex 00204 // than taskgraph version 00205 // since the tasks may appear more than one 00206 // in the schedule. 00207 00208 Element *root = theSchedule->get_document()->get_root_node(); 00209 xmlpp::Node::NodeList processors = root->get_children(); 00210 00211 try 00212 { 00213 std::string name = root->get_attribute_value("name"); 00214 std::string aut_name = root->get_attribute_value("appname"); 00215 set<Task> tasks; 00216 00217 Schedule::table schedule; 00218 for(xmlpp::Node::NodeList::iterator iter = processors.begin(); iter != processors.end(); ++iter) //for each core 00219 { 00220 if((*iter)->get_name().compare("core")) //skip indentation characters et cetera 00221 { 00222 continue; 00223 } 00224 00225 int core_id = atoi(dynamic_cast<xmlpp::Element*>(*iter)->get_attribute_value("coreid").c_str()); 00226 Schedule::sequence core_schedule_map; 00227 //cout << "Core " << core_id << endl; 00228 00229 std::list<xmlpp::Node*> itasks = (*iter)->get_children(); 00230 for(std::list<xmlpp::Node*>::iterator taskiter = itasks.begin(); taskiter != itasks.end(); ++taskiter) 00231 { 00232 if((*taskiter)->get_name().compare("task") != 0) //skip indentation characters et cetera 00233 { 00234 //cout << "Skipping " << (*taskiter)->get_name() << endl; 00235 continue; 00236 } 00237 00238 Element *igraph_task = dynamic_cast<Element*>(*taskiter); 00239 //cout << "Task " << igraph_task->get_attribute_value("name") << endl; 00240 00241 //Task &task = (Task&) tg.findTask(igraph_task->get_attribute_value("taskid")); 00242 Task task(igraph_task->get_attribute_value("name")); 00243 //cout << "Counter = " << task_id << ", tg_task.getName() = " << tg_task.getName() << ", tg_task.getTaskId() = \"" << tg_task.getTaskId() << "." << endl; 00244 00245 //Task task(tg_task.getName(), tg_task.getTaskId()); 00246 //Task& task_tg = (Task&)*tg.getTasks().find(task); 00247 00248 task.setFrequency(atof(igraph_task->get_attribute_value("frequency").c_str())); 00249 task.setWidth(atof(igraph_task->get_attribute_value("width").c_str())); 00250 //task.setWorkload(atof(igraph_task->get_attribute_value("workload").c_str())); 00251 task.setStartTime(atof(igraph_task->get_attribute_value("start").c_str())); 00252 tasks.insert(task); 00253 const Task &t = *tasks.find(task); 00254 00255 core_schedule_map.insert(std::pair<float, Schedule::work>(task.getStartTime(), pair<const Task*, double>(&t, atof(igraph_task->get_attribute_value("workload").c_str())))); 00256 } 00257 00258 schedule.insert(std::pair<int, Schedule::sequence>(core_id, core_schedule_map)); 00259 } 00260 00261 Schedule *sched = new Schedule(name, aut_name, schedule); 00262 00263 /* 00264 for(set<const Task*>::const_iterator j = sched->getTasks(1).begin(); j != sched->getTasks(1).end(); j++) 00265 { 00266 const Task *jj = *j; 00267 Task jjj = *jj; 00268 } 00269 */ 00270 00271 return sched; 00272 } 00273 catch(std::invalid_argument &e) 00274 { 00275 throw ParseException(std::string("std::invalid_argument")); 00276 } 00277 } 00278 00279 XMLSchedule* 00280 XMLSchedule::clone() const 00281 { 00282 return new XMLSchedule(); 00283 }