/*========================================================================= Program: ParaView Module: $RCSfile: vtkSubGroup.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /*---------------------------------------------------------------------------- Copyright (c) Sandia Corporation See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. ----------------------------------------------------------------------------*/ #include "vtkObjectFactory.h" #include "vtkMultiProcessController.h" #include "vtkSubGroup.h" #ifdef _MSC_VER #pragma warning ( disable : 4100 ) #endif #include vtkCxxRevisionMacro(vtkSubGroup, "$Revision: 1.11 $"); vtkStandardNewMacro(vtkSubGroup); vtkSubGroup::vtkSubGroup() { this->members = NULL; this->comm = NULL; this->nmembers = 0; this->myLocalRank = -1; this->tag = 0; this->nFrom = this->nTo = this->fanInTo = 0; this->nRecv = this->nSend = 0; this->gatherRoot = this->gatherLength = -1; } int vtkSubGroup::Initialize(int p0=0, int p1=0, int me=0, int itag=0, vtkCommunicator *c=NULL) { int i, ii; this->nmembers = p1 - p0 + 1; this->tag = itag; this->comm = c; if (this->members) { delete [] this->members; } this->members = new int [this->nmembers]; this->myLocalRank = -1; for (i=p0, ii=0; i<=p1; i++) { if (i == me) { this->myLocalRank = ii; } this->members[ii++] = i; } if (this->myLocalRank == -1) { delete [] this->members; this->members = NULL; return 1; } this->gatherRoot = this->gatherLength = -1; this->computeFanInTargets(); return 0; } int vtkSubGroup::computeFanInTargets() { int i; this->nTo = 0; this->nFrom = 0; for (i = 1; i < this->nmembers; i <<= 1) { int other = this->myLocalRank ^ i; if (other >= this->nmembers) { continue; } if (this->myLocalRank > other) { this->fanInTo = other; this->nTo++; /* one at most */ break; } else { this->fanInFrom[this->nFrom] = other; this->nFrom++; } } return 0; } void vtkSubGroup::moveRoot(int root) { int tmproot = this->members[root]; this->members[root] = this->members[0]; this->members[0] = tmproot; return; } void vtkSubGroup::restoreRoot(int root) { if (root == 0) { return; } this->moveRoot(root); if (this->myLocalRank == root) { this->myLocalRank = 0; this->computeFanInTargets(); } else if (this->myLocalRank == 0) { this->myLocalRank = root; this->computeFanInTargets(); } return; } void vtkSubGroup::setUpRoot(int root) { if (root == 0) { return; } this->moveRoot(root); if (this->myLocalRank == root) { this->myLocalRank = 0; this->computeFanInTargets(); } else if (this->myLocalRank == 0) { this->myLocalRank = root; this->computeFanInTargets(); } return; } vtkSubGroup::~vtkSubGroup() { delete [] this->members; this->members = NULL; } void vtkSubGroup::setGatherPattern(int root, int length) { int i; if ( (root == this->gatherRoot) && (length == this->gatherLength)) { return; } this->gatherRoot = root; this->gatherLength = length; int clogn; // ceiling(log2(this->nmembers)) for (clogn=0; 1<nmembers; clogn++); int left = 0; int right = this->nmembers - 1; int iroot = root; this->nSend = 0; this->nRecv = 0; for (i=0; imyLocalRank == iroot) { this->recvId[this->nRecv] = this->members[src]; this->recvOffset[this->nRecv] = offset; this->recvLength[this->nRecv] = len; this->nRecv++; } else if (this->myLocalRank == src) { this->sendId = this->members[iroot]; this->sendOffset = offset; this->sendLength = len; this->nSend++; } if (this->myLocalRank <= mid) { if (iroot > mid) { iroot = src; } right = mid; } else { if (iroot <= mid) { iroot = src; } left = mid + 1; } if (left == right) break; } return; } int vtkSubGroup::getLocalRank(int processId) { int localRank = processId - this->members[0]; if ( (localRank < 0) || (localRank >= this->nmembers)) return -1; else return localRank; } #define MINOP if (tempbuf[p] < buf[p]) {buf[p] = tempbuf[p];} #define MAXOP if (tempbuf[p] > buf[p]) {buf[p] = tempbuf[p];} #define SUMOP buf[p] += tempbuf[p]; #define REDUCE(Type, name, op) \ int vtkSubGroup::Reduce##name(Type *data, Type *to, int size, int root) \ { \ int i, p;\ if (this->nmembers == 1)\ { \ for (i=0; i= this->nmembers)) \ { \ return 1;\ } \ if (root != 0) \ { \ this->setUpRoot(root); \ } \ Type *buf, *tempbuf; \ tempbuf = new Type [size]; \ if (this->nTo > 0) \ { \ buf = new Type [size];\ } \ else \ { \ buf = to;\ } \ if (buf != data) \ { \ memcpy(buf, data, size * sizeof(Type));\ } \ for (i=0; i < this->nFrom; i++) \ { \ this->comm->Receive(tempbuf, size,\ this->members[this->fanInFrom[i]], this->tag);\ for (p=0; pnTo > 0)\ { \ this->comm->Send(buf, size, this->members[this->fanInTo], this->tag);\ delete [] buf;\ }\ if (root != 0) \ { \ this->restoreRoot(root);\ } \ return 0; \ } REDUCE(int, Min, MINOP) REDUCE(float, Min, MINOP) REDUCE(double, Min, MINOP) REDUCE(int, Max, MAXOP) REDUCE(float, Max, MAXOP) REDUCE(double, Max, MAXOP) REDUCE(int, Sum, SUMOP) #define BROADCAST(Type) \ int vtkSubGroup::Broadcast(Type *data, int length, int root) \ { \ int i;\ if (this->nmembers == 1) \ { \ return 0;\ } \ if ( (root < 0) || (root >= this->nmembers)) \ { \ return 1;\ } \ if (root != 0) \ { \ this->setUpRoot(root); \ } \ if (this->nTo > 0) \ { \ this->comm->Receive(data, length, this->members[this->fanInTo], this->tag);\ } \ for (i = this->nFrom-1 ; i >= 0; i--) \ { \ this->comm->Send(data, length, this->members[this->fanInFrom[i]], this->tag); \ } \ if (root != 0) \ { \ this->restoreRoot(root); \ } \ return 0; \ } BROADCAST(char) BROADCAST(int) BROADCAST(float) BROADCAST(double) #define GATHER(Type)\ int vtkSubGroup::Gather(Type *data, Type *to, int length, int root)\ { \ int i;\ Type *recvBuf;\ if (this->nmembers == 1)\ { \ for (i=0; i= this->nmembers)) \ { \ return 1;\ } \ this->setGatherPattern(root, length);\ if (this->nSend > 0)\ { \ recvBuf = new Type [length * this->nmembers];\ }\ else \ { \ recvBuf = to;\ }\ for (i=0; inRecv; i++) \ { \ this->comm->Receive(recvBuf + this->recvOffset[i], \ this->recvLength[i], this->recvId[i], this->tag);\ }\ memcpy(recvBuf + (length * this->myLocalRank), data,\ length * sizeof(Type));\ if (this->nSend > 0) \ { \ this->comm->Send(recvBuf + this->sendOffset,\ this->sendLength, this->sendId, this->tag);\ delete [] recvBuf;\ }\ return 0; \ } GATHER(int) GATHER(char) GATHER(float) int vtkSubGroup::AllReduceUniqueList(int *list, int len, int **newList) { int transferLen, myListLen, lastListLen, nextListLen; int *myList, *lastList, *nextList; myListLen = vtkSubGroup::MakeSortedUnique(list, len, &myList); if (this->nmembers == 1) { *newList = myList; return myListLen; } lastList = myList; lastListLen = myListLen; for (int i=0; i < this->nFrom; i++) { this->comm->Receive(&transferLen, 1, this->members[this->fanInFrom[i]], this->tag); int *buf = new int [transferLen]; this->comm->Receive(buf, transferLen, this->members[this->fanInFrom[i]], this->tag+1); nextListLen = vtkSubGroup::MergeSortedUnique(lastList, lastListLen, buf, transferLen, &nextList); delete [] buf; delete [] lastList; lastList = nextList; lastListLen = nextListLen; } if (this->nTo > 0) { this->comm->Send(&lastListLen, 1, this->members[this->fanInTo], this->tag); this->comm->Send(lastList, lastListLen, this->members[this->fanInTo], this->tag+1); } this->Broadcast(&lastListLen, 1, 0); if (this->myLocalRank > 0) { delete [] lastList; lastList = new int [lastListLen]; } this->Broadcast(lastList, lastListLen, 0); *newList = lastList; return lastListLen; } int vtkSubGroup::MergeSortedUnique(int *list1, int len1, int *list2, int len2, int **newList) { int newLen = 0; int i1=0; int i2=0; int *newl = new int [len1 + len2]; if (newl == NULL) { return 0; } while ((i1 < len1) || (i2 < len2)) { if (i2 == len2) { newl[newLen++] = list1[i1++]; } else if (i1 == len1) { newl[newLen++] = list2[i2++]; } else if (list1[i1] < list2[i2]) { newl[newLen++] = list1[i1++]; } else if (list1[i1] > list2[i2]) { newl[newLen++] = list2[i2++]; } else { newl[newLen++] = list1[i1++]; i2++; } } *newList = newl; return newLen; } int vtkSubGroup::MakeSortedUnique(int *list, int len, int **newList) { int i, newlen; int *newl; newl = new int [len]; if (newl == NULL) { return 0; } memcpy(newl, list, len * sizeof(int)); vtkstd::sort(newl, newl + len); for (i=1, newlen=1; iReduceMin(&token, &result, 1, 0); this->Broadcast(&token, 1, 0); return 0; } void vtkSubGroup::PrintSubGroup() const { int i; cout << "(Fan In setup ) nFrom: " << this->nFrom << ", nTo: " << this->nTo << endl; if (this->nFrom > 0) { for (i=0; inRecv << ", nSend: " << this->nSend << endl; if (this->nRecv > 0) { for (i=0; igatherRoot ; cout << ", gatherLength " << this->gatherLength << endl; cout << "nmembers: " << this->nmembers << endl; cout << "myLocalRank: " << this->myLocalRank << endl; for (i=0; inmembers; i++) { cout << " " << this->members[i]; if (i && (i%20 == 0)) { cout << endl; } } cout << endl; cout << "comm: " << this->comm; cout << endl; } void vtkSubGroup::PrintSelf(ostream &os, vtkIndent indent) { int i; os << indent << "(Fan In setup ) nFrom: " << this->nFrom << ", nTo: " << this->nTo << endl; if (this->nFrom > 0) { for (i=0; inRecv << ", nSend: " << this->nSend << endl; if (this->nRecv > 0) { for (i=0; igatherRoot ; os << indent << ", gatherLength " << this->gatherLength << endl; os << indent << "nmembers: " << this->nmembers << endl; os << indent << "myLocalRank: " << this->myLocalRank << endl; for (i=0; inmembers; i++) { os << indent << " " << this->members[i]; if (i && (i%20 == 0)) { os << indent << endl; } } os << indent << endl; os << indent << "comm: " << this->comm; os << indent << endl; }