crown
1.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 #include <crown/CrownConfigTaskgraph.hpp> 00021 #include <pelib/Matrix.hpp> 00022 #include <pelib/AmplInput.hpp> 00023 #include <pelib/time.h> 00024 00025 #ifdef debug 00026 #undef debug 00027 #endif 00028 00029 #define debug(var) cout << "[" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "] " << #var << " = \"" << (var) << "\"" << endl; 00030 00031 using namespace pelib; 00032 using namespace crown; 00033 using namespace std; 00034 00035 size_t 00036 pick_size(set<size_t> &sizes, size_t avail, size_t alt) 00037 { 00038 size_t out; 00039 if(sizes.size() > 0 && *sizes.rbegin() >= floor(avail / 2)) 00040 { 00041 out = *sizes.rbegin(); 00042 sizes.erase(sizes.find(out)); 00043 } 00044 else 00045 { 00046 out = alt; 00047 } 00048 00049 return out; 00050 } 00051 00052 static 00053 map<int, map<int, float> > 00054 build_crown(size_t p, size_t wi, size_t skip, set<size_t> &sizes, const map<int, map<int, float> > matrix, map<int, map<int, float> > &tree) 00055 { 00056 map<int, map<int, float> > config = matrix; 00057 map<int, float> group; 00058 for(size_t i = 0; i < p; i++) 00059 { 00060 if(i < skip || i >= skip + wi) 00061 { 00062 group.insert(pair<int, float>(i + 1, 0)); 00063 } 00064 else 00065 { 00066 group.insert(pair<int, float>(i + 1, 1)); 00067 } 00068 } 00069 00070 // Dependencies for this group 00071 map<int, float> deps; 00072 for(size_t i = 0; i < 2 * p - 1; i++) 00073 { 00074 deps.insert(pair<int, float>(i + 1, 0)); 00075 } 00076 00077 // Browse all other groups already formed 00078 for(map<int, map<int, float> >::iterator i = config.begin(); i != config.end(); i++) 00079 { 00080 // Browse all cores 00081 int ii = std::distance(config.begin(), i) + 1; 00082 for(map<int, float>::iterator j = i->second.begin(); j != i->second.end(); j++) 00083 { 00084 int jj = std::distance(i->second.begin(), j) + 1; 00085 // If both groups have the core, then there is a dependency link 00086 if(group[jj] == j->second && j->second > 0) 00087 { 00088 deps[ii] = 1; 00089 break; 00090 } 00091 } 00092 } 00093 00094 // Add groups membership and dependencies to temporary outcome 00095 config.insert(pair<int, map<int, float> >(config.size() + 1, group)); 00096 tree.insert(pair<int, map<int, float> >(tree.size() + 1, deps)); 00097 00098 // Recurse, if necessary 00099 if(wi > 1) 00100 { 00101 size_t size_left = pick_size(sizes, wi, floor((float)wi / 2)); 00102 if(sizes.find(wi - size_left) != sizes.end()) 00103 { 00104 sizes.erase(sizes.find(wi - size_left)); 00105 } 00106 size_t size_right = wi - size_left; 00107 config = build_crown(p, size_left, skip, sizes, config, tree); 00108 config = build_crown(p, size_right, skip + size_left, sizes, config, tree); 00109 } 00110 00111 return config; 00112 } 00113 00114 string 00115 CrownConfigTaskgraph::getShortDescription() const 00116 { 00117 return string("tg"); 00118 } 00119 00120 Algebra 00121 CrownConfigTaskgraph::configure(const Taskgraph &tg, const Platform &pt, const Algebra ¶m, map<const string, double> &stats) const 00122 { 00123 // Compute a binary crown and place it in class' Algebra container 00124 size_t p = pt.getCores().size(); 00125 struct timespec start, stop, total_time; 00126 00127 // Cellects the width that yields the best ratio efficiency / parallel time for each task 00128 set<size_t> best_group_sizes; 00129 clock_gettime(CLOCK_MONOTONIC, &start); 00130 for(set<Task>::const_iterator i = tg.getTasks().begin(); i != tg.getTasks().end(); i++) 00131 { 00132 debug(i->getName()); 00133 size_t best_width = 1; 00134 float best_ratio = 0; 00135 for(size_t j = 0; j < p && j < i->getMaxWidth(); j++) 00136 { 00137 debug(j + 1); 00138 debug(i->runtime(j + 1)); 00139 debug(i->getEfficiency(j + 1)); 00140 float task_time = i->runtime(j + 1, 1); 00141 float quality = i->getEfficiency(j + 1) / task_time; 00142 debug(quality); 00143 if(quality > best_ratio) 00144 { 00145 best_ratio = quality; 00146 best_width = j + 1; 00147 debug(best_width); 00148 } 00149 } 00150 if(best_width < p) 00151 { 00152 debug(best_width); 00153 best_group_sizes.insert(best_width); 00154 } 00155 } 00156 00157 map<int, map<int, float> > tree; 00158 map<int, map<int, float> > config = build_crown(p, p, 0, best_group_sizes, map<int, map<int, float> >(), tree); 00159 clock_gettime(CLOCK_MONOTONIC, &stop); 00160 pelib_timespec_subtract(&total_time, &stop, &start); 00161 00162 stats.insert(pair<const string, double>("time_config", (float)(total_time.tv_sec * pelib_nsec_in_sec + total_time.tv_nsec) / (float)pelib_nsec_in_sec)); 00163 Algebra conf; 00164 conf.insert(new Matrix<int, int, float>(CrownConfig::crownConfigGroups, config)); 00165 conf.insert(new Matrix<int, int, float>(CrownConfig::crownConfigTree, tree)); 00166 00167 return conf; 00168 } 00169 00170 CrownConfigTaskgraph::~CrownConfigTaskgraph() 00171 { 00172 // Do nothing 00173 } 00174 00175 CrownConfig* 00176 CrownConfigTaskgraph::clone() const 00177 { 00178 return new CrownConfigTaskgraph(*this); 00179 } 00180 00181 float 00182 CrownConfigTaskgraph::complexity(const Algebra &problem) const 00183 { 00184 return 0; 00185 } 00186 00187 float 00188 CrownConfigTaskgraph::complexity(const Taskgraph&, const Platform&, const Algebra&) const 00189 { 00190 return 0; 00191 } 00192