Changing CharmStrategy and DirectMulticastStrategy to use the strategy_handler
[charm.git] / src / ck-com / BroadcastStrategy.C
1
2 //Broadcast strategy for charm++ programs using the net version
3 //This strategy implements a tree based broadcast
4 //Developed by Sameer Kumar 04/10/04
5
6 //Extend for array sections later
7
8 #include "BroadcastStrategy.h"
9 #include "ComlibManager.h"
10
11 CkpvExtern(CkGroupID, cmgrID);
12 extern int sfactor;
13
14 static void recv_bcast_handler(void *msg) {
15     CmiMsgHeaderExt *conv_header = (CmiMsgHeaderExt *) msg;
16     int instid = conv_header->stratid;
17
18     BroadcastStrategy *bstrat = (BroadcastStrategy *)
19         CProxy_ComlibManager(CkpvAccess(cmgrID)).ckLocalBranch()->getStrategy(instid);
20     
21     bstrat->handleMessage((char *)msg);    
22 }
23
24
25 //Initialize the hypercube variables
26 void BroadcastStrategy::initHypercube() {
27     logp = log((double) CkNumPes())/log(2.0);
28     logp = ceil(logp);
29 }
30
31
32 //Constructor, 
33 //Can read spanning factor from command line
34 BroadcastStrategy::BroadcastStrategy(int topology) : 
35     CharmStrategy(), _topology(topology) {
36     spanning_factor = DEFAULT_BROADCAST_SPANNING_FACTOR;
37     if(sfactor > 0)
38         spanning_factor = sfactor;
39     
40     setType(GROUP_STRATEGY);
41     initHypercube();
42 }
43
44 //Array Constructor
45 //Can read spanning factor from command line
46 BroadcastStrategy::BroadcastStrategy(CkArrayID aid, int topology) : 
47     CharmStrategy(), _topology(topology) {
48         
49     setType(ARRAY_STRATEGY);
50     ainfo.setDestinationArray(aid);
51     
52     spanning_factor = DEFAULT_BROADCAST_SPANNING_FACTOR;
53     if(sfactor > 0)
54         spanning_factor = sfactor;    
55
56     initHypercube();
57     //if(topology == USE_HYPERCUBE)
58     //  CkPrintf("Warning: hypercube only works on powers of two PES\n");
59 }
60
61
62 //Receives the message and sends it along the spanning tree.
63 void BroadcastStrategy::insertMessage(CharmMessageHolder *cmsg){
64     //CkPrintf("[%d] BROADCASTING\n", CkMyPe());
65
66     char *msg = cmsg->getCharmMessage();
67
68     envelope *env = UsrToEnv(msg);
69     CmiMsgHeaderExt *conv_header = (CmiMsgHeaderExt *) env;
70
71     conv_header->root = 0;        //Use root later
72     if(_topology == USE_HYPERCUBE) 
73         conv_header->xhdl = 0;
74     else
75         //conv_header->root = CkMyPe();
76         conv_header->xhdl = CkMyPe();
77     
78     CkPackMessage(&env);
79     handleMessage((char *) env);
80     
81     delete cmsg;
82 }
83
84 //not implemented here because no bracketing is required for this strategy
85 void BroadcastStrategy::doneInserting(){
86 }
87
88
89 //register the converse handler to recieve the broadcast message
90 void BroadcastStrategy::beginProcessing(int nelements) {
91     handlerId = CkRegisterHandler((CmiHandler)recv_bcast_handler);
92 }
93
94 void BroadcastStrategy::handleMessage(char *msg) {
95     if(_topology == USE_TREE)
96         handleTree(msg);
97     else if(_topology == USE_HYPERCUBE) 
98         handleHypercube(msg);
99     else CkAbort("Unknown Topology");
100 }
101
102 void BroadcastStrategy::handleTree(char *msg){
103     
104     envelope *env = (envelope *)msg;
105     CmiMsgHeaderExt *conv_header = (CmiMsgHeaderExt *) msg;
106
107     int startpe = conv_header->xhdl;
108     int size = env->getTotalsize();
109     
110     CkAssert(startpe>=0 && startpe < CkNumPes());
111     
112     CmiSetHandler(msg, handlerId);
113     
114     conv_header->stratid = getInstance();
115     
116     //Sending along the spanning tree
117     //Gengbins tree building code stolen from the MPI machine layer    
118     int i;
119     for (i=1; i<=spanning_factor; i++) {
120         
121         int p = CkMyPe() - startpe;
122         if (p<0) 
123             p += CkNumPes();
124
125         p = spanning_factor*p + i;
126
127         if (p > CkNumPes() - 1) break;
128
129         p += startpe;
130         p = p % CkNumPes();
131
132         CkAssert(p>=0 && p < CkNumPes() && p != CkMyPe());
133
134         CmiSyncSend(p, size, msg);
135     }
136
137     if(getType() == GROUP_STRATEGY)
138         CkSendMsgBranch(env->getEpIdx(), EnvToUsr(env), CkMyPe(), 
139                         env->getGroupNum());
140     else if(getType() == ARRAY_STRATEGY)
141         ainfo.localBroadcast(env);        
142 }
143
144
145 void BroadcastStrategy::handleHypercube(char *msg){
146     envelope *env = (envelope *)msg;
147
148     CmiMsgHeaderExt *conv_header = (CmiMsgHeaderExt *) msg;
149     //int curcycle = conv_header->root;
150     int curcycle = conv_header->xhdl;
151
152     int i;
153     int size = env->getTotalsize();
154         
155     //CkPrintf("In hypercube %d, %d\n", (int)logp, curcycle); 
156     
157     /* assert(startpe>=0 && startpe<_Cmi_numpes); */
158     CmiSetHandler(msg, handlerId);
159
160     conv_header->stratid = getInstance();
161
162     //Copied from system hypercube message passing
163
164     for (i = logp - curcycle - 1; i >= 0; i--) {
165         int p = CkMyPe() ^ (1 << i);
166
167         int newcycle = ++curcycle;
168         //CkPrintf("%d --> %d, %d\n", CkMyPe(), p, newcycle); 
169         
170         //conv_header->root = newcycle;
171         conv_header->xhdl = newcycle;
172
173         if(p >= CkNumPes()) {
174             p &= (-1) << i;
175             
176             //loadbalancing
177             if (p < CkNumPes())
178                 p += (CkMyPe() - 
179                       (CkMyPe() & ((-1) << i))) % (CkNumPes() - p);
180         }     
181         
182         if(p < CkNumPes())
183             CmiSyncSendFn(p, size, msg);                    
184     }
185     
186     if(getType() == GROUP_STRATEGY)
187         CkSendMsgBranch(env->getEpIdx(), EnvToUsr(env), CkMyPe(), 
188                         env->getGroupNum());
189     else if(getType() == ARRAY_STRATEGY)
190         ainfo.localBroadcast(env);        
191 }
192
193
194 //Pack the group id and the entry point of the user message
195 void BroadcastStrategy::pup(PUP::er &p){
196     CharmStrategy::pup(p);    
197
198     p | spanning_factor;
199     p | _topology;
200     p | logp;
201 }