\section{Reduction Clients}

\label{reductionClients}

After the data is reduced, it is passed to you via a callback object,
as described in section~\ref{callbacks}.  The message passed to
the callback is of type \kw{CkReductionMsg}. Unlike typed reductions
briefed in Section~\ref{reductions}, here we discuss callbacks that take 
\kw{CkReductionMsg*} argument.
The important members of \kw{CkReductionMsg} are
\kw{getSize()}, which returns the number of bytes of reduction data; and
\kw{getData()}, which returns a ``void *'' to the actual reduced data.

You may pass the client callback as an additional parameter to \kw{contribute}.
If different \kw{contribute} calls pass different callbacks, some (unspecified,
unreliable) callback will be chosen for use.
\begin{alltt}
    double forces[2]=get_my_forces();
    // When done, broadcast the CkReductionMsg to ``myReductionEntry''
    CkCallback cb(CkIndex_myArrayType::myReductionEntry(NULL), thisProxy);
    contribute(2*sizeof(double), forces,CkReduction::sum_double, cb);
\end{alltt}

In the case of the reduced version used for synchronization purposes, the
callback parameter will be the only input parameter:
\begin{alltt}
    CkCallback cb(CkIndex_myArrayType::myReductionEntry(NULL), thisProxy);
    contribute(cb);
\end{alltt}

If no member passes a callback to \kw{contribute}, the reduction will use
the {\em default} callback. Programmers can set the default callback for an array or group
using the \kw{ckSetReductionClient} proxy call on processor zero, or
by passing the callback to {\tt CkArrayOptions::setReductionClient()}
before creating the array, as described in section~\ref{CkArrayOptions}.
Again, a \kw{CkReductionMsg} message will be passed to this callback,
which must delete the message when done.

\begin{alltt}
    // Somewhere on processor zero:
    myProxy.ckSetReductionClient(new CkCallback(...));
\end{alltt}

So, for the previous reduction on chare array {\tt arr}:
\begin{alltt}
    CkCallback *cb = new CkCallback(CkIndex_main::reportIn(NULL),  mainProxy);
    arr.ckSetReductionClient(cb);
\end{alltt}

and the actual entry point:

\begin{alltt}
void myReductionEntry(CkReductionMsg *msg)
\{
  int reducedArrSize=msg->getSize() / sizeof(double);
  double *output=(double *) msg->getData();
  for(int i=0 ; i<reducedArrSize ; i++)
  \{
   // Do something with the reduction results in each output[i] array element
   .
   .
   .
  \}
  delete msg;
\}
\end{alltt}

(See \examplerefdir{RedExample} for a complete example).

For backward compatibility, in the place of a general callback, you can
specify a particular kind of C function using \kw{ckSetReductionClient}
or \kw{setReductionClient}.  This C function takes a user-defined
parameter (passed to \kw{setReductionClient}) and the actual reduction data,
which it must not deallocate.

\begin{alltt}
  // Somewhere on processor zero (possibly in Main::Main, after creating 'myProxy'):
  myProxy.setReductionClient(myClient,(void *)NULL);

  // Code for the C function that serves as reduction client:
  void myClient(void *param,int dataSize,void *data)
  \{
    double *forceSum=(double *)data;
    cout<<``First force sum is ``<<forceSum[0]<<endl;
    cout<<``Second force sum is ``<<forceSum[1]<<endl;
  \}
\end{alltt}

If the target of a reduction is an entry method defined by a
\emph{when} clause in SDAG(Section~\ref{sec:sdag}), one may wish to set a
reference number (or tag) that SDAG can use to match the resulting
reduction message. To set the tag on a reduction message, the
contributors can pass an additional integer argument at the end of the
{\tt contribute()} call.

\section{Defining a New Reduction Type}

\label{new_type_reduction}

It is possible to define a new type of reduction, performing a 
user-defined operation on user-defined data.  This is done by 
creating a {\em reduction function}, which 
combines separate contributions 
into a single combined value.

The input to a reduction function is a list of \kw{CkReductionMsg}s.
A \kw{CkReductionMsg} is a thin wrapper around a buffer of untyped data
to be reduced.  
The output of a reduction function is a single CkReductionMsg
containing the reduced data, which you should create using the
\kw{CkReductionMsg::buildNew(int nBytes,const void *data)} method.  

Thus every reduction function has the prototype:
\begin{alltt}
CkReductionMsg *\uw{reductionFn}(int nMsg,CkReductionMsg **msgs);
\end{alltt}

For example, a reduction function to add up contributions 
consisting of two machine {\tt short int}s would be:

\begin{alltt}
CkReductionMsg *sumTwoShorts(int nMsg,CkReductionMsg **msgs)
\{
  //Sum starts off at zero
  short ret[2]={0,0};
  for (int i=0;i<nMsg;i++) \{
    //Sanity check:
    CkAssert(msgs[i]->getSize()==2*sizeof(short));
    //Extract this message's data
    short *m=(short *)msgs[i]->getData();
    ret[0]+=m[0];
    ret[1]+=m[1];
  \}
  return CkReductionMsg::buildNew(2*sizeof(short),ret);
\}
\end{alltt}

The reduction function must be registered with \charmpp{} 
using \kw{CkReduction::addReducer} from
an \kw{initnode} routine (see section~\ref{initnode} for details
on the \kw{initnode} mechanism).   \kw{CkReduction::addReducer}
returns a \kw{CkReduction::reducerType} which you can later 
pass to \kw{contribute}.  Since \kw{initnode} routines are executed
once on every node, you can safely store the \kw{CkReduction::reducerType}
in a global or class-static variable.  For the example above, the reduction
function is registered and used in the following manner:

\begin{alltt}
//In the .ci file:
  initnode void registerSumTwoShorts(void);

//In some .C file:
/*global*/ CkReduction::reducerType sumTwoShortsType;
/*initnode*/ void registerSumTwoShorts(void)
\{
  sumTwoShortsType=CkReduction::addReducer(sumTwoShorts);
\}

//In some member function, contribute data to the customized reduction:
  short data[2]=...;
  contribute(2*sizeof(short),data,sumTwoShortsType);
\end{alltt}
Note that typed reductions briefed in Section~\ref{reductions}
can also be used for custom reductions. The target reduction client 
can be declared as in Section~\ref{reductions} but the reduction functions
will be defined as explained above.\\
Note that you cannot call \kw{CkReduction::addReducer}
from anywhere but an \kw{initnode} routine.\\
(See \examplerefdir{barnes-charm} for a complete example).

