Next: Parallelism with Collection: Up: Collections. Ver 1.0+ Previous: Working with the

Accessing a Remote Collection Element. Ver 1.0+

The operator (...) is overloaded for collections so that one may access individual elements. If this element is local to the executing thread, then the (...) returns a pointer to the local object. If the object is not local, then ( ... ) returns a pointer to a cache buffer containing a copy of the object. The problem with the cache buffer is that it may be overwritten. If it is necessary to keep a copy of an element for a long period, or if a thread needs copies of several elements that must remain local together, then a better function to use is Get_CopyElem().

If the element of a collection is local Get_CopyElem(i) returns a pointer to the element and no copy is made. Otherwise, Get_CopyElem() allocates space on the local heap and makes a copy of the element there. That copy will persist until it is deleted by the users. A good example is in the following MethodOfElement code that computes the back-solve step in a cyclic reduction operation on a vector of elements for which operators +, *, / and = have all been overloaded. That is we solve the equation


       (*b)*X(i-s)  +  (*a)*Xnew(i)  +  (*b)*X(i+s)  =   Xold(i)
for Xnew(i) which overwrites Xold(i) in *this.

void DistributedTridiagonal::backSolve(int s){
    int k;
    ElementType *v1,*v2;
    v1 = (ElementType *) ThisCollection->Get_CopyElem(index1 -s);
    v2 = (ElementType *) ThisCollection->Get_CopyElem(index1 +s);

    *this = (*this - (*b)*( *v1 + *v2 ))/(*a);
        
     if (!ThisCollection->Is_Local(index1 -s))  delete v1;
     if (!ThisCollection->Is_Local(index1 +s))  delete v2;
}

Another frequent situation is when we only wish to look at part of an element. For example, if we have an element structure that contains one or more large arrays or sub-grids of a larger structure.


class BigElement{
  public:
     double x[100][100];
   ...
};
In many situations we may only wish to access part of this structure, for example, the first row of the array filed x. In this case, it would be very costly to cache a complete copy of the element. There are special functions that allow us to program a thread to fetch only the part of the element that we need. The function Get_ElementPart() takes three parameters. The first is the index of the element, the second is the offset of the of the data field measured in sizeof(int) word boundaries from the beginning of the element. The third parameter is the size in terms of multiples of sizeof(int). Note that the formulation does not allow for data fields that are character aligned. We will fix this in version 2.0.

As an example of how to fetch a single row of the field x from a remote element, the MethodOfElement member function below uses the this pointer to establish the correct offset.


#define IntOffset(p, x) ( ((int *) x) - ((int *) p)) 

void Grid::grabNeighborXrow(int index, int row){
  double *tmp;
  double mybuff[100];
  int size, off;
  off = IntOffset(this, &(this->x[row][0]));
  size = (sizeof(double)*100)/sizeof(int);
  tmp = (double *) ThisCollection->Get_ElementPart(index, off, size);
  for(int i = 0; i < N; i++) mybuff[i] = tmp[i];
}

In our future version, a user will not need to use Get_ElementPart to access part of an element. A user may simply write


 tmp = (double *) ThisCollection->(index)->x[row][0:99];
to get an entire row of a remote element.

It should also be noted that we have only used one dimensional collections in the examples in this sections. There are also versions of Get_ElementPart, Get_CopyElem() and (...) for two dimensional distributed array and higher dimensional structures will be allowed as soon as we have time to implement them.



Next: Parallelism with Collection: Up: Collections. Ver 1.0+ Previous: Working with the


beckman@cica.indiana.edu
Mon Nov 21 09:49:54 EST 1994