doc: more section promotion in a coupla chapters
[charm.git] / doc / charm++ / reductions.tex
1 \section{Reductions}
2
3 \subsection{Reduction Clients}
4
5 \label{reductionClients}
6
7 After the data is reduced, it is passed to a you via a callback object,
8 as described in section~\ref{callbacks}.  The message passed to
9 the callback is of type \kw{CkReductionMsg}.
10 The important members of \kw{CkReductionMsg} are
11 \kw{getSize()}, which returns the number of bytes of reduction data; and
12 \kw{getData()}, which returns a ``void *'' to the actual reduced data.
13
14 You may pass the client callback as an additional parameter to \kw{contribute}.
15 If different \kw{contribute} calls pass different callbacks, some (unspecified,
16 unreliable) callback will be chosen for use.
17 \begin{alltt}
18     double forces[2]=get_my_forces();
19     // When done, broadcast the CkReductionMsg to ``myReductionEntry''
20     CkCallback cb(CkIndex_myArrayType::myReductionEntry(NULL), thisProxy);
21     contribute(2*sizeof(double), forces,CkReduction::sum_double, cb);
22 \end{alltt}
23
24 In the case of the reduced version used for synchronization purposes, the
25 callback parameter will be the only input parameter:
26 \begin{alltt}
27     CkCallback cb(CkIndex_myArrayType::myReductionEntry(NULL), thisProxy);
28     contribute(cb);
29 \end{alltt}
30
31 If no member passes a callback to \kw{contribute}, the reduction will use
32 the {\em default} callback. Programmers can set the default callback for an array or group
33 using the \kw{ckSetReductionClient} proxy call on processor zero, or
34 by passing the callback to {\tt CkArrayOptions::setReductionClient()}
35 before creating the array, as described in section~\ref{CkArrayOptions}.
36 Again, a \kw{CkReductionMsg} message will be passed to this callback,
37 which must delete the message when done.
38
39 \begin{alltt}
40     // Somewhere on processor zero:
41     myProxy.ckSetReductionClient(new CkCallback(...));
42 \end{alltt}
43
44 So, for the previous reduction on chare array {\tt arr}:
45 \begin{alltt}
46     CkCallback *cb = new CkCallback(CkIndex_main::reportIn(NULL),  mainProxy);
47     arr.ckSetReductionClient(cb);
48 \end{alltt}
49
50 and the actual entry point:
51
52 \begin{alltt}
53 void myReductionEntry(CkReductionMsg *msg)
54 \{
55   int reducedArrSize=msg->getSize() / sizeof(double);
56   double *output=(double *) msg->getData();
57   for(int i=0 ; i<reducedArrSize ; i++)
58   \{
59    // Do something with the reduction results in each output[i] array element
60    .
61    .
62    .
63   \}
64   delete msg;
65 \}
66 \end{alltt}
67
68 (See \kw{pgms/charm++/RedExample} for a complete example).
69
70 For backward compatibility, in the place of a general callback, you can
71 specify a particular kind of C function using \kw{ckSetReductionClient}
72 or \kw{setReductionClient}.  This C function takes a user-defined
73 parameter (passed to \kw{setReductionClient}) and the actual reduction data,
74 which it must not deallocate.
75
76 \begin{alltt}
77   // Somewhere on processor zero (possibly in Main::Main, after creating 'myProxy'):
78   myProxy.setReductionClient(myClient,(void *)NULL);
79
80   // Code for the C function that serves as reduction client:
81   void myClient(void *param,int dataSize,void *data)
82   \{
83     double *forceSum=(double *)data;
84     cout<<``First force sum is ``<<forceSum[0]<<endl;
85     cout<<``Second force sum is ``<<forceSum[1]<<endl;
86   \}
87 \end{alltt}
88
89 If the target of a reduction is an entry method defined by a
90 \emph{whem} clause in \ref[SDAG]{sdag}, one may wish to set a
91 reference number or tag that SDAG can use to match the resulting
92 reduction message. To set the tag on a reduction message, the
93 contributors can pass an additional integer argument at the end of the
94 {\tt contribute()} call.
95
96 \subsection{Defining a New Reduction Type}
97
98 \label{new_type_reduction}
99
100 It is possible to define a new type of reduction, performing a 
101 user-defined operation on user-defined data.  This is done by 
102 creating a {\em reduction function}, which 
103 combines separate contributions 
104 into a single combined value.
105
106 The input to a reduction function is a list of \kw{CkReductionMsg}s.
107 A \kw{CkReductionMsg} is a thin wrapper around a buffer of untyped data
108 to be reduced.  
109 The output of a reduction function is a single CkReductionMsg
110 containing the reduced data, which you should create using the
111 \kw{CkReductionMsg::buildNew(int nBytes,const void *data)} method.  
112
113 Thus every reduction function has the prototype:
114 \begin{alltt}
115 CkReductionMsg *\uw{reductionFn}(int nMsg,CkReductionMsg **msgs);
116 \end{alltt}
117
118 For example, a reduction function to add up contributions 
119 consisting of two machine {\tt short int}s would be:
120
121 \begin{alltt}
122 CkReductionMsg *sumTwoShorts(int nMsg,CkReductionMsg **msgs)
123 \{
124   //Sum starts off at zero
125   short ret[2]={0,0};
126   for (int i=0;i<nMsg;i++) \{
127     //Sanity check:
128     CkAssert(msgs[i]->getSize()==2*sizeof(short));
129     //Extract this message's data
130     short *m=(short *)msgs[i]->getData();
131     ret[0]+=m[0];
132     ret[1]+=m[1];
133   \}
134   return CkReductionMsg::buildNew(2*sizeof(short),ret);
135 \}
136 \end{alltt}
137
138 The reduction function must be registered with \charmpp{} 
139 using \kw{CkReduction::addReducer} from
140 an \kw{initnode} routine (see section~\ref{initcall} for details
141 on the \kw{initnode} mechanism).   \kw{CkReduction::addReducer}
142 returns a \kw{CkReduction::reducerType} which you can later 
143 pass to \kw{contribute}.  Since \kw{initnode} routines are executed
144 once on every node, you can safely store the \kw{CkReduction::reducerType}
145 in a global or class-static variable.  For the example above, the reduction
146 function is registered and used in the following manner:
147
148 \begin{alltt}
149 //In the .ci file:
150   initnode void registerSumTwoShorts(void);
151
152 //In some .C file:
153 /*global*/ CkReduction::reducerType sumTwoShortsType;
154 /*initnode*/ void registerSumTwoShorts(void)
155 \{
156   sumTwoShortsType=CkReduction::addReducer(sumTwoShorts);
157 \}
158
159 //In some member function, contribute data to the customized reduction:
160   short data[2]=...;
161   contribute(2*sizeof(short),data,sumTwoShortsType);
162 \end{alltt}
163
164 Note that you cannot call \kw{CkReduction::addReducer}
165 from anywhere but an \kw{initnode} routine.
166
167