Added the converse-master-slave section.
[charm.git] / doc / convext / cms.tex
1 \chapter{\converse{} Master-Slave Library}
2
3 \section{Introduction}
4
5 CMS is the implementation of the master-slave (or manager-worker or
6 agenda) parallel programming paradigm on top of \converse{}.
7
8 \section{Available Functions}
9
10 Following functions are available in this library:
11
12 \function{typedef int (*CmsWorkerFn) (void *, void *);}
13 \desc{Prototype for the worker function. See below.}
14
15 \function{typedef int (*CmsConsumerFn) (void *, int);}
16 \desc{Prototype for the consumer function. See below.}
17
18 \function{void CmsInit(CmsWorkerFn worker, int max); }
19 \desc{
20   This function must be called before firing any tasks for the workers.
21   \uw{max} is the largest possible number of tasks you will fire
22   before calling either \kw{CmsAwaitResponses} or \kw{CmsProcessResponses}
23   next. (So the system know how many it may have to buffer).
24 }
25
26 \function{int worker(void *t, void **r)}
27 \desc{
28   The user writes this function. Its name does not have to be 
29   \uw{worker}; It can be anything. \uw{worker} can be any function
30   that the use writes to perform the task on the slave
31   processors. It must allocate and compute the response 
32   data structure, and return a pointer to it, by assigning to \uw{r};
33   It must also return the size of the response data structure as
34   its return value.
35 }
36
37 \function{void CmsFireTask(int ref, void * t, int size)}
38 \desc{
39   Creates task to be worked on by a worker. The task description
40   is pointed to by \uw{t}, and goes on for \uw{size} bytes. \uw{ref} 
41   must be a unique serial number between 0 and \uw{max} (see \kw{CmsInit}).
42 }
43
44 \function{void CmsAwaitResponses(void); }
45 \desc{  
46   This call allows the system to use processor 0 as a worker. It
47   returns after all the tasks have sent back their responses. The
48   responses themselves can be extracted using \kw{CmsGetResponse}.
49 }
50
51 \function{void *CmsGetResponse(int ref);}
52 \desc{
53   Extracts the response associated with the reference number \uw{ref}
54   from the system's buffers.
55 }
56
57 \function{void CmsProcessResponses(CmsConsumerFn consumer);}
58 \desc{
59   Instead of using \kw{CmsAwaitResponses}/\kw{CmsGetResponse} pair, 
60   you can use this call alone. It turns the control over to the CMS system
61   on processor 0, so it can be used as a worker. As soon as a
62   response is available on processor 0, cms calls the user
63   specified \uw{consumer} function with two parameters: the
64   response (a void *) and an integer \uw{refnum}. 
65   (Question:\experimental{} should the size of the response be passed as a
66   parameter to the consumer? User can do that as an explicit
67   field of the response themselves, if necessary.)
68 }
69
70 \function{void CmsExit(void);}
71 \desc{
72   Must be called on all processors to terminate execution.
73 }
74
75 Once either \kw{CmsProcessResponses} or \kw{CmsAwaitResponses} returns, you may
76 fire the next batch of tasks via \kw{CmsFireTask} again.
77
78 \section{Example Program}
79
80 \begin{alltt}
81 #include "cms.h"
82
83 #define MAX 10
84
85 typedef struct \{
86     float a;
87 \} Task;
88
89 typedef struct \{
90     float result;
91 \} Response;
92
93 Task t;
94
95 int worker(Task *t, Response **r)
96 \{
97     /* do work and generate a single response */
98     int i;
99     Task *t1;
100     int k;
101
102     CmiPrintf("%d: in worker %f \verb+\n+", CmiMyPe(), t->a);
103     *r = (Response *) malloc(sizeof(Response));
104     (*r)->result = t->a * t->a;
105     return sizeof(r);
106 \}
107
108 int consumer(Response * r, int refnum)
109 \{
110     CmiPrintf("consumer: response with refnum = %d is %f\verb+\n+", refnum,
111               r->result);
112 \}
113
114 main(int argc, char *argv[])
115 \{
116     int i, j, k, ref;
117     /* 2nd parameter is the max number of tasks 
118      * fired before "awaitResponses"
119      */
120     CmsInit((CmsWorkerFn)worker, 20);
121     if (CmiMyPe() == 0) \{ /* I am the manager */
122         CmiPrintf("manager inited\verb+\n+");
123         for (i = 0; i < 3; i++) \{ /* number of iterations or phases */
124           /* prepare the next generation of problems to solve */
125           /* then, fire the next batch of tasks for the worker */
126             for (j = 0; j < 5; j++) \{
127                 t.a = 10 * i + j;
128                 ref = j;  /* a ref number to associate with the task, */
129                 /* so that the reponse for this task can be identified. */
130                 CmsFireTask(ref, \&t, sizeof(t));
131             \}
132           /* Now wait for the responses */
133             CmsAwaitResponses();  /* allows proc 0 to be used as a worker. */
134             /* Now extract the resoneses from the system */
135             for (j = 0; j < 5; j++) \{
136                 Response *r = (Response *) CmsGetResponse(j);
137                 CmiPrintf("Response %d is: %f \verb+\n+", j, r->result);
138             \}
139           /* End of one mast-slave phase */
140             CmiPrintf("End of phase %d\verb+\n+", i);
141         \}
142     \}
143
144     CmiPrintf("Now the consumerFunction mode\verb+\n+");
145
146     if (CmiMyPe() == 0) \{ /* I am the manager */
147        for (i = 0; i < 3; i++) \{
148            t.a = 5 + i;
149            CmsFireTask(i, \&t, sizeof(t));
150        \}
151        CmsProcessResponses((CmsConsumerFn)consumer);
152        /* Also allows proc. 0 to be used as a worker. 
153         * In addition, responses will be processed on processor 0 
154         * via the "consumer" function as soon as they are available 
155         */
156     \}
157     CmsExit();
158 \}
159 \end{alltt}