Next: Vector Subsets of Up: Collections. Ver 1.0+ Previous: Collection Constructors. Ver

Communication between Collection Elements. Ver 1.0+

The elements in a collection have a global name space. That is, any processor object may refer to any element of any collection by using the elements integer Ident field or by array index notation in the case of collections that are derived from the DistributedArray collection class. To illustrate this, let us consider the parallel code that would implement a reduction of all elements of a collection. Over the next four subsections we will look at four ways this might be done. In the first scheme we will do a serial reduction from the main thread. In the second scheme we build a binary reduction tree from the elements and leave the total with element 0. We will make the following assumption. Each element in the collection has an addition operator and an accumulation operator defined as follows.


class E{
  public:
   E(){ // a ``zero'' initializer }
   E  operator +(E &);
   E & operator +=(E &);
};

The serial solution looks like this.


  Processor_Main(){
     Processors P;
     Distribution d( .... );
     Align a( .....)

     C < E >  x(d,a);   // x is the collection
     E total;
     for(i = 0; i < x.dim1size; i++);
        total += *x(i);  // x(i) returns pointer to element
};
The field dim1size is inherited from SuperKernel collection and denotes the size of the first dimension of the collection.The operator ( int ) returns a pointer to the element if the element lives in the address space of the executing. Otherwise it returns a pointer to a copy of the element. This mechanism will always allow any thread to access public data from any element of any collection. However, to modify an element with a statement like

     x(i)->y  = 3.14;
the element must reside in the address space of the executing thread. (This is because if the element is not local, the pointer x(i) will be pointing to a copy and the copy will be modified. In a similar manner, if f() is a member function of the element class that side effects the object, then the call

     x(i)->f();
will have no effect unless the element is local. There is a special kernel function that users may use to tell if an element is local to the executing thread:

    x.Is_Local(i)
returns true if the element is in the local address space.

There is one very important property of the x(i) operator that must always be kept in mind. If an element i in a collection x is not local to the thread that executes x(i), then x(i) points to a copy of the element. This copy should be viewed as a ``cached'' copy in a one element cache. Consequently, if a thread tries to access two non-local elements then only one may reside in the cache at any time. In other words, x(j) is a reference to another element after the reference to x(i), then the second reference will eliminate the first. So, for example, in the code below, the second reference to x(i) is an error.


    ElementType *p;
    p = x(i);
    printf(" %d", x(j)->Ident);  // x(j) overwrites *p 
    printf(" %d", p->Ident);     // error: p now points to x(j)
There are ways to avoid this problem by using the function Get_CopyElem() which is described in section 4.7.

In version 2.0 of pC++ we will change some of these rules. A new data type modifier global will be added. This idea comes from the CC++ language. The idea is that any data object that is of global type may be referenced by pointers of the form


    global ElementType *p;
In this case expressions of the form p->y = 3.14 or p->f() will cause a message to be sent to the processor object thread that contains the element to perform the given action on the element. Additional information on element communication can be found in section 4.7.




Next: Vector Subsets of Up: Collections. Ver 1.0+ Previous: Collection Constructors. Ver


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