Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

644 lines
14 KiB

/*=========================================================================
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 <vtkstd/algorithm>
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<<clogn < this->nmembers; clogn++);
int left = 0;
int right = this->nmembers - 1;
int iroot = root;
this->nSend = 0;
this->nRecv = 0;
for (i=0; i<clogn; i++)
{
int src, offset, len;
int mid = (left + right) / 2;
if (iroot <= mid)
{
src = (iroot == left ? mid + 1 : right);
}
else
{
src = (iroot == right ? mid : left);
}
if (src <= mid)
{ /* left ... mid */
offset = left * length;
len = (mid - left + 1) * length;
}
else
{ /* mid+1 ... right */
offset = (mid + 1) * length;
len = (right - mid) * length;
}
if (this->myLocalRank == 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<size; i++) to[i] = data[i];\
return 0;\
}\
if ( (root < 0) || (root >= 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; p<size; p++){ op }\
}\
delete [] tempbuf;\
if (this->nTo > 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<length; i++) to[i] = data[i];\
return 0;\
}\
if ( (root < 0) || (root >= this->nmembers)) \
{ \
return 1;\
} \
this->setGatherPattern(root, length);\
if (this->nSend > 0)\
{ \
recvBuf = new Type [length * this->nmembers];\
}\
else \
{ \
recvBuf = to;\
}\
for (i=0; i<this->nRecv; 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; i<len; i++)
{
if (newl[i] == newl[newlen-1])
{
continue;
}
newl[newlen++] = newl[i];
}
*newList = newl;
return newlen;
}
int vtkSubGroup::Barrier()
{
float token = 0;
float result;
this->ReduceMin(&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; i<nFrom; i++)
{
cout << "fanInFrom[" << i << "] = " << this->fanInFrom[i] << endl;
}
}
if (this->nTo > 0)
{
cout << "fanInTo = " << this->fanInTo << endl;
}
cout << "(Gather setup ) nRecv: " << this->nRecv << ", nSend: " << this->nSend << endl;
if (this->nRecv > 0)
{
for (i=0; i<nRecv; i++)
{
cout << "recvId[" << i << "] = " << this->recvId[i];
cout << ", recvOffset[" << i << "] = " << this->recvOffset[i];
cout << ", recvLength[" << i << "] = " << this->recvLength[i] << endl;
}
}
if (nSend > 0)
{
cout << "sendId = " << this->sendId;
cout << ", sendOffset = " << this->sendOffset;
cout << ", sendLength = " << this->sendLength << endl;
}
cout << "gatherRoot " << this->gatherRoot ;
cout << ", gatherLength " << this->gatherLength << endl;
cout << "nmembers: " << this->nmembers << endl;
cout << "myLocalRank: " << this->myLocalRank << endl;
for (i=0; i<this->nmembers; 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; i<nFrom; i++)
{
os << indent << "fanInFrom[" << i << "] = " << this->fanInFrom[i] << endl;
}
}
if (this->nTo > 0)
{
os << indent << "fanInTo = " << this->fanInTo << endl;
}
os << indent << "(Gather setup ) nRecv: " << this->nRecv << ", nSend: " << this->nSend << endl;
if (this->nRecv > 0)
{
for (i=0; i<nRecv; i++)
{
os << indent << "recvId[" << i << "] = " << this->recvId[i];
os << indent << ", recvOffset[" << i << "] = " << this->recvOffset[i];
os << indent << ", recvLength[" << i << "] = " << this->recvLength[i] << endl;
}
}
if (this->nSend > 0)
{
os << indent << "sendId = " << this->sendId;
os << indent << ", sendOffset = " << this->sendOffset;
os << indent << ", sendLength = " << this->sendLength << endl;
}
os << indent << "gatherRoot " << this->gatherRoot ;
os << indent << ", gatherLength " << this->gatherLength << endl;
os << indent << "nmembers: " << this->nmembers << endl;
os << indent << "myLocalRank: " << this->myLocalRank << endl;
for (i=0; i<this->nmembers; 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;
}