pcxx_ug (1158314), страница 6
Текст из файла (страница 6)
Thereason for this is that the basic communication mechanism in a pC++ program is tomake a copy of an element. Though pC++ maintains a global name space for elementsin a collection, there is no global name space other than program global data. Inparticular, the heap and stack of each processor object thread is for the private andexclusive use by that thread. This is because on distributed memory machines withoutshared address spaces, pointers cannot be moved across the machine and still havemeaning as pointers.Future versions of pC++ will have the concept of a global pointer that will help easethe pain of this restriction. An ElementType in a template TEClass collection can be a basic type like int, float,etc.
It can even be a global pointer to an element in version 2.0. However, the type ofan element must be a full C++ class in form of the collection described below. In otherwords, in version 1.0, if you want a collection of element of type int you must declarea class of the formclassint//////};Int{data;constructor (see next item) andany overloaded integer operators you needwould be here.In most cases this restriction is not serious.
Elements that are ne grained are discouraged because the overhead of member function calls will far outweigh the advantage ofparallel arithmetic. In version 1.0 an ElementType must have a constructor with no arguments.class Int{int data;public:Int(){ data = 0; }...};This constructor is used by the SuperKernel collection to allocate the elements. In thefuture this rule will be relaxed to allow more general constructors so that one may buildcollections from elements with arbitrary initializations.4.4 The Structure of a Collection.
Ver 1.0+While the C++ template based collections described in the preceding sections provides avery easy to use form of the collection concept, it does not allow for all the types of operationson aggregates that one frequently needs. For example, there is no way in which a member23function of a element class to refer to the structure of the collection as a whole. This missingfeature makes it dicult to write programs where one element object can refer to otherelements in terms of the topology dened by the collection.
To solve this problem there is amore elaborate (and more specialized) form of the collection class that has a special syntax.Collection NameOfCollectionType: ParentCollection{private:< private data fields and method functions>protected:< protected data fields and method functions>public:< other public data fields and method functions>MethodOfElement:< data and functions that are added to each element>};The key points to understand are listed below. Collections are derived from a special machine dependent root class called SuperKernel.Consequently, every user dened collection is required to be a subclass of SuperKernelor, at least, have the SuperKernel in its ancestry.
The SuperKernel class uses thedistribution and alignment objects of a collection to initialize the collection andallocate the appropriate element objects on each memory module. The kernel alsoprovides a global name space based on an integer enumeration of the elements of eachcollection. In other words the kernel numbers each element of the collection andthis number can be used by any element to identify and access any other element. Theimportant element access functions provided by the kernel will be described in greaterdetail later. A collection has private, protected and public data and member function elds exactly as any other class. However, unlike a standard class, when a collection objectis allocated a copy of the basic collection structure is allocated in the local memoryof each processor. Consequently, the data elds are not shared in the same way thatelement object indices are shared.
The method functions in a collection are invokedin SPMD mode, i.e. they execute in an independent thread on each processor. This isexplained in more detail later. Because the type of the collection element is not specied when the collection isdened, the special keyword ElementType is used to whenever it is necessary to referto the type of the element. A collection also has a set of data elds and member functions that are copied intoeach element as public elds. These are labeled in the collection as MethodOfElement:elds. The purpose of MethodOfElement elds is to allow each element to \inherit "properties of the collection and to dene operators that act on the elements with24knowledge of the global structure of collection.
Fields or method functions withinthe MethodOfElement section that are dened as virtual are assumed to be overriddenby a denition within the element class.To illustrate how the MethodOfELement eld works, we will show how the pC++ compiler translates a collection into the correct template class. We will start with a simple\hello world" example. There are four parts to every pC++ program and they must be inthe following order. First are the element class denitions. We will use a simple class E withone member function. Next, one must include the denition of the kernel with an includedirective as shown below.
Third are the denitions of the collections in the program. Lastis the main program, which in pC++ version 1.0 is called Processor_Main().#include "pcxx.h"class E{ // the elementint e_data;void sayHi(){ printf("hello"); }};#include "kernel.h"Collection Set: SuperKernel{int i;Set(Distribution *T, Align *A): SuperKernel(T,A){};MethodOfElement:int j;virtual void sayHi();void hello(){ printf("\nfrom element %d", Ident); }};Processor_Main(){Processors P;Distribution T(4,&P,BLOCK);Align A(4,"[ALIGN(V[i],T[i])]");Set<E> x(&T, &A);x.sayHi();x.hello();}The variable Ident is the unique element identier that is assigned to each element bythe SuperKernel. This program will print, up to a permutation of the last 4 lines,hellohellohellohellofrom element 0from element 325from element 1from element 2The collection Set in this example denes two new features that are added to each element.One is the integer eld j and the other is the member function hello.
Consequently, theuser should view the action of the compiler in this case as dening a new class, which weshall call Element which is derived from the users original class E.class Element: E{public:int Ident; // from SuperKernel MethodOfElementSuperkernel<Element> *ThisCollection;...// additional SuperKernel Fields.int j;// from Set MethodOfElementvoid hello();};This new element class inherits all of the MethodOfElement elds from all the collection inthe inheritance chain of the Set collection.
A way to view this is that the MethodOfElementelds and member functions form a wrapper around each collection element that allow theelement to references collection specic operators and data. The ThisCollection pointerprovides a way for the MethodOfElement functions to refer to the TEClass object data thatis local to the thread containing the element object as a member of the local collection.The Set collection is translated by the pC++ compiler to a template class of the formtemplate <class ELementType> TEClass Set: SuperKernel<ElementType>{int i;Set(Distribution *T, Align *A): SuperKernel(T,A){};}(Version 1.0 of the compiler does not actually generate an explicit template.
Instead, thecompiler expand the collection into a new class in a manner similar to the way the C++compiler expands templates. Version 2.0 will generate a template class as shown above.)The main program is the same except that the collection object denition is translatedtoSet<Element> x(&T, &A);4.5 Collection Constructors.
Ver 1.0+Every collection must have a constructor and each constructor must have at least two standard arguments: a pointer to a distribution and a pointer to an alignment. These twoarguments must be passed to the parent collection, which, in tern, passes them to the SuperKernel collection. For example, to build a collection constructor that initializes the localTEClass data one could write as follows.26Collection C: DistributedArray{int z;float x;public:C(Distribution *D, Align *A, int i, float j);};C::C(Distribution *D, Align *A, int i, float j): DistributedArray(D, A){z = i;x = j;};A BUG in the version 1.0 pC++ compiler will not allow constructors to be dened inlinein the Collection body.Constructors for the ElementType of a collection are restricted as well. See section 4.3.4.6 Communication between Collection Elements.
Ver 1.0+The elements in a collection have a global name space. That is, any processor object may referto any element of any collection by using the elements integer Ident eld or by array indexnotation in the case of collections that are derived from the DistributedArray collectionclass. To illustrate this, let us consider the parallel code that would implement a reductionof all elements of a collection.
Over the next four subsections we will look at four ways thismight be done. In the rst scheme we will do a serial reduction from the main thread. Inthe second scheme we build a binary reduction tree from the elements and leave the totalwith element 0. We will make the following assumption. Each element in the collection hasan addition operator and an accumulation operator dened 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 collection27E total;for(i = 0; i < x.dim1size; i++);total += *x(i); // x(i) returns pointer to element};The operator ( int ) returns a pointer to the th element if the th element lives in theaddress space of the executing.
Otherwise it returns a pointer to a copy of the th element.This mechanism will always allow any thread to access public data from any element of anycollection. However, to modify an element with a statement likeiiix(i)->y= 3.14;the element must reside in the address space of the executing thread. (This is because ifthe element is not local, the pointer x(i) will be pointing to a copy and the copy will bemodied. In a similar manner, if f() is a member function of the element class that sideeects the object, then the callx(i)->f();will have no eect unless the element is local. There is a special kernel function that usersmay use to tell if an element is local to the executing thread:x.Is_Local(i)returns true if the th element is in the local address space.There is one very important property of the x(i) operator that must always be kept inmind.