Describes:
authorOrion Lawlor <olawlor@acm.org>
Sun, 8 Apr 2001 01:39:11 +0000 (01:39 +0000)
committerOrion Lawlor <olawlor@acm.org>
Sun, 8 Apr 2001 01:39:11 +0000 (01:39 +0000)
-Parameter marshalling
-PUP framework, pup routines, and PUP::able objects.
-[createhere] and [createhome]
-``initcall'' .ci file mechanism.

doc/charm++/arrays.tex
doc/charm++/manual.tex
doc/charm++/marshalling.tex [new file with mode: 0644]
doc/charm++/messages.tex
doc/charm++/othercalls.tex
doc/charm++/overview.tex
doc/charm++/pup.tex [new file with mode: 0644]

index 44eb2962bce05f0be170ec2061d9a7e43170e7df..fae0fb3370c0a49b219e3256ed7e16c7aa04286e 100644 (file)
@@ -204,14 +204,26 @@ aF[CkArrayIndexFoo(...)].doAgain();
 \end{alltt}
 
 You may invoke methods on array elements that have not yet
-been created-- the system will buffer the message until the
-element is created.  However, the element must eventually be 
-created (currently, there is a 3-minute buffering period).
+been created-- by default, the system will buffer the message until the
+element is created\footnote{However, the element must eventually be 
+created-- i.e., within a 3-minute buffering period.}.
+Instead, if you declare an entry method with the attribute 
+\index{createhere} \index{createhome}
+\kw{[createhere]} or \kw{[createhome]}, the array manager will 
+``demand create'' a new element (using the element's default constructor)
+to handle the message.  With \kw{[createhome]}, the new element
+is created on the home processor (most efficient when messages for
+the element may arrive from across the machine); with \kw{[createhere]},
+the new elment is created on the sending processor (most efficient
+when messages will often be sent from that processor).
+Of course, a single array can have a mix of demand-created and
+classic entry methods.
+
+
 Messages sent to migrating elements will be delivered after
 the migrating element arrives.  It is an error to send 
 a message to a deleted array element.
 
-
 To \index{Array broadcast} broadcast a message to all the current elements of an array, 
 simply omit the index, as:
 
@@ -488,12 +500,8 @@ void A2::pup(PUP::er \&p)
 \}
 \end{alltt}
 
-You can apply a \kw{PUP::er} to any primitive variable
-(as with ``p(nt)'') or array of primitive variables-- there,
-the second parameter gives the length of the array (as with
-``p(flt,7)'').  You can pass a simple run of bytes 
-by calling the \kw{PUP::er} with a ``void *'' and number of bytes
-(packing bytes, however, prevents cross-platform pack/unpacking).
+See the \index{PUP} section ``PUP'' for more details on pup routines
+and the \kw{PUP::er} type.
 
 The system uses one pup routine to do both packing and unpacking by
 passing different types of \kw{PUP::er}s to it.  You can determine
@@ -524,48 +532,6 @@ Migration constructors, then, are normally empty-- all the unpacking
 and allocation of the data items is done in the element's \uw{pup} routine.
 Deallocation is done in the element destructor as usual.
 
-The \kw{PUP::er} overhead is very small-- one virtual function call
-for each item to be packed/unpacked.  The actual packing/unpacking is
-a simple memory-to-memory binary copy.  In addition, the \uw{pup}
-routine may also be called to pack your array element to disk (e.g.,
-for a ``checkpoint'' operation), and unpack it from disk afterwards
-(e.g., for ``restart'' operation).  During unpacking, a
-``translating'' \kw{PUP::er} can be used to perform binary format
-conversion if needed.
-
-To easily pack user-defined types, we recommend adding
-a \uw{pup} method to the user-defined type:
-
-\begin{alltt}
-class myData 
-\{
-private:
-    int a,b;
-    char c;
-public:
-    ...
-    void pup(PUP::er \&p) \{
-        p(a);
-        p(b);
-        p(c);
-    \}
-\};
-
-//... array element can now easily pack myData as:
-class myElement:public ArrayElement1D 
-\{
-private:
-    myData d;
-public:
-    ...
-    void pup(PUP::er \&p)
-    \{
-        ArrayElement1D::pup(p); //Call superclass
-        d.pup(p); //<- pack/unpacks myData
-    \}
-\};
-\end{alltt}
-
 
 \subsubsection{Load Balancing Chare Arrays}
 \charmpp{} includes a run-time load balancer which works
index d66ea94f12b7d9db353eed66a8c567bff12da4c8..349b4bf5e2c3128e79e335659bd2203102d0e74c 100644 (file)
@@ -60,6 +60,7 @@ for the changes to the system since the last release.
 
 \section{The \charmpp\ Language}
   \input{modules}      
+  \input{marshalling}  
   \input{messages}
   \input{seqobjs}
   \input{chares}
@@ -67,7 +68,8 @@ for the changes to the system since the last release.
   \input{nodegroups}
   \input{arrays}
   \input{readonly}    
-  \input{quiesce}    
+  \input{quiesce}
+  \input{pup}
   \input{io}
   \input{othercalls}    
 
diff --git a/doc/charm++/marshalling.tex b/doc/charm++/marshalling.tex
new file mode 100644 (file)
index 0000000..fec0e75
--- /dev/null
@@ -0,0 +1,101 @@
+\subsection{Parameter Marshalling}
+       
+In \charmpp, \index{chare}chares, \index{group}groups and \index{nodegroup}
+nodegroups communicate by invoking each others methods. 
+The methods may either take several parameters, described here; 
+or take a special message object as described in the next section.
+Since parameters get marshalled into a message before being
+sent across the network, in this manual we use ``message''
+to mean either a literal message object or a set of marshalled
+parameters.
+
+For example, a chare could have this entry method declaration in 
+the interface ({\tt .ci}) file:
+\begin{alltt}
+  entry void foo(int i,int k);
+\end{alltt}
+Then invoking foo(2,3) on the chare proxy will eventually
+invoke foo(2,3) on the remote chare.
+
+Since \charmpp\ runs on distributed memory machines, we cannot
+pass an array via a pointer in the usual \CC\ way.  Instead,
+we must specify the length of the array in the interface file, as:
+\begin{alltt}
+  entry void bar(int n,double arr[n]);
+\end{alltt}
+Since \CC\ does not recognize this syntax, the array data
+should be passed to the chare proxy as a simple pointer.
+The array data will be copied sent to the
+destination processor, where the chare will receive the copy
+via a simple pointer again.  The remote copy of the data
+will be kept until the remote method returns, when
+it will be freed.  
+This means any modifications made locally after the call will not be 
+seen by the remote chare; and the remote chare's modifications
+will be lost after the remote method returns-- \charmpp\ always 
+uses call-by-value, even for arrays and structures.  
+
+This also means the data must be copied on the sending 
+side, and to be kept must be copied again 
+at the receive side-- for a more efficient approach,
+use the message objects described in the next section.
+
+Array parameters and other parameters can be combined in arbitrary ways, as:
+\begin{alltt}
+  entry void doLine(float data[n],int n);
+  entry void doPlane(float data[n*n],int n);
+  entry void doSpace(int n,int m,int o,float data[n*m*o]);
+  entry void doGeneral(int nd,int dims[nd],float data[product(dims,nd)]);
+\end{alltt}
+The array length expression between the square brackets can be 
+any valid C++ expression, and may depend in any way on any of the passed
+parameters, global variables, or global data.  The array length expression
+is evaluated exactly once per invocation, on the sending side only.
+
+\subsubsection{Marshalling User-Defined Structures and Classes}
+
+For a ``simple'' struct or class without dynamic allocation,
+virtual methods, or subclasses, the marshalling system will
+copy the type across machines as flat bytes.  Thus these sorts
+of structures will work properly as parameters or in arrays
+with no further effort:
+
+\begin{alltt}
+//Declarations:
+class point3d {
+public:
+    double x,y,z;    
+};
+
+typedef struct {
+    int refCount;
+    char data[17];
+} refChars;
+
+class date {
+public:
+    char month,day;
+    int year;
+    //...non-virtual manipulation routines...
+};
+
+//In the .ci file:
+    entry void pointRefOnDate(point3d &p,refChars r[d.year],date &d);
+\end{alltt}
+
+Any user-defined types in the argument list must be declared 
+before including the ``.decl.h'' file.
+As usual in \CC, it is often dramatically more efficient to pass
+a large structure by reference (as shown) than by value.
+
+Complicated structures, such as those with dynamically
+allocated data or virtual methods can only be passed as
+parameters, but never in arrays.  They also must include a pup
+routine and \CC\ operator| (see the PUP chapter for details).
+\kw{PUP::able} structures may be passed via a pointer,
+but will be dynamically allocated on the receive side
+but, for historical reasons, cannot appear alone in the
+parameter list (or else they are confused with messages).
+
+Complicated structures are usually most efficiently passed 
+via messages; not marshalling.
index 3448c66d1eca5f1192d7b5f634ffa9a8d8630022..81acdf731e29f0d6b520f15857573f4e2881fef2 100644 (file)
@@ -1,9 +1,10 @@
 \subsection{Messages}
 
 In \charmpp, \index{chare}chares, \index{group}groups and \index{nodegroup}
-nodegroups communicate using messages. Sending a message \index{message} to an
-object corresponds to an asynchronous method invocation.  Several variations on
-messaging are available, regular \charmpp{} messages are objects of
+nodegroups communicate using remote method invocation.  The methods may either take marshalled parameters, described in the previous section; or messages. Messages are lower level, more efficient, more flexible, and much more difficult to use than parameter marshalling.
+
+Several kinds of message are available.
+Regular \charmpp{} messages are objects of
 \textit{fixed size}. One can have messages that contain pointers or variable
 length arrays (arrays with sizes specified at runtime) and still have these
 pointers to be valid when messages are sent across processors, with some
@@ -26,7 +27,7 @@ In the {\tt .ci} file (the interface file), a message is declared as:
 A message that contains variable length arrays is declared as:
 
 \begin{alltt}
- message [varsize] MessageType \{
+ message MessageType \{
    type1 var_name1[];
    type2 var_name2[];
    type3 var_name3[];
@@ -142,8 +143,9 @@ Thus, the programmer needs a way to ``serialize'' these messages
 message crosses the address-space boundary.  \charmpp{} provides a way to do
 this serialization by allowing the developer to override the default
 serialization methods generated by the \charmpp{} interface translator.
+Note that this low-level serialization has nothing to do with the PUP framework described later.
 
-Such messages are declared in the {\tt .ci} file similar to the ordinary
+Packed messages are declared in the {\tt .ci} file the same way as ordinary
 messages:
 
 \begin{alltt}
index e628bb3862ae947b478caeccbbec35f19d3223d1..2165cf0343655abec2a159fddeda63e53dafa858 100644 (file)
@@ -1,3 +1,27 @@
+\subsection{\kw{initcall} routines}
+Some registration routines need be executed exactly once
+on every processor before the computation begins.
+By declaring a regular \CC subroutine \index{initcall}
+\kw{initcall} in the .ci file, you ask \charmpp to execute 
+the routine exactly once on every processor before the
+computation begins.
+
+\begin{alltt}
+module foo {
+    initcall void fooGlobalInit(void);
+    chare bar {
+        ...
+        initcall void barInit(void);
+    };
+};
+\end{alltt}
+
+This code will execute the routines \uw{fooGlobalInit} and
+\uw{bar::barInit} before the main computation starts.
+These routines should only do registration, not computation--
+use a mainchare, which gets executed on only one processor,
+to begin the computation.
+
 \subsection{Other Calls}
 
 \label{other Charm++ calls}
index 1ab3ad1266dfeba29f17f1f30b76323cd513246e..ad7e66e9734fee1cfff0a2a2bba8c29fa4de7592 100644 (file)
@@ -155,8 +155,10 @@ not be mentioned in the module interface files.
 
 Messages supply data arguments to the asynchronous remote method invocation.
 These objects are treated differently from other objects in \charmpp\ by the
-runtime system, and therefore they should be specified in the interface file of
-the module.  Messages are instances of \CC\ classes that are subclassed from a
+runtime system, and therefore they must be specified in the interface file of
+the module.  With parameter marshalling, the system creates and handles
+the message completely internally.
+Other messages are instances of \CC\ classes that are subclassed from a
 special class that is generated by the \charmpp\ interface translator.  Another
 variation of communication objects is conditionally packed and unpacked. This
 variation should be used when one wants to send messages that contain pointers
diff --git a/doc/charm++/pup.tex b/doc/charm++/pup.tex
new file mode 100644 (file)
index 0000000..fbda50a
--- /dev/null
@@ -0,0 +1,328 @@
+\subsection{PUP}
+
+The \index{PUP} PUP framework is a generic way to describe the data in an object.
+The \charmpp\ system can use this description to pack the object 
+into a message, and unpack the message into a new object on another 
+processor.
+The name thus is a contraction of the words Pack and UnPack (PUP).
+
+Like many \CC\ concepts, the PUP framework is easier to use than 
+describe: 
+
+\begin{alltt}
+class foo {
+ private:
+    double a;
+    int x;
+    char y;
+    unsigned long z;
+    float q[3];
+ public:
+    ...other methods...
+
+    //pack/unpack routine: describe my fields to charm++
+    void pup(PUP::er &p) {
+      p(a);
+      p(x);p(y);p(z);
+      p(q,3);
+    }
+};
+PUPmarshall(foo); //<- for passing foo's as marshalled parameters
+\end{alltt}
+
+This class's pup routine describes the fields of a \uw{foo} to \charmpp\.
+This will allow \charmpp\ to: marshall parameters of type \uw{foo},
+send \uw{foo} objects in messages, translate \uw{foo}s across processors,
+inspect and modify \uw{foo} objects in the debugger, and checkpoint 
+calculations involving \uw{foo}s.
+
+The \kw{PUPmarshall(\uw{foo})} statement allows foo objects to be
+marshalled properly when passed as parameters to \charmpp\ entry methods.
+
+As shown, data is described by passing it to an object of type 
+\index{PUP::er} \kw{PUP::er}.  You can apply a \kw{PUP::er} to any 
+primitive variable, as ``p(a)''.
+For an array of primitive variables, you apply the array and an integer
+that gives the length of the array, as in ``p(q,3)''.  You can pass a 
+simple run of bytes 
+by calling the \kw{PUP::er} with a ``void *'' and number of bytes
+(bytes, however, prevents cross-platform operation).
+
+The system uses the one pup routine to do both packing and unpacking by
+passing different types of \kw{PUP::er}s to it.  You can determine
+what type of \kw{PUP::er} has been passed to you with the
+\kw{p.isPacking()}, \kw{p.isUnpacking()}, and \kw{p.isSizing()} methods.
+The \kw{p.isDeleting()} method returns true if the pupped object
+will be deleted after packing.
+
+Note that the same data must be passed to the \kw{PUP::er} 
+in the same order regardless of the pack direction.
+This is the fundamental beauty of the \kw{PUP::er} framework.
+
+The \kw{PUP::er} overhead is very small-- one virtual function call
+for each item or array to be packed/unpacked.  The actual packing/unpacking is
+normally a simple memory-to-memory binary copy. 
+
+\subsubsection{C and Fortran bindings}
+C and Fortran programmers can use a limited subset of the
+\kw{PUP::er} capability.  The routines all take a 
+handle named \kw{pup\_er}.  The routines 
+have the prototype:
+\begin{alltt}
+void pup\_\kw{type}(pup\_er p,\kw{type} *val);
+void pup\_\kw{type}s(pup\_er p,\kw{type} *vals,int nVals);
+\end{alltt}
+The first call is for use with a single element;
+the second call is for use with an array.
+The supported types are char, short, int, long,
+uchar, ushort, uint, ulong, float, and double,
+which all have the usual C meanings.
+
+A byte-packing routine
+\begin{alltt}
+void pup\_bytes(pup\_er p,void *data,int nBytes);
+\end{alltt}
+is also provided, but its use is discouraged
+for cross-platform puping.
+
+\kw{pup\_isSizing}, \kw{pup\_isPacking}, \kw{pup\_isUnpacking},
+and \kw{pup\_isDeleting} calls are also available.
+Since C and Fortran have no destructors, you should 
+actually deallocate all data when passed a deleting \kw{pup\_er}.
+
+C and Fortran users cannot use \kw{PUP::able} objects, 
+seeking, or write custom \kw{PUP::er}s. Using the \CC\
+interface is recommended.
+
+\subsubsection{Dynamic Allocation}
+
+If your class has fields that are dynamically allocated, when unpacking
+these need to be allocated (in the usual way) before you pup them.
+Deallocation should be left to the class destructor as usual.
+
+\begin{alltt}
+class bar {
+private:
+    foo *f; /*Heap-allocated foo object*/
+    int n;
+    double *arr;/*Dynamically allocated array of n doubles*/
+public:
+    ...other methods...
+    //Destructor is the usual
+    ~bar() {free(arr);delete f;}
+    
+    //pack/unpack: describe my fields to Charm++
+    void pup(PUP::er &p) {
+      if (p.isUnpacking()) 
+         f=new foo;
+      f->pup(p);//pup f's fields
+      
+      p(n);//pup the array length n
+      if (p.isUnpacking()) 
+         arr=(double *)malloc(sizeof(double)*n);
+      p(arr,n);//pup array data
+    }
+};
+PUPmarshall(bar); //<- for passing foo's as marshalled parameters
+\end{alltt}
+
+
+\subsubsection{Automatic allocation via PUP::able}
+If the \uw{foo *} above might have been a subclass, instead of
+simply using \uw{new foo} above we would have had to allocate 
+an object of the appropriate subclass.  Since determining the
+proper subclass and calling the appropriate constructor can be 
+difficult, the PUP framework provides a scheme for automatically
+determining and dynamically allocating subobjects of the appropriate type.
+
+You enable this by inheriting the root of your inheritance heirarchy 
+from \kw{PUP::able}, adding empty \kw{CkMigrateMessage *} constructors,
+and including a few \#defines for each class.
+Each class needs a \kw{PUPable\_decl(\uw{className})} in its 
+declaration body, a \kw{PUPable\_def(\uw{className})} exactly once
+at file scope, and a \kw{PUPable\_reg(\uw{className})} executed
+exactly once on each processor at initialization time (usually
+via the ``initcall'' mechanism, see chapter of the same name).
+For example,
+
+\begin{alltt}
+//Somewhere in the .ci file:
+   initcall void parentChildInit(void);
+
+//In the .h file:
+class parent : public PUP::able {
+    ... data members ...
+public:
+    ... other methods ...
+    parent() {...}
+    parent(CkMigrateMessage *m) : PUP::able(m) {}
+    virtual void pup(PUP::er &p) {
+        PUP::able::pup(p);//Call base class
+        ... pup data members as usual ...
+    }
+    PUPable\_decl(parent);    
+};
+class child : public parent {
+    ... more data members ...
+public:    ... more methods, possibly virtual ...
+    child() {...}
+    child(CkMigrateMessage *m) : parent(m) {}
+    virtual void pup(PUP::er &p) {
+        parent::pup(p);//Call base class
+        ... pup child's data members as usual ...
+    }
+    PUPable\_decl(child);    
+};
+
+//Somewhere in a .C file:
+PUPable\_def(parent);
+PUPable\_def(child);
+void parentChildInit(void)
+{//Called once on each processor
+    PUPable\_reg(parent);
+    PUPable\_reg(child);
+}
+\end{alltt}
+
+These declarations supercede the \kw{PUPmarshall} declaration 
+described earlier.
+
+With these declarations, then, we can automatically 
+allocate and pup a pointer to a parent or child
+using the vertical bar \kw{PUP::er} syntax:
+
+\begin{alltt}
+class keepsParent {
+    parent *obj; //May actually point to a child class
+public:
+    ...
+    ~keepsParent() {
+        delete obj;
+    }
+    void pup(PUP::er &p) 
+    {
+        p|obj;
+    }
+};
+\end{alltt}
+
+This will properly pack, allocate, and unpack obj whether
+it is actually a parent or child object.  The child class 
+can use all the usual \CC\ features, such as virtual functions
+and extra private data.
+
+If obj is NULL when packed, it will be restored to NULL when unpacked.
+For example, if the nodes of a binary tree are \kw{PUP::able},
+one may write the tree's pup routine easily:
+
+\begin{alltt}
+class treeNode : public PUP::able {
+    treeNode *left;//Left subtree
+    treeNode *right;//Right subtree
+    ... other fields ...
+public:
+    ... usual PUP::able support: ...
+    treeNode(CkMigrateMessage *m) : PUP::able(m) {}
+    ~treeNode() {delete left; delete right;}
+    void pup(PUP::er &p) {
+        PUP::able::pup(p);//Call base class
+        p|left;
+        p|right;
+        ... pup other fields as usual ...
+    }
+    PUPable\_decl(treeNode);
+};
+\end{alltt}
+
+This same implementation will work properly if the tree's
+internal nodes are actually subclasses of treeNode.
+
+
+\subsubsection{Common PUP::ers}
+The most common \kw{PUP::er}s used are \kw{PUP::sizer},
+\kw{PUP::toMem}, and \kw{PUP::fromMem}.  These are sizing,
+packing, and unpacking \kw{PUP::er}s, respectively.
+
+\kw{PUP::sizer} simply sums up the sizes of the native
+binary representation of the objects it is passed.
+\kw{PUP::toMem} copies the binary representation of the
+objects passed into a preallocated contiguous memory buffer.
+\kw{PUP::fromMem} copies binary data from a contiguous memory
+buffer into the objects passed.  All three support the
+\kw{size} method, which returns the number of bytes used
+by the objects seen so far.
+
+Other common \kw{PUP::er}s are \kw{PUP::toDisk}, 
+\kw{PUP::fromDisk}, and \kw{PUP::xlater}.  The first
+two are simple filesystem variants of the \kw{PUP::toMem} 
+and \kw{PUP::fromMem} classes; \kw{PUP::xlater} translates
+binary data from an unpacking PUP::er into the machine's
+native binary format, based on a \kw{machineInfo} structure
+that describes the format used by the source machine.
+
+
+\subsubsection{PUP::seekBlock}
+It may rarely occur that you require items to be unpacked
+in a different order than they are packed.  That is, you
+want a seek capability.  \kw{PUP::er}s support a limited 
+form of seeking.
+
+To begin a seek block, create a \kw{PUP::seekBlock} object
+with your current PUP::er and the number of ``sections'' to 
+create.  Seek to a (0-based) section number
+with the seek method, and end the seeking with the endBlock method.
+For example, if we have two objects A and B, where A's pup
+depends on and affects some object B, we can pup the two with:
+
+\begin{alltt}
+void pupAB(PUP::er &p)
+{
+  ... other fields ...
+  PUP::seekBlock s(p,2); //2 seek sections
+  if (p.isUnpacking()) 
+  {//In this case, pup B first
+    s.seek(1);
+    B.pup(p);
+  }
+  s.seek(0);
+  A.pup(p,B);
+  
+  if (!p.isUnpacking()) 
+  {//In this case, pup B last
+    s.seek(1);
+    B.pup(p);
+  }
+  s.endBlock(); //End of seeking block
+  ... other fields ...
+};
+\end{alltt}
+
+Note that without the seek block, A's fields would be unpacked
+over B's memory, with disasterous consequences.
+The packing or sizing path must traverse the seek sections
+in numerical order; the unpack path may traverse them in any
+order.  There is currently a small fixed limit of 3 on the 
+maximum number of seek sections.
+
+
+\subsubsection{Writing a PUP::er}
+System-level programmers may occasionally find it useful to define
+their own \kw{PUP::er} objects.  The system \kw{PUP::er} class is 
+an abstract base class that funnels all incoming pup requests
+to a single subroutine:
+
+\begin{alltt}
+    virtual void bytes(void *p,int n,size\_t itemSize,dataType t);
+\end{alltt}
+
+The parameters are, in order, the field address, the number of items,
+the size of each item, and the type of the items. The \kw{PUP::er}
+is allowed to use these fields in any way.  However, an isSizing
+or isPacking PUP::er may not modify the referenced user data; 
+while an isUnpacking PUP::er may not read the original values of 
+the user data.  If your PUP::er is not clearly packing (saving values
+to some format) or unpacking (restoring values), declare it as 
+sizing \kw{PUP::er}.
+
+
+