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 namespace topo {
00007
00020 template <typename Iterator,typename ValueType = typename std::iterator_traits<Iterator>::value_type>
00021 class SpanningTreeStrategy_3dTorus_minHops: public SpanningTreeStrategy<Iterator>
00022 {
00023 public:
00024 virtual SpanningTreeVertex* buildNextGen(const Iterator firstVtx, const Iterator beyondLastVtx, const int maxBranches=2) = 0;
00025 };
00026
00027
00028
00031 template <typename Iterator>
00032 class SpanningTreeStrategy_3dTorus_minHops<Iterator,SpanningTreeVertex>: public SpanningTreeStrategy<Iterator>
00033 {
00034 public:
00035 virtual SpanningTreeVertex* buildNextGen(const Iterator firstVtx, const Iterator beyondLastVtx, const int maxBranches=2);
00036 };
00037
00038
00039
00045 template <typename Iterator>
00046 class SpanningTreeStrategy_3dTorus_minHops<Iterator,vtxType>: public SpanningTreeStrategy<Iterator>
00047 {
00048 public:
00049 virtual SpanningTreeVertex* buildNextGen(const Iterator firstVtx, const Iterator beyondLastVtx, const int maxBranches=2)
00050 {
00052 std::vector<SpanningTreeVertex> tree;
00053 for (Iterator itr = firstVtx; itr != beyondLastVtx; itr++)
00054 tree.push_back( SpanningTreeVertex(*itr) );
00056 SpanningTreeStrategy_3dTorus_minHops< std::vector<SpanningTreeVertex>::iterator > theRealBuilder;
00057 SpanningTreeVertex *result = theRealBuilder.buildNextGen(tree.begin(),tree.end(),maxBranches);
00059 int indx=0;
00060 for (Iterator itr = firstVtx; itr != beyondLastVtx; itr++)
00061 {
00062 *itr = tree[indx].id;
00063 indx++;
00064 }
00066 return result;
00067 }
00068 };
00069
00070
00071
00072 namespace impl {
00077 template <typename Iterator>
00078 class TreeBoundingBoxOn3dTorus
00079 {
00080 public:
00082 void partition(const Iterator parent, const Iterator start, const Iterator end, const int numPartitions);
00083
00084 protected:
00086 void bisect(const Iterator parent, const Iterator start, const Iterator end, const int numPartitions);
00088 void trisect(const Iterator parent, const Iterator start, const Iterator end, const int numPartitions);
00090 int findMaxSpreadDimension(const Iterator start, const Iterator end);
00092 class lessThan
00093 {
00094 public:
00095 lessThan(const int _dim): dim(_dim) {}
00096 inline bool operator() (const SpanningTreeVertex &a, const SpanningTreeVertex &b)
00097 {
00098 return (a.X[dim] < b.X[dim]);
00099 }
00100 private:
00101 const int dim;
00102 };
00103 };
00104 }
00105
00106 }
00107
00108
00109 #include "TopoManager.h"
00110
00111 namespace topo {
00112
00113 template <typename Iterator>
00114 SpanningTreeVertex* SpanningTreeStrategy_3dTorus_minHops<Iterator,SpanningTreeVertex>::buildNextGen(const Iterator firstVtx, const Iterator beyondLastVtx, const int maxBranches)
00115 {
00117 (*firstVtx).childIndex.clear();
00118 (*firstVtx).childIndex.reserve(maxBranches);
00119
00121 TopoManager aTopoMgr;
00123 for (Iterator itr = firstVtx; itr != beyondLastVtx; itr++)
00124 {
00125 (*itr).X.reserve(3);
00126 (*itr).X.assign(3,0);
00127 int coreNum;
00128 aTopoMgr.rankToCoordinates( (*itr).id, (*itr).X[0], (*itr).X[1], (*itr).X[2], coreNum );
00129 }
00131
00133 Iterator firstDescendant = firstVtx;
00134 impl::TreeBoundingBoxOn3dTorus<Iterator> treePart;
00135 treePart.partition(firstVtx,++firstDescendant,beyondLastVtx,maxBranches);
00136
00138 for (int i=0, numChildren=(*firstVtx).childIndex.size(); i<numChildren; i++)
00139 {
00140 Iterator rangeStart = firstVtx;
00141 std::advance(rangeStart,(*firstVtx).childIndex[i]);
00142 Iterator rangeEnd = firstVtx;
00143 if (i+1 == numChildren)
00144 rangeEnd = beyondLastVtx;
00145 else
00146 std::advance(rangeEnd, (*firstVtx).childIndex[i+1] );
00147 Iterator closestItr = pickClosest(*firstVtx,rangeStart,rangeEnd);
00148 std::iter_swap(rangeStart,closestItr);
00149 }
00151 return (new SpanningTreeVertex(*firstVtx) );
00152 }
00153
00154
00155
00156 namespace impl {
00157
00158 template <typename Iterator>
00159 inline void TreeBoundingBoxOn3dTorus<Iterator>::partition(const Iterator parent, const Iterator start, const Iterator end, const int numPartitions)
00160 {
00162 int numVertices = std::distance(start,end);
00164 if ( (numPartitions > 1) && (numVertices > 1) )
00165 {
00166 if (numPartitions % 3 == 0)
00167 trisect(parent,start,end,numPartitions);
00168 else
00169 bisect (parent,start,end,numPartitions);
00170 }
00172 else if ( (numPartitions >= 1) && (numVertices >= 1) )
00173 {
00174 int indx = std::distance(parent,start);
00175 (*parent).childIndex.push_back(indx);
00176 }
00178 else if (numVertices == 0)
00179 {
00180 }
00182 else if ( (numVertices >= 0) && (numPartitions == 0) )
00183 CkAbort("\nThere are vertices left but no remaining partitions to put them in.");
00185 else
00186 CkAbort("\nPartitioning fell through to the default case (which it never should). Check the logic in this routine.");
00187 }
00188
00189
00190
00191 template <typename Iterator>
00192 void TreeBoundingBoxOn3dTorus<Iterator>::bisect(const Iterator parent, const Iterator start, const Iterator end, const int numPartitions)
00193 {
00195 int numVertices = std::distance(start,end);
00197 int maxSpreadDim = findMaxSpreadDimension(start,end);
00199 Iterator median = start;
00200 std::advance(median,numVertices/2);
00202 std::nth_element( start, median, end, lessThan(maxSpreadDim) );
00204 int numLeft = numPartitions/2;
00205 partition(parent, start, median, numLeft);
00206 partition(parent, median, end, numPartitions - numLeft);
00207 }
00208
00209
00210
00211 template <typename Iterator>
00212 void TreeBoundingBoxOn3dTorus<Iterator>::trisect(const Iterator parent, const Iterator start, const Iterator end, const int numPartitions)
00213 {
00215 if (numPartitions % 3 == 0)
00216 {
00218 int numVertices = std::distance(start,end);
00220 int maxSpreadDim = findMaxSpreadDimension(start,end);
00222 Iterator oneThird = start;
00223 std::advance(oneThird,numVertices/3);
00224 Iterator twoThird = oneThird;
00225 std::advance(twoThird,numVertices/3);
00227 std::nth_element( start, oneThird, end, lessThan(maxSpreadDim) );
00228 std::nth_element( oneThird, twoThird, end, lessThan(maxSpreadDim) );
00230 int numLeft = numPartitions/3;
00231 partition(parent, start, oneThird, numLeft);
00232 partition(parent, oneThird, twoThird, numLeft);
00233 partition(parent, twoThird, end, numLeft);
00234 }
00236 else
00237 partition(parent, start, end, numPartitions);
00238 }
00239
00240
00241
00242 template <typename Iterator>
00243 int TreeBoundingBoxOn3dTorus<Iterator>::findMaxSpreadDimension(const Iterator start, const Iterator end)
00244 {
00245 int nDims = (*start).X.size();
00246 std::vector<int> min, max, spread;
00247 min.reserve(nDims);
00248 max.reserve(nDims);
00249 spread.reserve(nDims);
00251 min = max = (*start).X;
00252 for (Iterator itr = start; itr != end; itr++)
00253 {
00255 for (int i=0; i<nDims; i++)
00256 {
00257 if ( (*itr).X[i] < min[i] )
00258 min[i] = (*itr).X[i];
00259 if ( (*itr).X[i] > max[i] )
00260 max[i] = (*itr).X[i];
00261 }
00262 }
00264 int maxSpread = abs(max[0] - min[0]);
00265 int maxSpreadDimension = 0;
00266 for (int i=1; i<nDims; i++)
00267 {
00268 int spread = abs(max[i] - min[i]);
00269 if (maxSpread < spread )
00270 {
00271 maxSpread = spread;
00272 maxSpreadDimension = i;
00273 }
00274 }
00275 return maxSpreadDimension;
00276 }
00277
00278 }
00279
00280 }
00281 #endif // TREE_STRATEGY_3D_TORUS_MIN_HOPS
00282