pelib  2.0.0
src/Taskgraph.cpp
Go to the documentation of this file.
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 }