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 <sstream> 00022 00023 #include <pelib/Taskgraph.hpp> 00024 #include <pelib/DeadlineCalculator.hpp> 00025 #include <pelib/ParseException.hpp> 00026 #include <pelib/CastException.hpp> 00027 #include <pelib/PelibException.hpp> 00028 #include <pelib/DummyCore.hpp> 00029 00030 #include <pelib/Scalar.hpp> 00031 #include <pelib/Vector.hpp> 00032 #include <pelib/Matrix.hpp> 00033 00034 #ifdef debug 00035 #undef debug 00036 #endif 00037 00038 #if 01 00039 #define debug(var) cout << "[" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "] " << #var << " = \"" << var << "\"" << endl; 00040 #else 00041 #define debug(var) 00042 #endif 00043 00044 using namespace std; 00045 00046 namespace pelib 00047 { 00048 Taskgraph::Taskgraph() 00049 { 00050 } 00051 00052 Taskgraph::Taskgraph(const set<Task> &tasks, const set<Link> &links) 00053 { 00054 // Check if all tasks have a unique string ID 00055 set<string> task_ids; 00056 for(set<Task>::const_iterator iter = tasks.begin(); iter != tasks.end(); iter++) 00057 { 00058 task_ids.insert(iter->getName()); 00059 } 00060 00061 if(task_ids.size() != tasks.size()) 00062 { 00063 // This should never happen as tasks are indexed with their id 00064 throw ParseException("The tasks added do not have a unique taskId."); 00065 } 00066 00067 this->tasks = tasks; 00068 this->setLinks(links); 00069 } 00070 00071 Taskgraph::~Taskgraph() 00072 { 00073 // Do nothing 00074 } 00075 00076 void 00077 Taskgraph::setLinks(const set<Link> &links) 00078 { 00079 // Add all links so their endpoints point to tasks in the local collection 00080 this->links.clear(); 00081 for(set<Link>::const_iterator i = links.begin(); i != links.end(); i++) 00082 { 00083 const Task &producer = *this->tasks.find(*i->getProducer()); 00084 const Task &consumer = *this->tasks.find(*i->getConsumer()); 00085 00086 Link link(producer, consumer, i->getProducerName(), i->getConsumerName(), i->getDataType(), i->getProducerRate(), i->getConsumerRate()); 00087 this->links.insert(link); 00088 } 00089 00090 // Update the tasks' producer and consumer links 00091 for(set<Task>::iterator i = this->tasks.begin(); i != this->tasks.end(); i++) 00092 { 00093 Task &t = (Task&)*i; 00094 00095 // Keep a copy of the link lists 00096 set<const Link*> producers = t.getProducers(); 00097 set<const Link*> consumers = t.getConsumers(); 00098 00099 // Clear the link lists 00100 t.getProducers().clear(); 00101 t.getConsumers().clear(); 00102 00103 // Reconstruct all links so they point to local tasks 00104 for(set<const Link*>::iterator j = producers.begin(); j != producers.end(); j++) 00105 { 00106 Task *producer = (*j)->getProducer(); 00107 Task *consumer = (*j)->getConsumer(); 00108 Link newLink(*this->tasks.find(*producer), *this->tasks.find(*consumer), (*j)->getProducerName(), (*j)->getConsumerName(), (*j)->getDataType(), (*j)->getProducerRate(), (*j)->getConsumerRate()); 00109 const Link &link = *this->links.find(newLink); 00110 t.getProducers().insert(&link); 00111 } 00112 00113 // Reconstruct all links so they point to local tasks 00114 for(set<const Link*>::iterator j = consumers.begin(); j != consumers.end(); j++) 00115 { 00116 Task *producer = (*j)->getProducer(); 00117 Task *consumer = (*j)->getConsumer(); 00118 Link newLink(*this->tasks.find(*producer), *this->tasks.find(*consumer), (*j)->getProducerName(), (*j)->getConsumerName(), (*j)->getDataType(), (*j)->getProducerRate(), (*j)->getConsumerRate()); 00119 const Link &link = *this->links.find(newLink); 00120 t.getConsumers().insert(&link); 00121 } 00122 } 00123 } 00124 00125 Taskgraph::Taskgraph(const Taskgraph *graph) 00126 { 00127 this->name = graph->getName(); 00128 this->deadlineCalculator = graph->getDeadlineCalculator(); 00129 this->tasks = graph->getTasks(); 00130 this->setLinks(graph->getLinks()); 00131 } 00132 00133 Taskgraph::Taskgraph(const Taskgraph &graph) 00134 { 00135 this->name = graph.getName(); 00136 this->deadlineCalculator = graph.getDeadlineCalculator(); 00137 this->tasks = graph.getTasks(); 00138 this->setLinks(graph.getLinks()); 00139 } 00140 00141 Taskgraph::Taskgraph(const Algebra &algebra) 00142 { 00143 this->name = "Converted from AMPL"; 00144 const Scalar<float> *M = algebra.find<Scalar<float> >("M"); 00145 const Scalar<float> *n = algebra.find<Scalar<float> >("n"); 00146 const Vector<int, float> *tau = algebra.find<Vector<int, float> >("Tau"); 00147 const Vector<int, float> *streaming_task = algebra.find<Vector<int, float> >("stream"); 00148 const Vector<int, float> *Wi = algebra.find<Vector<int, float> >("Wi"); 00149 const Matrix<int, int, float> *e = algebra.find<Matrix<int, int, float> >("e"); 00150 const Matrix<int, int, float> *c = algebra.find<Matrix<int, int, float> >("c"); 00151 const Vector<int, string> *task_name = algebra.find<Vector<int, string> >("name"); 00152 00153 if(M == NULL || n == NULL || tau == NULL || Wi == NULL || e == NULL || task_name == NULL) 00154 { 00155 //throw CastException("Missing parameter. Need float scalar M, integer scalar n, integer vectors tau and Wi (of size n), and float matrix e of n lines."); 00156 throw PelibException("Missing parameter. Need float scalar M, integer scalar n, integer vectors tau and Wi (of size n), float matrix e of n lines and vector name for tasks' names."); 00157 } 00158 else 00159 { 00160 stringstream ss; 00161 ss << M->getValue(); 00162 this->deadlineCalculator = ss.str(); 00163 } 00164 00165 for(map<int, float>::const_iterator i = tau->getValues().begin(); i != tau->getValues().end(); i++) 00166 { 00167 float id = i->first; 00168 float work = i->second; 00169 bool streaming = true; 00170 if(streaming_task != NULL) 00171 { 00172 streaming = streaming_task->getValues().find((int)id)->second; 00173 } 00174 float max_wi = Wi->getValues().find((int)id)->second; 00175 00176 stringstream ss; 00177 for(map<int, float>::const_iterator j = e->getValues().find((int)id)->second.begin(); j != e->getValues().find((int)id)->second.end(); j++) 00178 { 00179 ss << j->second << " "; 00180 } 00181 00182 /* 00183 stringstream estr; 00184 estr << "task_" << id; 00185 Task t(estr.str()); 00186 */ 00187 if(task_name->getValues().find(id) == task_name->getValues().end()) 00188 { 00189 throw PelibException("Missing task name in Algebra record when building a Taskgraph instance"); 00190 } 00191 00192 Task t(task_name->getValues().find(id)->second, streaming); 00193 t.setWorkload(work); 00194 t.setMaxWidth(max_wi); 00195 t.setEfficiencyString(ss.str()); 00196 00197 this->tasks.insert(t); 00198 } 00199 00200 if(c != NULL) 00201 { 00202 for(map<int, map<int, float> >::const_iterator i = c->getValues().begin(); i != c->getValues().end(); i++) 00203 { 00204 for(map<int, float>::const_iterator j = i->second.begin(); j != i->second.end(); j++) 00205 { 00206 if(j->second > 0) 00207 { 00208 set<Task>::const_iterator from = this->getTasks().begin(), to = this->getTasks().begin(); 00209 std::advance(from, (size_t)i->first - 1); 00210 std::advance(to, (size_t)j->first - 1); 00211 this->links.insert(Link(*from, *to, from->getName(), to->getName())); 00212 } 00213 } 00214 } 00215 } 00216 } 00217 00218 Taskgraph* 00219 Taskgraph::clone() const 00220 { 00221 return new Taskgraph(this->getTasks(), this->getLinks()); 00222 } 00223 00224 Algebra 00225 Taskgraph::buildAlgebra() const 00226 { 00227 set<float> f; 00228 f.insert(1); 00229 set<const Core*, Core::LessCorePtrByCoreId> cores; 00230 cores.insert(new DummyCore(f, 1)); 00231 Platform arch(cores); 00232 00233 return buildAlgebra(Platform(cores)); 00234 } 00235 00236 Algebra 00237 Taskgraph::buildAlgebra(const Platform &arch) const 00238 { 00239 Algebra out; 00240 00241 Scalar<float> n("n", getTasks().size()); 00242 map<int, map<int, float> > map_e; 00243 map<int, map<int, float> > map_c; 00244 map<int, float> map_tau; 00245 map<int, float> map_streaming; 00246 map<int, float> map_Wi; 00247 map<int, string> map_name; 00248 00249 if(!arch.isHomogeneous()) 00250 { 00251 throw CastException("Cannot output discretive efficiency function for a heterogeneous platform."); 00252 } 00253 00254 for(set<Task>::const_iterator i = getTasks().begin(); i != getTasks().end(); i++) 00255 { 00256 map_tau.insert(pair<int, float>(std::distance(this->getTasks().begin(), i) + 1, i->getWorkload())); 00257 map_streaming.insert(pair<int, float>(std::distance(this->getTasks().begin(), i) + 1, i->isStreaming())); 00258 map_name.insert(pair<int, string>(std::distance(this->getTasks().begin(), i) + 1, i->getName())); 00259 float max_width = 0; 00260 if(i->getMaxWidth() > arch.getCores().size()) 00261 { 00262 max_width = arch.getCores().size(); 00263 } 00264 else 00265 { 00266 max_width = i->getMaxWidth(); 00267 } 00268 map_Wi.insert(pair<int, float>(std::distance(this->getTasks().begin(), i) + 1, max_width)); 00269 00270 map<int, float> task_e; 00271 for(size_t j = 1; j <= arch.getCores().size(); j++) 00272 { 00273 task_e.insert(pair<int, float>((int)j, i->getEfficiency(j))); 00274 } 00275 00276 map_e.insert(pair<int, map<int, float> >(std::distance(this->getTasks().begin(), i) + 1, task_e)); 00277 00278 map<int, float> task_c; 00279 for(set<Task>::const_iterator j = getTasks().begin(); j != getTasks().end(); j++) 00280 { 00281 set<Link>::const_iterator k; 00282 for(k = this->getLinks().begin(); k != this->getLinks().end(); k++) 00283 { 00284 if(*k->getProducer() == *i && *k->getConsumer() == *j) 00285 //if(this->this->getLinks().find(Link(*i, *j)) != this->getLinks().end()) 00286 { 00287 task_c.insert(pair<int, float>((int)std::distance(this->getTasks().begin(), j) + 1, 1)); 00288 break; 00289 } 00290 } 00291 if(k == this->getLinks().end()) 00292 { 00293 task_c.insert(pair<int, float>((int)std::distance(this->getTasks().begin(), j) + 1, 0)); 00294 } 00295 } 00296 00297 map_c.insert(pair<int, map<int, float> >(std::distance(this->getTasks().begin(), i) + 1, task_c)); 00298 } 00299 00300 Vector<int, float> tau("Tau", map_tau); 00301 Vector<int, float> streaming("streaming", map_streaming); 00302 Vector<int, float> Wi("Wi", map_Wi); 00303 Vector<int, string> name("name", map_name); 00304 Matrix<int, int, float> e("e", map_e); 00305 Matrix<int, int, float> c("c", map_c); 00306 00307 Scalar<float> M("M", getDeadline(arch), AlgebraData::higher); 00308 00309 out.insert(&n); 00310 out.insert(&name); 00311 out.insert(&tau); 00312 out.insert(&streaming); 00313 out.insert(&Wi); 00314 out.insert(&e); 00315 out.insert(&c); 00316 out.insert(&M); 00317 00318 return out; 00319 } 00320 00321 string 00322 Taskgraph::getName() const 00323 { 00324 return this->name; 00325 } 00326 00327 void 00328 Taskgraph::setName(const string name) 00329 { 00330 this->name = name; 00331 } 00332 00333 string 00334 Taskgraph::getDeadlineCalculator() const 00335 { 00336 return this->deadlineCalculator; 00337 } 00338 00339 void 00340 Taskgraph::setDeadlineCalculator(const string deadlineCalculator) 00341 { 00342 try{ 00343 DeadlineCalculator *calculator = DeadlineCalculator::getDeadlineCalculator(deadlineCalculator); 00344 delete calculator; 00345 } catch (ParseException &e) 00346 { 00347 throw e; 00348 } 00349 00350 this->deadlineCalculator = deadlineCalculator; 00351 } 00352 00353 double 00354 Taskgraph::getDeadline(const Platform &arch) const 00355 { 00356 //cerr << "[" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "] getTasks().size() = " << getTasks().size() << endl; 00357 DeadlineCalculator *calculator = DeadlineCalculator::getDeadlineCalculator(this->getDeadlineCalculator()); 00358 double time = calculator->calculate(*this, arch); 00359 delete calculator; 00360 00361 return time; 00362 } 00363 00364 const set<Task>& 00365 Taskgraph::getTasks() const 00366 { 00367 return tasks; 00368 } 00369 00370 set<Task>& 00371 Taskgraph::getTasks() 00372 { 00373 return tasks; 00374 } 00375 00376 const Task& 00377 Taskgraph::findTask(const string &taskId) const 00378 { 00379 for(set<Task>::const_iterator iter = this->tasks.begin(); iter != this->tasks.end(); iter++) 00380 { 00381 if(iter->getName().compare(taskId) == 0) 00382 { 00383 return *iter; 00384 } 00385 } 00386 00387 throw ParseException("No task \"" + taskId + "\" exists in this taskgraph."); 00388 } 00389 00390 const set<Link>& 00391 Taskgraph::getLinks() const 00392 { 00393 return this->links; 00394 } 00395 00396 set<Link>& 00397 Taskgraph::getLinks() 00398 { 00399 return this->links; 00400 } 00401 00402 Taskgraph& 00403 Taskgraph::operator=(const Taskgraph& copy) 00404 { 00405 this->name = copy.getName(); 00406 this->deadlineCalculator = copy.getDeadlineCalculator(); 00407 this->tasks = copy.getTasks(); 00408 this->setLinks(copy.getLinks()); 00409 00410 return *this; 00411 } 00412 }