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