00001 #include <algorithm>
00002 #include "charm++.h"
00003
00004 #ifndef TREE_STRATEGY_3D_TORUS_MIN_HOPS
00005 #define TREE_STRATEGY_3D_TORUS_MIN_HOPS
00006
00007 #if XE6_TOPOLOGY
00008 #include <bitset>
00009 #endif
00010
00011 namespace topo {
00012
00025 template <typename Iterator,typename ValueType = typename std::iterator_traits<Iterator>::value_type>
00026 class SpanningTreeStrategy_3dTorus_minHops: public SpanningTreeStrategy<Iterator>
00027 {
00028 public:
00029 virtual SpanningTreeVertex* buildNextGen(const Iterator firstVtx, const Iterator beyondLastVtx, const int maxBranches=2) = 0;
00030 };
00031
00032
00033
00036 template <typename Iterator>
00037 class SpanningTreeStrategy_3dTorus_minHops<Iterator,SpanningTreeVertex>: public SpanningTreeStrategy<Iterator>
00038 {
00039 public:
00040 virtual SpanningTreeVertex* buildNextGen(const Iterator firstVtx, const Iterator beyondLastVtx, const int maxBranches=2);
00041 };
00042
00043
00044
00050 template <typename Iterator>
00051 class SpanningTreeStrategy_3dTorus_minHops<Iterator,vtxType>: public SpanningTreeStrategy<Iterator>
00052 {
00053 public:
00054 virtual SpanningTreeVertex* buildNextGen(const Iterator firstVtx, const Iterator beyondLastVtx, const int maxBranches=2)
00055 {
00057 std::vector<SpanningTreeVertex> tree;
00058 for (Iterator itr = firstVtx; itr != beyondLastVtx; itr++)
00059 tree.push_back( SpanningTreeVertex(*itr) );
00061 SpanningTreeStrategy_3dTorus_minHops< std::vector<SpanningTreeVertex>::iterator > theRealBuilder;
00062 SpanningTreeVertex *result = theRealBuilder.buildNextGen(tree.begin(),tree.end(),maxBranches);
00064 int indx=0;
00065 for (Iterator itr = firstVtx; itr != beyondLastVtx; itr++)
00066 {
00067 *itr = tree[indx].id;
00068 indx++;
00069 }
00071 return result;
00072 }
00073 };
00074
00075
00076
00077 namespace impl {
00082 template <typename Iterator>
00083 class TreeBoundingBoxOn3dTorus
00084 {
00085 public:
00087 void partition(const Iterator parent, const Iterator start, const Iterator end, const int numPartitions);
00088 #if XE6_TOPOLOGY
00089 void translateCoordinates(const Iterator start, const Iterator end, int nDims);
00090 #endif
00091
00092 protected:
00094 void bisect(const Iterator parent, const Iterator start, const Iterator end, const int numPartitions);
00096 void trisect(const Iterator parent, const Iterator start, const Iterator end, const int numPartitions);
00098 int findMaxSpreadDimension(const Iterator start, const Iterator end);
00100 class lessThan
00101 {
00102 public:
00103 lessThan(const int _dim): dim(_dim) {}
00104 inline bool operator() (const SpanningTreeVertex &a, const SpanningTreeVertex &b)
00105 {
00106
00107
00108
00109 if (a.X[dim] < b.X[dim]) return true;
00110 else if (a.X[dim] == b.X[dim]) {
00111 switch(dim) {
00112 case 0: other[0] = 1; other[1] = 2; break;
00113 case 1: other[0] = 0; other[1] = 2; break;
00114 case 2: other[0] = 0; other[1] = 1; break;
00115 default: CkAbort("NOT SUPPORTED\n");
00116 }
00117 if (a.X[other[0]] < b.X[other[0]]) return true;
00118 else if (a.X[other[0]] == b.X[other[0]]) {
00119 return (a.X[other[1]] < b.X[other[1]]);
00120 } else {
00121 return false;
00122 }
00123 } else {
00124 return false;
00125 }
00126 }
00127 private:
00128 const int dim;
00129 int other[2];
00130 };
00131 };
00132 }
00133
00134 }
00135
00136
00137 #include "TopoManager.h"
00138
00139 namespace topo {
00140
00141 template <typename Iterator>
00142 SpanningTreeVertex* SpanningTreeStrategy_3dTorus_minHops<Iterator,SpanningTreeVertex>::buildNextGen(const Iterator firstVtx, const Iterator beyondLastVtx, const int maxBranches)
00143 {
00145 (*firstVtx).childIndex.clear();
00146 (*firstVtx).childIndex.reserve(maxBranches);
00147
00149 TopoManager *aTopoMgr = TopoManager::getTopoManager();
00151 for (Iterator itr = firstVtx; itr != beyondLastVtx; itr++)
00152 {
00153 (*itr).X.reserve(3);
00154 (*itr).X.assign(3,0);
00155 int coreNum;
00156 aTopoMgr->rankToCoordinates( (*itr).id, (*itr).X[0], (*itr).X[1], (*itr).X[2], coreNum );
00157 }
00159 impl::TreeBoundingBoxOn3dTorus<Iterator> treePart;
00160 #if XE6_TOPOLOGY
00161 if ((aTopoMgr->getDimNX() > MAX_TORUS_DIM_SIZE) ||
00162 (aTopoMgr->getDimNY() > MAX_TORUS_DIM_SIZE) ||
00163 (aTopoMgr->getDimNZ() > MAX_TORUS_DIM_SIZE)) {
00164 CkAbort("Torus dimension size larger than supported limit. Please increase limit");
00165 }
00166 treePart.translateCoordinates(firstVtx, beyondLastVtx, 3);
00167 #endif
00168
00170 Iterator firstDescendant = firstVtx;
00171 treePart.partition(firstVtx,++firstDescendant,beyondLastVtx,maxBranches);
00172
00174 for (int i=0, numChildren=(*firstVtx).childIndex.size(); i<numChildren; i++)
00175 {
00176 Iterator rangeStart = firstVtx;
00177 std::advance(rangeStart,(*firstVtx).childIndex[i]);
00178 Iterator rangeEnd = firstVtx;
00179 if (i+1 == numChildren)
00180 rangeEnd = beyondLastVtx;
00181 else
00182 std::advance(rangeEnd, (*firstVtx).childIndex[i+1] );
00183 Iterator closestItr = pickClosest(*firstVtx,rangeStart,rangeEnd);
00184 std::iter_swap(rangeStart,closestItr);
00185 }
00187 return (new SpanningTreeVertex(*firstVtx) );
00188 }
00189
00190
00191
00192 namespace impl {
00193
00194 template <typename Iterator>
00195 inline void TreeBoundingBoxOn3dTorus<Iterator>::partition(const Iterator parent, const Iterator start, const Iterator end, const int numPartitions)
00196 {
00198 int numVertices = std::distance(start,end);
00200 if ( (numPartitions > 1) && (numVertices > 1) )
00201 {
00202 if (numPartitions % 3 == 0)
00203 trisect(parent,start,end,numPartitions);
00204 else
00205 bisect (parent,start,end,numPartitions);
00206 }
00208 else if ( (numPartitions >= 1) && (numVertices >= 1) )
00209 {
00210 int indx = std::distance(parent,start);
00211 (*parent).childIndex.push_back(indx);
00212 }
00214 else if (numVertices == 0)
00215 {
00216 }
00218 else if ( (numVertices >= 0) && (numPartitions == 0) )
00219 CkAbort("\nThere are vertices left but no remaining partitions to put them in.");
00221 else
00222 CkAbort("\nPartitioning fell through to the default case (which it never should). Check the logic in this routine.");
00223 }
00224
00225 #if __DEBUG_SPANNING_TREE_
00226
00227
00228 template <typename Iterator>
00229 void checkSection(const Iterator start, const Iterator end, const Iterator p1, const Iterator p2) {
00230 if ((p1 != start) && ((*p1).X == (*(p1-1)).X)) {
00231 CkAbort("checkSection: section point p1 incorrect\n");
00232 }
00233 if ((p2 != start) && ((*p2).X == (*(p2-1)).X)) {
00234 CkAbort("checkSection: section point p2 incorrect\n");
00235 }
00236 for (Iterator it = start; it != end; it++) {
00237 int d=1;
00238 for (Iterator it2 = it+1; it2 != end; it2++, d++) {
00239 if ((*it).X == (*it2).X) {
00240 if (d == 1) break;
00241 else CkAbort("ERROR PEs in same node are NOT together\n");
00242 }
00243 }
00244 }
00245 }
00246 #endif
00247
00248
00249
00250
00251 template <typename Iterator>
00252 void TreeBoundingBoxOn3dTorus<Iterator>::bisect(const Iterator parent, const Iterator start, const Iterator end, const int numPartitions)
00253 {
00255 int numVertices = std::distance(start,end);
00257 int maxSpreadDim = findMaxSpreadDimension(start,end);
00258 std::sort(start, end, lessThan(maxSpreadDim));
00259 Iterator median = start;
00260 std::advance(median,numVertices/2);
00261
00262 if ((median != start) && ((*median).X == (*(median-1)).X)) {
00263
00264
00265 #if __DEBUG_SPANNING_TREE_
00266 CkPrintf("[%d] WARNING: median at middle of physical node\n", CkMyPe());
00267 #endif
00268 while ((median != start) && ((*(median-1)).X == (*median).X)) median--;
00269 }
00270 #if __DEBUG_SPANNING_TREE_
00271 checkSection(start, end, median, median);
00272 #endif
00273 if (median == start) {
00274 partition(parent, start, end, 1);
00275 return;
00276 }
00277
00279 int numLeft = numPartitions/2;
00280 partition(parent, start, median, numLeft);
00281 partition(parent, median, end, numPartitions - numLeft);
00282 }
00283
00284
00285
00286
00287
00288 template <typename Iterator>
00289 void TreeBoundingBoxOn3dTorus<Iterator>::trisect(const Iterator parent, const Iterator start, const Iterator end, const int numPartitions)
00290 {
00292 if (numPartitions % 3 == 0)
00293 {
00295 int numVertices = std::distance(start,end);
00297 int maxSpreadDim = findMaxSpreadDimension(start,end);
00298 std::sort(start, end, lessThan(maxSpreadDim));
00299 Iterator oneThird = start;
00300 std::advance(oneThird,numVertices/3);
00301 Iterator twoThird = oneThird;
00302 std::advance(twoThird,numVertices/3);
00303
00304
00305 if ((oneThird != start) && ((*oneThird).X == (*(oneThird-1)).X)) {
00306 #if __DEBUG_SPANNING_TREE_
00307 CkPrintf("[%d] WARNING: oneThird at middle of physical node\n", CkMyPe());
00308 #endif
00309 while ((oneThird != start) && ((*(oneThird-1)).X == (*oneThird).X)) oneThird--;
00310 }
00311 if ((twoThird != start) && ((*twoThird).X == (*(twoThird-1)).X)) {
00312 #if __DEBUG_SPANNING_TREE_
00313 CkPrintf("[%d] WARNING: twoThird at middle of physical node\n", CkMyPe());
00314 #endif
00315 while ((twoThird != start) && ((*(twoThird-1)).X == (*twoThird).X)) twoThird--;
00316 }
00317 #if __DEBUG_SPANNING_TREE_
00318 checkSection(start, end, oneThird, twoThird);
00319 #endif
00320 if (oneThird == twoThird) {
00321 while ((twoThird != end) && ((*twoThird).X == (*oneThird).X)) twoThird++;
00322 if (twoThird == end) {
00323 if (oneThird == start) {
00324 partition(parent, start, end, 1);
00325 return;
00326 } else {
00327 int numLeft = numPartitions/2;
00328 partition(parent, start, oneThird, numLeft);
00329 partition(parent, oneThird, end, numPartitions - numLeft);
00330 return;
00331 }
00332 }
00333 }
00334 if (oneThird == start) {
00335 int numLeft = numPartitions/2;
00336 partition(parent, start, twoThird, numLeft);
00337 partition(parent, twoThird, end, numPartitions - numLeft);
00338 return;
00339 }
00340
00342 int numLeft = numPartitions/3;
00343 partition(parent, start, oneThird, numLeft);
00344 partition(parent, oneThird, twoThird, numLeft);
00345 partition(parent, twoThird, end, numLeft);
00346 }
00348 else
00349 partition(parent, start, end, numPartitions);
00350 }
00351
00352 template <typename Iterator>
00353 int TreeBoundingBoxOn3dTorus<Iterator>::findMaxSpreadDimension(const Iterator start, const Iterator end)
00354 {
00355 int nDims = (*start).X.size();
00356 #if XE6_TOPOLOGY
00357 std::vector<std::bitset<MAX_TORUS_DIM_SIZE> > usedCoordinates(nDims);
00358 for (Iterator itr = start; itr != end; itr++) {
00359 for (int i=0; i < nDims; i++) usedCoordinates[i].set((*itr).X[i]);
00360 }
00361 int maxSpreadDimension = 0;
00362 int maxSpread = -1;
00363 for (int i=0; i < nDims; i++) {
00364 int count = usedCoordinates[i].count();
00365 #if __DEBUG_SPANNING_TREE_
00366 if (CkMyPe() == 0) CkPrintf("Spread on dimension %d is %d\n", i, count);
00367 #endif
00368 if (count > maxSpread) {
00369 maxSpread = count;
00370 maxSpreadDimension = i;
00371 }
00372 }
00373 #if __DEBUG_SPANNING_TREE_
00374 if (CkMyPe() == 0) CkPrintf("Max spread dimension is %d\n", maxSpreadDimension);
00375 #endif
00376
00377 return maxSpreadDimension;
00378 #else
00379 std::vector<int> min, max, spread;
00380 min.reserve(nDims);
00381 max.reserve(nDims);
00382 spread.reserve(nDims);
00384 min = max = (*start).X;
00385 for (Iterator itr = start; itr != end; itr++)
00386 {
00388 for (int i=0; i<nDims; i++)
00389 {
00390 if ( (*itr).X[i] < min[i] )
00391 min[i] = (*itr).X[i];
00392 if ( (*itr).X[i] > max[i] )
00393 max[i] = (*itr).X[i];
00394 }
00395 }
00397 int maxSpread = abs(max[0] - min[0]);
00398 int maxSpreadDimension = 0;
00399 for (int i=1; i<nDims; i++)
00400 {
00401 int spread = abs(max[i] - min[i]);
00402 if (maxSpread < spread )
00403 {
00404 maxSpread = spread;
00405 maxSpreadDimension = i;
00406 }
00407 }
00408 return maxSpreadDimension;
00409 #endif
00410 }
00411
00412 #if XE6_TOPOLOGY
00413
00414 #include <limits.h>
00415
00416 inline int modulo(int k, int n) {
00417 return ((k %= n) < 0) ? k+n : k;
00418 }
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 template <typename Iterator>
00430 void TreeBoundingBoxOn3dTorus<Iterator>::translateCoordinates(const Iterator start, const Iterator end, int nDims)
00431 {
00432 std::vector<std::bitset<MAX_TORUS_DIM_SIZE> > usedCoordinates(nDims);
00433 std::vector<int> max_coord(nDims, -1);
00434 std::vector<int> min_coord(nDims, INT_MAX);
00435 std::vector<int> maxSpread(nDims);
00436 std::vector<int> gapCenter(nDims, -1);
00437 std::vector<int> dimSizes(nDims+1);
00438 TopoManager_getDims(&(dimSizes.front()));
00439 #if __DEBUG_SPANNING_TREE_
00440 if (CkMyPe() == 0)
00441 std::cout << "Dim sizes are: " << dimSizes[0] << " " << dimSizes[1] << " " << dimSizes[2] << std::endl;
00442 #endif
00443
00444 int numVertices = 0;
00445 for (Iterator itr = start; itr != end; itr++, numVertices++) {
00446 for (int i=0; i < nDims; i++) {
00447 int c = (*itr).X[i];
00448 usedCoordinates[i].set(c);
00449 if (c > max_coord[i]) max_coord[i] = c;
00450 if (c < min_coord[i]) min_coord[i] = c;
00451 }
00452 }
00453 for (int i=0; i < nDims; i++) {
00454 maxSpread[i] = max_coord[i] - min_coord[i] + 1;
00455 int sum = 0, nbUnusedCoords = 0;
00456 for (int j=0; j < dimSizes[i]; j++) {
00457 if (!usedCoordinates[i].test(j)) {
00458 #if __DEBUG_SPANNING_TREE_
00459 if (CkMyPe() == 0)
00460 std::cout << "Dimension " << i << ": coordinate " << j << " is unused" << std::endl;
00461 #endif
00462 sum += j;
00463 nbUnusedCoords++;
00464 }
00465 }
00466 if (nbUnusedCoords > 0) gapCenter[i] = sum / nbUnusedCoords;
00467 }
00468
00469 #if __DEBUG_SPANNING_TREE_
00470 if (CkMyPe() == 0) {
00471 std::cout << "Used coordinates in each dimension:" << std::endl;
00472 for (int i=0; i < nDims; i++) {
00473 std::cout << i << ": ";
00474 for (int j=0; j < dimSizes[i]; j++) if (usedCoordinates[i].test(j)) std::cout << j << " ";
00475 std::cout << ", " << usedCoordinates[i].count() << std::endl;
00476 }
00477 std::cout << "Max,min coord in each dimension:" << std::endl;
00478 for (int i=0; i < nDims; i++) std::cout << i << ": " << max_coord[i] << " " << min_coord[i] << std::endl;
00479 std::cout << "Gap center for each dimension:" << std::endl;
00480 for (int i=0; i < nDims; i++) std::cout << i << ": " << gapCenter[i] << std::endl;
00481 std::cout << "Max spread for each dimension:" << std::endl;
00482 for (int i=0; i < nDims; i++) std::cout << i << ": " << maxSpread[i] << std::endl;
00483 }
00484 #endif
00485
00486
00487 for (int i=0; i < nDims; i++) {
00488 if (maxSpread[i] == usedCoordinates[i].count()) continue;
00489
00490 #if __DEBUG_SPANNING_TREE_
00491 if (CkMyPe() == 0)
00492 std::cout << "Going to attempt to correct coordinates on dimension " << i << std::endl;
00493 #endif
00494
00495
00496 int direction = 1;
00497 if (gapCenter[i] < dimSizes[i]/2) direction = -1;
00498 #if __DEBUG_SPANNING_TREE_
00499 if (CkMyPe() == 0) std::cout << "Chose direction " << direction << std::endl;
00500 #endif
00501
00502
00503 int bestMaxSpread = maxSpread[i];
00504 int bestOffset=0;
00505 Iterator itr;
00506
00507 for (int m=0; ; m++) {
00508
00509 int max_coord = -1;
00510 int min_coord = INT_MAX;
00511 for (itr = start; itr != end; itr++) {
00512 int &x = (*itr).X[i];
00513 x += direction;
00514 if (x >= dimSizes[i]) x = 0;
00515 else if (x < 0) x = dimSizes[i] - 1;
00516 if (x > max_coord) max_coord = x;
00517 if (x < min_coord) min_coord = x;
00518 }
00519
00520 int maxSpread_new = max_coord - min_coord + 1;
00521 #if __DEBUG_SPANNING_TREE_
00522 if (CkMyPe() == 0)
00523 std::cout << m << " " << maxSpread_new << std::endl;
00524 #endif
00525 if (maxSpread_new == usedCoordinates[i].count()) {
00526 #if __DEBUG_SPANNING_TREE_
00527 if (CkMyPe() == 0)
00528 std::cout << "FIXED after " << (m+1) << " movements" << std::endl;
00529 #endif
00530 break;
00531 } else if (maxSpread_new < bestMaxSpread) {
00532 bestMaxSpread = maxSpread_new;
00533
00534 bestOffset = m;
00535 }
00536 if (m == dimSizes[i] - 2) {
00537
00538
00539 if (maxSpread_new > bestMaxSpread) {
00540 for (itr=start; itr != end; itr++) {
00541
00542
00543 int &x = (*itr).X[i];
00544 x += ((m - bestOffset)*-direction);
00545 x = modulo(x, dimSizes[i]);
00546 }
00547 }
00548 #if __DEBUG_SPANNING_TREE_
00549 if ((CkMyPe() == 0) && (bestMaxSpread < maxSpread[i]))
00550 std::cout << "Improved to " << bestMaxSpread << " max spread" << std::endl;
00551 #endif
00552 break;
00553 }
00554 }
00555 }
00556 }
00557 #endif
00558
00559 }
00560
00561 }
00562 #endif // TREE_STRATEGY_3D_TORUS_MIN_HOPS
00563