Merge branch 'charm' of charmgit:charm into charm
[charm.git] / src / ck-com / ChunkMulticastStrategy.h
1 /**
2    @addtogroup ComlibCharmStrategy
3    @{
4    
5    @file 
6  
7 */
8
9 #ifndef CHUNK_MULTICAST_STRATEGY
10 #define CHUNK_MULTICAST_STRATEGY
11
12 #include "ComlibManager.h"
13 #include "ComlibSectionInfo.h"
14 #include <list>
15
16 /*class blkMsg1 {
17 public:
18   double *data;
19 };*/
20
21 struct ChunkInfo {
22   //int bcastPe;     ///< pe who is doing the broadcast, used for the hash key
23   int chunkNumber;   ///< which chunk is this inside the whole message
24   int chunkSize;     ///< it is the size of the data part of the message (without the converse header)
25   int numChunks;   ///< total number of chunks to arrive
26   //int messageSize;   ///< the entire message size, all included 
27   int idx;           ///< keeps track of the number of messages sent from this pe
28   int srcPe;       ///< pe from whom I'm receiving the message
29 };
30
31
32
33 /**
34    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.  
35
36    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.
37
38 @fixme Fix projections logging for the non [nokeep] version
39
40    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.
41
42    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, ChunkRingMulticastStrategy forwards the multicast messages in a ring while ChunkTreeMulticastStrategy forwards messages along a tree of specified degree. In the future, topology aware (both network and core/cpu/node) strategies should be added.
43
44    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.
45    
46    To create a new strategy:
47    <ul>
48    <li>Add a class declaration similar to the ones below, making sure they inherit from ChunkMulticastStrategy. 
49    <li>Add a PUPable entry in ComlibManager.ci 
50    <li>Implement determineNextHopPEs in ChunkMulticastStrategy.C. See information for ChunkMulticastStrategy::determineNextHopPEs .
51    </ul>
52
53 @todo  Buffer messages until strategy is fully enabled. The current version might have some startup issues if the multicast is used too early.
54
55 @todo  Implement topology aware subclasses. 
56
57 */
58
59 struct recvBuffer {
60   int numChunks;
61   envelope** recvChunks;
62   int nrecv;
63   int srcPe;
64   int idx;
65 };
66
67 class ChunkMulticastStrategy: public Strategy, public CharmStrategy {
68  private:
69   
70   ComlibSectionInfo sinfo; // This is used to create the multicast messages themselves
71
72   void remoteMulticast(ComlibMulticastMsg * multMsg, bool rootPE, int chunkNumber, int numChunks);
73   void localMulticast(CharmMessageHolder *cmsg);
74   
75  public:
76
77   //int numChunks;
78   //int nrecv;
79   std::list< recvBuffer* > recvList;
80   int sentCount;
81
82   /** 
83       Determine the set of PEs to which the message should be forwarded from this PE.
84       Fill in pelist and npes to which the multicast message will be forwarded from this PE.
85
86       @param [in] totalDestPEs The number of destination PEs to whom the message needs to be sent. This will always be > 0.
87       @param [in] destPEs The list of PEs that eventually will be sent the message.
88       @param [in] myIndex The index into destPEs for this PE.
89
90       @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.
91       @param [out] npes The size of pelist
92
93   */
94   virtual void determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, int * &pelist, int &npes, int chunkNumber, int numChunks);
95
96     ChunkMulticastStrategy(CkMigrateMessage *m): Strategy(m), CharmStrategy(m){}
97   
98   ChunkMulticastStrategy();
99   ~ChunkMulticastStrategy();
100   
101   void insertMessage(MessageHolder *msg) {insertMessage((CharmMessageHolder*)msg);}
102   void insertMessage(CharmMessageHolder *msg);
103   
104   ///Called by the converse handler function
105   void handleMessage(void *msg);    
106
107   void pup(PUP::er &p);
108
109   PUPable_decl(ChunkMulticastStrategy);
110
111 };
112
113
114
115
116
117 /**
118    A strategy that sends along a ring through the destination processors.
119 */
120 class ChunkRingMulticastStrategy: public ChunkMulticastStrategy {
121   
122  public:
123   void determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, int * &pelist, int &npes, int chunkNumber, int numChunks );
124
125  ChunkRingMulticastStrategy(CkMigrateMessage *m): ChunkMulticastStrategy(m) {}
126  ChunkRingMulticastStrategy(): ChunkMulticastStrategy() {}
127   ~ChunkRingMulticastStrategy() {}
128   
129   void pup(PUP::er &p){ ChunkMulticastStrategy::pup(p); }
130   
131   PUPable_decl(ChunkRingMulticastStrategy);
132
133 };
134
135
136
137 /**
138    A strategy that sends along a tree with user specified branching factor.
139 */
140 class ChunkTreeMulticastStrategy: public ChunkMulticastStrategy {
141  private:
142   int degree;
143   
144  public:
145   
146   void determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, int * &pelist, int &npes, int chunkNumber, int numChunks );
147   
148  ChunkTreeMulticastStrategy(CkMigrateMessage *m): ChunkMulticastStrategy(m) {}
149
150  ChunkTreeMulticastStrategy(int treeDegree=4): ChunkMulticastStrategy(), degree(treeDegree) {}
151
152   ~ChunkTreeMulticastStrategy() {}
153   
154   void pup(PUP::er &p){ 
155     ChunkMulticastStrategy::pup(p); 
156     p | degree;
157   }
158   
159   PUPable_decl(ChunkTreeMulticastStrategy);
160 };
161
162
163 /**
164    A strategy that sends along a tree with user specified branching factor.
165 */
166 class ChunkPipeTreeMulticastStrategy: public ChunkMulticastStrategy {
167  private:
168   int degree;
169   
170  public:
171   
172   void determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, int * &pelist, int &npes, int chunkNumber, int numChunks );
173   
174  ChunkPipeTreeMulticastStrategy(CkMigrateMessage *m): ChunkMulticastStrategy(m) {}
175
176  ChunkPipeTreeMulticastStrategy(int treeDegree=4): ChunkMulticastStrategy(), degree(treeDegree) {}
177
178   ~ChunkPipeTreeMulticastStrategy() {}
179   
180   void pup(PUP::er &p){ 
181     ChunkMulticastStrategy::pup(p); 
182     p | degree;
183   }
184   
185   PUPable_decl(ChunkPipeTreeMulticastStrategy);
186 };
187
188
189
190
191
192
193
194 /**
195    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.
196 */
197 /*class ChunkNodeTreeMulticastStrategy: public ChunkMulticastStrategy {
198  private:
199   int degree;
200   
201  public:
202   
203   void determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, int * &pelist, int &npes );
204   
205  ChunkNodeTreeMulticastStrategy(CkMigrateMessage *m): ChunkMulticastStrategy(m) {}
206   
207  ChunkNodeTreeMulticastStrategy(int treeDegree=4): ChunkMulticastStrategy(), degree(treeDegree) {}
208   
209   ~ChunkNodeTreeMulticastStrategy() {}
210   
211   void pup(PUP::er &p){ 
212     ChunkMulticastStrategy::pup(p); 
213     p | degree;
214   }
215   
216   PUPable_decl(ChunkNodeTreeMulticastStrategy);
217 };*/
218
219
220
221 /**
222    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.
223 */
224 /*class ChunkNodeTreeRingMulticastStrategy: public ChunkMulticastStrategy {
225  private:
226   int degree;
227   
228  public:
229   
230   void determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, int * &pelist, int &npes );
231   
232  ChunkNodeTreeRingMulticastStrategy(CkMigrateMessage *m): ChunkMulticastStrategy(m) {}
233   
234  ChunkNodeTreeRingMulticastStrategy(int treeDegree=4): ChunkMulticastStrategy(), degree(treeDegree) {}
235   
236   ~ChunkNodeTreeRingMulticastStrategy() {}
237   
238   void pup(PUP::er &p){ 
239     ChunkMulticastStrategy::pup(p); 
240     p | degree;
241   }
242   
243   PUPable_decl(ChunkNodeTreeRingMulticastStrategy);
244 };*/
245
246
247
248
249
250 #endif
251
252 /*@}*/