Merge nodehelper lib and example codes into charm
[charm.git] / src / ck-com / OneTimeMulticastStrategy.h
1 /**
2    @addtogroup ComlibCharmStrategy
3    @{
4    
5    @file 
6  
7 */
8
9 #ifndef ONE_TIME_MULTICAST_STRATEGY
10 #define ONE_TIME_MULTICAST_STRATEGY
11
12 #include "ComlibManager.h"
13 #include "ComlibSectionInfo.h"
14
15 /**
16    The simplest multicast strategy. This strategy extracts the array section information, and packs the section information and the user message into a single message. The original message is delivered locally, and the new message is sent using CmiSyncListSendAndFree to all other processors containing destination objects. If the destination entry method is [nokeep], then the multicast is delivered inline without extra copies to the local destination elements. If the destination is not [nokeep], then the message is delivered through the scheduler queue.  
17
18    Projections can trace the messages for the [nokeep] destinations, but the sending entry method will end prematurely because inline calling of local entry methods is not fully supported by Projections. Messages multicast to non [nokeep] methods are displayed incorrectly, probably because the call to deliver overwrites the source pe & event.
19
20 @fixme Fix projections logging for the non [nokeep] version
21
22    This strategy is simpler than those which are derived from the MulticastStrategy class because those maintain a persistant record of previous array section information extracted from the messages, and those provide multiple implementations of the multicast tree (such as ring or multiring or all to all). Those strategies ought to be used when multiple multicasts are sent to the same array section. If an array section is not reused, then this strategy ought to be used.
23
24    A class can be created which inherits from this class, but provides its own determineNextHopPEs method to specify any type of desired spanning tree. For example, OneTimeRingMulticastStrategy forwards the multicast messages in a ring while OneTimeTreeMulticastStrategy forwards messages along a tree of specified degree. In the future, topology aware (both network and core/cpu/node) strategies should be added.
25
26    The local messages are delivered through the array manager using the CharmStrategy::deliverToIndices methods. If a destination chare is remote, the array manager will forward it on to the pe that contains the chare.
27    
28    To create a new strategy:
29    <ul>
30    <li>Add a class declaration similar to the ones below, making sure they inherit from OneTimeMulticastStrategy. 
31    <li>Add a PUPable entry in ComlibManager.ci 
32    <li>Implement determineNextHopPEs in OneTimeMulticastStrategy.C. See information for OneTimeMulticastStrategy::determineNextHopPEs .
33    </ul>
34
35 @todo  Buffer messages until strategy is fully enabled. The current version might have some startup issues if the multicast is used too early.
36
37 @todo  Implement topology aware subclasses. 
38
39 */
40 class OneTimeMulticastStrategy: public Strategy, public CharmStrategy {
41  private:
42   
43   ComlibSectionInfo sinfo; // This is used to create the multicast messages themselves
44
45   void remoteMulticast(ComlibMulticastMsg * multMsg, bool rootPE);
46   void localMulticast(CharmMessageHolder *cmsg);
47   
48  public:
49
50   /** 
51       Determine the set of PEs to which the message should be forwarded from this PE.
52       Fill in pelist and npes to which the multicast message will be forwarded from this PE.
53
54       @param [in] totalDestPEs The number of destination PEs to whom the message needs to be sent. This will always be > 0.
55       @param [in] destPEs The list of PEs that eventually will be sent the message.
56       @param [in] myIndex The index into destPEs for this PE.
57       @param [in] rootPE The PE that created the multicast (is not listed in destPEs).
58       
59       @param [out] pelist A list of PEs to which the message will be sent after this function returns. This function allocates the array with new. The caller will free it with delete[] if npes>0.
60       @param [out] npes The size of pelist
61
62   */
63   virtual void determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, const int rootPE , int * &pelist, int &npes);
64
65     OneTimeMulticastStrategy(CkMigrateMessage *m): Strategy(m), CharmStrategy(m){}
66   
67   OneTimeMulticastStrategy();
68   ~OneTimeMulticastStrategy();
69   
70   void insertMessage(MessageHolder *msg) {insertMessage((CharmMessageHolder*)msg);}
71   void insertMessage(CharmMessageHolder *msg);
72   
73   ///Called by the converse handler function
74   void handleMessage(void *msg);    
75
76   void pup(PUP::er &p);
77
78   PUPable_decl(OneTimeMulticastStrategy);
79
80 };
81
82
83
84
85
86 /**
87    A strategy that sends along a ring through the destination processors.
88 */
89 class OneTimeRingMulticastStrategy: public OneTimeMulticastStrategy {
90   
91  public:
92   void determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, const int rootPE , int * &pelist, int &npes);
93
94  OneTimeRingMulticastStrategy(CkMigrateMessage *m): OneTimeMulticastStrategy(m) {}
95  OneTimeRingMulticastStrategy(): OneTimeMulticastStrategy() {}
96   ~OneTimeRingMulticastStrategy() {}
97   
98   void pup(PUP::er &p){ OneTimeMulticastStrategy::pup(p); }
99   
100   PUPable_decl(OneTimeRingMulticastStrategy);
101
102 };
103
104
105
106 /**
107    A strategy that sends along a tree with user specified branching factor.
108 */
109 class OneTimeTreeMulticastStrategy: public OneTimeMulticastStrategy {
110  private:
111   int degree;
112   
113  public:
114   
115   void determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, const int rootPE, int * &pelist, int &npes);
116   
117  OneTimeTreeMulticastStrategy(CkMigrateMessage *m): OneTimeMulticastStrategy(m) {}
118
119   /** Create a strategy with specified branching factor(which defaults to 4) */
120  OneTimeTreeMulticastStrategy(int treeDegree=4): OneTimeMulticastStrategy(), degree(treeDegree) {}
121
122   ~OneTimeTreeMulticastStrategy() {}
123   
124   void pup(PUP::er &p){ 
125     OneTimeMulticastStrategy::pup(p); 
126     p | degree;
127   }
128   
129   PUPable_decl(OneTimeTreeMulticastStrategy);
130 };
131
132
133
134 /**
135  * A strategy that uses the topo-aware spanning tree builder to send msgs down a spanning tree 
136  * that is constructed in a network-topology aware manner if such info is available. Users 
137  * can specify the branching factor for the spanning tree
138  */
139 class OneTimeTopoTreeMulticastStrategy: public OneTimeMulticastStrategy 
140 {
141     private:
142         int degree;
143         
144     public:
145         OneTimeTopoTreeMulticastStrategy(CkMigrateMessage *m): OneTimeMulticastStrategy(m) {}
146         /** Create a strategy with specified branching factor(which defaults to 4) */
147         OneTimeTopoTreeMulticastStrategy(int treeDegree=4): OneTimeMulticastStrategy(), degree(treeDegree) { }
148         ~OneTimeTopoTreeMulticastStrategy() {}
149         /// Determine the direct children of this PE in the spanning tree
150         void determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, const int rootPE, int * &pelist, int &npes);
151         void pup(PUP::er &p)
152         { 
153             OneTimeMulticastStrategy::pup(p);
154             p | degree;
155         }
156         PUPable_decl(OneTimeTopoTreeMulticastStrategy);
157 };
158
159
160
161 /**
162    A strategy that does dimension ordered sending of messages. This may result in lower contention for torus networks than a topology oblivious tree.
163 */
164 class OneTimeDimensionOrderedMulticastStrategy: public OneTimeMulticastStrategy {
165  public:
166   
167   void determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, const int rootPE, int * &pelist, int &npes);
168   
169  OneTimeDimensionOrderedMulticastStrategy(CkMigrateMessage *m): OneTimeMulticastStrategy(m) {}
170
171   /** Create a strategy with specified branching factor(which defaults to 4) */
172  OneTimeDimensionOrderedMulticastStrategy(): OneTimeMulticastStrategy() {}
173
174   ~OneTimeDimensionOrderedMulticastStrategy() {}
175   
176   void pup(PUP::er &p){ 
177     OneTimeMulticastStrategy::pup(p); 
178   }
179   
180   PUPable_decl(OneTimeDimensionOrderedMulticastStrategy);
181  private:
182   int findMinMaxArray(int min, int len, int *array, bool* notincluded, int notIndex);
183 };
184
185
186
187
188 /**
189    A node-aware strategy that sends along a node-based tree with user specified branching factor. Once the message reaches the PE representative for each node, it is forwarded from the PE to all other destination PEs on the node. This strategy can result in imbalanced loads. The PEs along the tree have higher load than the other PEs.
190 */
191 class OneTimeNodeTreeMulticastStrategy: public OneTimeMulticastStrategy {
192  private:
193   int degree;
194   
195  public:
196   
197   void determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, const int rootPE, int * &pelist, int &npes);
198   
199  OneTimeNodeTreeMulticastStrategy(CkMigrateMessage *m): OneTimeMulticastStrategy(m) {}
200   
201   /** Create a strategy with specified branching factor(which defaults to 4) */
202  OneTimeNodeTreeMulticastStrategy(int treeDegree=4): OneTimeMulticastStrategy(), degree(treeDegree) {}
203   
204   ~OneTimeNodeTreeMulticastStrategy() {}
205   
206   void pup(PUP::er &p){ 
207     OneTimeMulticastStrategy::pup(p); 
208     p | degree;
209   }
210   
211   PUPable_decl(OneTimeNodeTreeMulticastStrategy);
212 };
213
214
215
216 /**
217    A node-aware strategy that sends along a node-based tree with user specified branching factor. Once the message arrives at the first PE on the node, it is forwarded to the other PEs on the node through a ring.
218 */
219 class OneTimeNodeTreeRingMulticastStrategy: public OneTimeMulticastStrategy {
220  private:
221   int degree;
222   
223  public:
224   
225   void determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, const int rootPE, int * &pelist, int &npes);
226   
227  OneTimeNodeTreeRingMulticastStrategy(CkMigrateMessage *m): OneTimeMulticastStrategy(m) {}
228   
229   /** Create a strategy with specified branching factor(which defaults to 4) */
230  OneTimeNodeTreeRingMulticastStrategy(int treeDegree=4): OneTimeMulticastStrategy(), degree(treeDegree) {}
231   
232   ~OneTimeNodeTreeRingMulticastStrategy() {}
233   
234   void pup(PUP::er &p){ 
235     OneTimeMulticastStrategy::pup(p); 
236     p | degree;
237   }
238   
239   PUPable_decl(OneTimeNodeTreeRingMulticastStrategy);
240 };
241
242 #endif
243
244 /*@}*/