Removing assert statement that caused strategies only to work with 1d chare arrays.
[charm.git] / src / ck-com / BroadcastStrategy.C
1 /**
2    @addtogroup ComlibCharmStrategy
3    @{
4    @file
5 */
6
7 #include "BroadcastStrategy.h"
8 //#include "ComlibManager.h"
9
10 CkpvExtern(CkGroupID, cmgrID);
11 extern int sfactor;
12
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     Strategy(), 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     Strategy(), CharmStrategy(), _topology(topology) {
48         
49         CkAbort("BroadcastStrategy currently works only for groups");
50     setType(ARRAY_STRATEGY);
51     ainfo.setDestinationArray(aid);
52     
53     spanning_factor = DEFAULT_BROADCAST_SPANNING_FACTOR;
54     if(sfactor > 0)
55         spanning_factor = sfactor;    
56
57     initHypercube();
58     //if(topology == USE_HYPERCUBE)
59     //  CkPrintf("Warning: hypercube only works on powers of two PES\n");
60 }
61
62
63 //Receives the message and sends it along the spanning tree.
64 void BroadcastStrategy::insertMessage(CharmMessageHolder *cmsg){
65     //CkPrintf("[%d] BROADCASTING\n", CkMyPe());
66
67     char *msg = cmsg->getCharmMessage();
68
69     envelope *env = UsrToEnv(msg);
70     CmiMsgHeaderExt *conv_header = (CmiMsgHeaderExt *) env;
71
72     conv_header->root = 0;        //Use root later
73     if(_topology == USE_HYPERCUBE) 
74         conv_header->xhdl = 0;
75     else
76         //conv_header->root = CkMyPe();
77         conv_header->xhdl = CkMyPe();
78     
79     CkPackMessage(&env);
80     handleMessage((char *) env);
81     
82     delete cmsg;
83 }
84
85 //not implemented here because no bracketing is required for this strategy
86 //void BroadcastStrategy::doneInserting(){
87 //}
88
89 /*
90 //register the converse handler to recieve the broadcast message
91 void BroadcastStrategy::beginProcessing(int nelements) {
92     handlerId = CkRegisterHandler((CmiHandler)recv_bcast_handler);
93 }
94 */
95
96 void BroadcastStrategy::handleMessage(void *msg) {
97     if(_topology == USE_TREE)
98         handleTree(msg);
99     else if(_topology == USE_HYPERCUBE) 
100         handleHypercube(msg);
101     else CkAbort("Unknown Topology");
102 }
103
104 void BroadcastStrategy::handleTree(void *msg){
105     
106     envelope *env = (envelope *)msg;
107     CmiMsgHeaderExt *conv_header = (CmiMsgHeaderExt *) msg;
108
109     int startpe = conv_header->xhdl;
110     int size = env->getTotalsize();
111     
112     CkAssert(startpe>=0 && startpe < CkNumPes());
113     
114     CmiSetHandler(msg, CkpvAccess(comlib_handler));
115     
116     conv_header->stratid = getInstance();
117     
118     //Sending along the spanning tree
119     //Gengbins tree building code stolen from the MPI machine layer    
120     int i;
121     for (i=1; i<=spanning_factor; i++) {
122         
123         int p = CkMyPe() - startpe;
124         if (p<0) 
125             p += CkNumPes();
126
127         p = spanning_factor*p + i;
128
129         if (p > CkNumPes() - 1) break;
130
131         p += startpe;
132         p = p % CkNumPes();
133
134         CkAssert(p>=0 && p < CkNumPes() && p != CkMyPe());
135
136         CmiSyncSend(p, size, (char*)msg);
137     }
138
139     if(getType() == GROUP_STRATEGY) {
140       ComlibPrintf("BroadcastStrategy: delivering message\n");
141         CkSendMsgBranch(env->getEpIdx(), EnvToUsr(env), CkMyPe(), 
142                         env->getGroupNum());
143     }
144     else if(getType() == ARRAY_STRATEGY)
145         ainfo.localBroadcast(env);        
146 }
147
148
149 void BroadcastStrategy::handleHypercube(void *msg){
150     envelope *env = (envelope *)msg;
151
152     CmiMsgHeaderExt *conv_header = (CmiMsgHeaderExt *) msg;
153     //int curcycle = conv_header->root;
154     int curcycle = conv_header->xhdl;
155
156     int i;
157     int size = env->getTotalsize();
158         
159     //CkPrintf("In hypercube %d, %d\n", (int)logp, curcycle); 
160     
161     /* assert(startpe>=0 && startpe<_Cmi_numpes); */
162     CmiSetHandler(msg, CkpvAccess(comlib_handler));
163
164     conv_header->stratid = getInstance();
165
166     //Copied from system hypercube message passing
167
168     for (i = logp - curcycle - 1; i >= 0; i--) {
169         int p = CkMyPe() ^ (1 << i);
170
171         int newcycle = ++curcycle;
172         //CkPrintf("%d --> %d, %d\n", CkMyPe(), p, newcycle); 
173         
174         //conv_header->root = newcycle;
175         conv_header->xhdl = newcycle;
176
177         if(p >= CkNumPes()) {
178             p &= (-1) << i;
179             
180             //loadbalancing
181             if (p < CkNumPes())
182                 p += (CkMyPe() - 
183                       (CkMyPe() & ((-1) << i))) % (CkNumPes() - p);
184         }     
185         
186         if(p < CkNumPes())
187             CmiSyncSendFn(p, size, (char*)msg);                    
188     }
189     
190     if(getType() == GROUP_STRATEGY) {
191       ComlibPrintf("BroadcastStrategy: delivering message\n");
192         CkSendMsgBranch(env->getEpIdx(), EnvToUsr(env), CkMyPe(), 
193                         env->getGroupNum());
194     }
195     else if(getType() == ARRAY_STRATEGY)
196         ainfo.localBroadcast(env);        
197 }
198
199
200 //Pack the group id and the entry point of the user message
201 void BroadcastStrategy::pup(PUP::er &p){
202     Strategy::pup(p);
203     CharmStrategy::pup(p);    
204
205     p | spanning_factor;
206     p | _topology;
207     p | logp;
208 }
209
210 /*@}*/