00001 #ifndef VIRTUAL_ROUTER_H
00002 #define VIRTUAL_ROUTER_H
00003
00004 #include <algorithm>
00005 #include <vector>
00006
00007
00008
00009 static const int routeNotFound = -1;
00010
00011 static const int initialCompletionStage = -2;
00012 static const int finalCompletionStage = -1;
00013
00014 struct Route {
00015 int dimension;
00016 int dimensionIndex;
00017 int destinationPe;
00018 };
00019
00020 struct CompletionStatus {
00021 int stageIndex;
00022 int numContributors;
00023 std::vector<int> dimensionsToFlush;
00024
00025 void pup(PUP::er &p) {
00026 p|stageIndex;
00027 p|numContributors;
00028 p|dimensionsToFlush;
00029 }
00030 };
00031
00032
00033 template <class Derived>
00034 class VirtualRouter {
00035
00036 protected:
00037
00038 int numDimensions_;
00039 int myIndex_;
00040 int numMembers_;
00041 std::vector<int> individualDimensionSizes_;
00042 std::vector<int> combinedDimensionSizes_;
00043 std::vector<int> myLocationIndex_;
00044
00045 int initialRoutingDimension_;
00046
00047 #ifdef CMK_TRAM_CACHE_ROUTE
00048 std::vector <Route> cachedRoutes_;
00049 std::vector <bool> isCached_;
00050 #endif
00051
00052 public:
00053
00054
00055 void initializeRouter(int numDimensions,
00056 int myIndex,
00057 int *dimensionSizes) {
00058 numMembers_ = CkNumPes();
00059 numDimensions_ = numDimensions;
00060 myIndex_ = myIndex;
00061 individualDimensionSizes_.assign(dimensionSizes,
00062 dimensionSizes + numDimensions_);
00063 combinedDimensionSizes_.resize(numDimensions_);
00064 myLocationIndex_.resize(numDimensions_);
00065
00066 int sumAlongAllDimensions = 0;
00067 combinedDimensionSizes_[numDimensions - 1] = 1;
00068 sumAlongAllDimensions += individualDimensionSizes_[numDimensions_ - 1];
00069 for (int i = numDimensions_ - 2; i >= 0; i--) {
00070 sumAlongAllDimensions += individualDimensionSizes_[i];
00071 combinedDimensionSizes_[i] =
00072 combinedDimensionSizes_[i + 1] * individualDimensionSizes_[i + 1];
00073 }
00074 if (combinedDimensionSizes_[0] * individualDimensionSizes_[0]
00075 != numMembers_) {
00076 CkAbort("Error: number of elements in virtual topology must be equal to "
00077 "total number of PEs.");
00078 }
00079
00080 int remainder = myIndex_;
00081 for (int i = 0; i < numDimensions_; i++) {
00082 myLocationIndex_[i] = remainder / combinedDimensionSizes_[i];
00083 remainder -= combinedDimensionSizes_[i] * myLocationIndex_[i];
00084 }
00085
00086 #ifdef CMK_TRAM_CACHE_ROUTE
00087 cachedRoutes_.resize(numMembers_);
00088 isCached_.resize(numMembers_);
00089 std::fill(isCached_, isCached_ + numMembers_, false);
00090 #endif
00091
00092 static_cast<Derived*>(this)->additionalInitialization();
00093 }
00094
00095 void pup(PUP::er &p) {
00096 p|numDimensions_;
00097 p|myIndex_;
00098 p|numMembers_;
00099 p|individualDimensionSizes_;
00100 p|combinedDimensionSizes_;
00101 p|myLocationIndex_;
00102 p|initialRoutingDimension_;
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 };
00127
00128 template <class Derived>
00129 class MeshRouter: public VirtualRouter<Derived> {
00130
00131 private:
00132
00133 inline void assignRoute(int dimension, int dimensionIndex,
00134 Route &routeToDestination) {
00135 routeToDestination.dimension = dimension;
00136 routeToDestination.dimensionIndex = dimensionIndex;
00137 routeToDestination.destinationPe =
00138 nextPeAlongRoute(dimension, dimensionIndex);
00139
00140 #ifdef CMK_TRAM_CACHE_ROUTE
00141 this->cachedRoutes_[destinationPe] = routeToDestination;
00142 this->isCached_[destinationPe] = true;
00143 #endif
00144
00145 }
00146
00147 protected:
00148
00149 inline int routeAlongDimension(int destinationPe, int dimension) {
00150
00151 int blockIndex = destinationPe / this->combinedDimensionSizes_[dimension];
00152
00153 int dimensionIndex =
00154 blockIndex - blockIndex / this->individualDimensionSizes_[dimension]
00155 * this->individualDimensionSizes_[dimension];
00156
00157 return dimensionIndex;
00158 }
00159
00160 public:
00161
00162 void additionalInitialization() {
00163 this->initialRoutingDimension_ = this->numDimensions_ - 1;
00164 }
00165
00166 inline int nextPeAlongRoute(int dimension, int dimensionIndex) {
00167 int destinationPe =
00168 this->myIndex_ + (dimensionIndex - this->myLocationIndex_[dimension]) *
00169 this->combinedDimensionSizes_[dimension];
00170
00171 return destinationPe;
00172
00173 }
00174
00175 inline void determineInitialRoute(int destinationPe,
00176 Route &routeToDestination) {
00177 if (destinationPe == CkMyPe()) {
00178 routeToDestination.dimension = 0;
00179 routeToDestination.destinationPe = destinationPe;
00180 routeToDestination.dimensionIndex = routeAlongDimension(destinationPe, 0);
00181 } else {
00182
00183
00184 static_cast<Derived*>(this)->
00185 determineRoute(destinationPe, this->initialRoutingDimension_ + 1,
00186 routeToDestination);
00187 }
00188 }
00189
00190 inline void determineRoute(int destinationPe, int dimensionReceivedAlong,
00191 Route &routeToDestination) {
00192
00193 #ifdef CMK_TRAM_CACHE_ROUTE
00194 if (this->isCached_[destinationPe]) {
00195 return this->cachedRoutes_[destinationPe];
00196 }
00197 #endif
00198
00199 for (int i = dimensionReceivedAlong - 1; i >= 0; i--) {
00200 int dimensionIndex = routeAlongDimension(destinationPe, i);
00201 if (dimensionIndex != this->myLocationIndex_[i]) {
00202 static_cast<Derived*>(this)->
00203 assignRoute(i, dimensionIndex, routeToDestination);
00204 return;
00205 }
00206 }
00207
00208 routeToDestination.dimension = routeNotFound;
00209 }
00210
00211 void updateCompletionProgress(CompletionStatus ¤tStatus) {
00212 if (currentStatus.stageIndex == initialCompletionStage) {
00213 currentStatus.stageIndex = this->numDimensions_ - 1;
00214 }
00215 else {
00216 currentStatus.stageIndex--;
00217 }
00218
00219 int currentStage = currentStatus.stageIndex;
00220 if (currentStage == finalCompletionStage) {
00221 return;
00222 }
00223
00224 currentStatus.numContributors =
00225 this->individualDimensionSizes_[currentStage] - 1;
00226 currentStatus.dimensionsToFlush.push_back(currentStage);
00227 }
00228
00229 inline int numBuffersPerDimension(int dimension) {
00230 return this->individualDimensionSizes_[dimension];
00231 }
00232
00233 inline int maxNumAllocatedBuffers() {
00234 int numBuffers = 0;
00235 for (int i = 0; i < this->numDimensions_; i++) {
00236
00237 numBuffers += numBuffersPerDimension(i) - 1;
00238 }
00239 return numBuffers;
00240 }
00241
00242 inline int numMsgTypes() {
00243 return this->numDimensions_;
00244 }
00245
00246 inline bool isMessagePersonalized(int dimension) {
00247 return false;
00248 }
00249
00250 inline int dimensionReceived(int msgType) {
00251
00252 return msgType;
00253 }
00254
00255 inline int determineMsgType(int dimension) {
00256 #if CMK_MULTICORE
00257 return !isMessagePersonalized(dimension);
00258 #else
00259 return dimension;
00260 #endif
00261 }
00262
00263 inline bool isBufferInUse(int dimension, int index) {
00264 return index != this->myLocationIndex_[dimension];
00265 }
00266
00267 inline bool isBroadcastSupported() {
00268 return false;
00269 }
00270
00271 };
00272
00273 class SimpleMeshRouter: public MeshRouter<SimpleMeshRouter> {};
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 class NodeAwareMeshRouter: public MeshRouter<NodeAwareMeshRouter> {
00285
00286 private:
00287 int myAssignedDim_;
00288
00289
00290 int teamSize_;
00291 int dimensionOfArrivingMsgs_;
00292 std::vector<int> forwardingDestinations_;
00293
00294
00295
00296
00297 enum {personalizedMsgType, forwardMsgType, msgTypeCount};
00298
00299 int numSendingToMe(int msgType) {
00300 int senderCount = 0;
00301 if (msgType == forwardMsgType) {
00302 if (myAssignedDim_ > numDimensions_ - 1) {
00303
00304 senderCount = 0;
00305 }
00306 else {
00307
00308 senderCount = numDimensions_ - 1;
00309
00310 if (myAssignedDim_ != numDimensions_ - 2) {
00311 senderCount +=
00312 individualDimensionSizes_[dimensionOfArrivingMsgs_] - 1;
00313 }
00314
00315 int offset = myLocationIndex_[numDimensions_ - 1] +
00316 (numDimensions_ - myAssignedDim_) * teamSize_;
00317
00318 while (offset < individualDimensionSizes_[numDimensions_ - 1]) {
00319 senderCount++;
00320 offset += teamSize_;
00321 }
00322 }
00323 }
00324 else if (msgType == personalizedMsgType) {
00325 senderCount =
00326 myAssignedDim_ == numDimensions_ - 1 ? teamSize_ - 1 : teamSize_;
00327 }
00328 else {
00329 CkAbort("In function NodeAwareMeshRouter::numSendingToMe(int msgType): "
00330 "invalid message type.\n");
00331 }
00332 return senderCount;
00333 }
00334
00335 public:
00336
00337 void additionalInitialization() {
00338
00339
00340 if (individualDimensionSizes_[numDimensions_ - 1] < numDimensions_) {
00341 CkAbort("Error: Last dimension in TRAM virtual topology must have size "
00342 "greater than or equal to number of dimensions in the topology.");
00343 }
00344
00345 teamSize_ = individualDimensionSizes_[numDimensions_ - 1] / numDimensions_;
00346 myAssignedDim_ = myLocationIndex_[numDimensions_ - 1] / teamSize_;
00347
00348
00349
00350 if (myAssignedDim_ > numDimensions_ - 1) {
00351 dimensionOfArrivingMsgs_ = numDimensions_ - 1;
00352 }
00353 else {
00354 dimensionOfArrivingMsgs_ =
00355 myAssignedDim_ == numDimensions_ - 1 ? 0 : myAssignedDim_ + 1;
00356 }
00357 forwardingDestinations_.resize(numDimensions_);
00358
00359 int baseIndex = myIndex_ - myLocationIndex_[numDimensions_ - 1] +
00360 myIndex_ % teamSize_;
00361 for (int i = 0; i < numDimensions_; i++) {
00362 forwardingDestinations_[i] = baseIndex + i * teamSize_;
00363 }
00364
00365
00366
00367 initialRoutingDimension_ = numDimensions_ - 2;
00368
00369 }
00370
00371 inline void assignRoute(int dimension, int dimensionIndex,
00372 Route &routeToDestination) {
00373 routeToDestination.dimension = dimension;
00374 routeToDestination.dimensionIndex =
00375 myAssignedDim_ == dimension ? dimensionIndex : 0;
00376 routeToDestination.destinationPe =
00377 nextPeAlongRoute(dimension, dimensionIndex);
00378 }
00379
00380 inline int nextPeAlongRoute(int dimension, int dimensionIndex) {
00381 int destinationPe;
00382
00383 if (dimension == myAssignedDim_) {
00384 destinationPe =
00385 MeshRouter<NodeAwareMeshRouter>::nextPeAlongRoute(dimension,
00386 dimensionIndex);
00387
00388
00389
00390 if (dimension == 0) {
00391 destinationPe += (numDimensions_ - 1) * teamSize_;
00392 }
00393 else if (dimension != numDimensions_ - 1) {
00394 destinationPe -= teamSize_;
00395 }
00396 }
00397 else {
00398
00399
00400
00401 destinationPe = forwardingDestinations_[dimension];
00402 }
00403
00404 return destinationPe;
00405 }
00406
00407 inline void determineRoute(int destinationPe, int dimensionReceivedAlong,
00408 Route &routeToDestination) {
00409
00410 MeshRouter<NodeAwareMeshRouter>::
00411 determineRoute(destinationPe, dimensionReceivedAlong, routeToDestination);
00412
00413 if (routeToDestination.dimension == routeNotFound) {
00414 int dimensionIndex =
00415 routeAlongDimension(destinationPe, numDimensions_ - 1);
00416 assignRoute(numDimensions_ - 1, dimensionIndex, routeToDestination);
00417 }
00418
00419 }
00420
00421 void updateCompletionProgress(CompletionStatus ¤tStatus) {
00422 if (currentStatus.stageIndex == initialCompletionStage) {
00423 currentStatus.stageIndex = forwardMsgType;
00424 }
00425 else {
00426 currentStatus.stageIndex--;
00427 }
00428
00429 int currentStage = currentStatus.stageIndex;
00430 if (currentStage == finalCompletionStage) {
00431 return;
00432 }
00433
00434 currentStatus.numContributors = numSendingToMe(currentStage);
00435
00436 if (currentStatus.stageIndex == forwardMsgType) {
00437 for (int i = numDimensions_ - 2; i >= dimensionOfArrivingMsgs_;
00438 i--) {
00439 currentStatus.dimensionsToFlush.push_back(i);
00440 }
00441 }
00442 else {
00443 for (int i = dimensionOfArrivingMsgs_ - 1; i >= 0; i--) {
00444 currentStatus.dimensionsToFlush.push_back(i);
00445 }
00446 currentStatus.dimensionsToFlush.push_back(numDimensions_ - 1);
00447 }
00448 }
00449
00450 inline int numBuffersPerDimension(int dimension) {
00451 int numBuffers =
00452 dimension == myAssignedDim_ ? individualDimensionSizes_[dimension] : 1;
00453
00454 return numBuffers;
00455 }
00456
00457 inline int maxNumAllocatedBuffers() {
00458 int numBuffers = 0;
00459 for (int i = 0; i < numDimensions_; i++) {
00460 numBuffers += numBuffersPerDimension(i);
00461 }
00462 return numBuffers;
00463 }
00464
00465 inline int numMsgTypes() {
00466 return msgTypeCount;
00467 }
00468
00469 inline bool isMessagePersonalized(int dimension) {
00470 return
00471 dimension == numDimensions_ - 1 && myAssignedDim_ == numDimensions_ - 1;
00472 }
00473
00474 inline int dimensionReceived(int msgType) {
00475 CkAssert(msgType == forwardMsgType);
00476 return dimensionOfArrivingMsgs_;
00477 }
00478
00479 inline int determineMsgType(int dimension) {
00480 return !isMessagePersonalized(dimension);
00481 }
00482
00483 inline bool isBufferInUse(int dimension, int index) {
00484 return true;
00485 }
00486
00487 inline bool isBroadcastSupported() {
00488 return false;
00489 }
00490
00491 };
00492
00493 #endif