*** empty log message ***
[charm.git] / src / ck-com / BroadcastStrategy.C
1 //Broadcast strategy for charm++ programs using the net version
2 //This stategy will wonly work for groups.
3 //This strategy implements a tree based broadcast
4 //I will extent it for arrays later.
5 //Developed by Sameer Kumar 04/10/04
6
7 #include "BroadcastStrategy.h"
8
9 CkpvExtern(CkGroupID, cmgrID);
10 extern int sfactor;
11
12 static void recv_bcast_handler(void *msg) {
13     int instid = CmiGetXHandler(msg);
14     BroadcastStrategy *bstrat = (BroadcastStrategy *)
15         CProxy_ComlibManager(CkpvAccess(cmgrID)).ckLocalBranch()->getStrategy(instid);
16     
17     bstrat->handleMessage((char *)msg);    
18 }
19
20 //Constructor, 
21 //Can read spanning factor from command line
22 BroadcastStrategy::BroadcastStrategy(int topology) : 
23     CharmStrategy(), _topology(topology) {
24     spanning_factor = DEFAULT_BROADCAST_SPANNING_FACTOR;
25     if(sfactor > 0)
26         spanning_factor = sfactor;
27     
28 }
29
30
31 //Receives the message and sends it along the spanning tree.
32 void BroadcastStrategy::insertMessage(CharmMessageHolder *cmsg){
33     CkPrintf("[%d] BROADCASTING\n", CkMyPe());
34
35     char *msg = cmsg->getCharmMessage();
36     if(_topology == USE_HYPERCUBE) {
37         envelope *env = UsrToEnv(msg);
38         env->setSrcPe(0);    
39     }
40     handleMessage((char *)UsrToEnv(msg));
41     
42     delete cmsg;
43 }
44
45 //not implemented here because no bracketing is required for this strategy
46 void BroadcastStrategy::doneInserting(){
47 }
48
49
50 //register the converse handler to recieve the broadcast message
51 void BroadcastStrategy::beginProcessing(int nelements) {
52     handlerId = CkRegisterHandler((CmiHandler)recv_bcast_handler);
53 }
54
55 void BroadcastStrategy::handleMessage(char *msg) {
56     if(_topology == USE_TREE)
57         handleTree(msg);
58     else if(_topology == USE_HYPERCUBE) 
59         handleHypercube(msg);
60     else CkAbort("Unknown Topology");
61 }
62
63 void BroadcastStrategy::handleTree(char *msg){
64     
65     envelope *env = (envelope *)msg;
66     int startpe = env->getSrcPe();
67     int size = env->getTotalsize();
68     
69     CkAssert(startpe>=0 && startpe < CkNumPes());
70     
71     CmiSetHandler(msg, handlerId);
72     CmiSetXHandler(msg, getInstance());    
73     
74     //Sending along the spanning tree
75     //Gengbins tree building code stolen from the MPI machine layer    
76     int i;
77     for (i=1; i<=spanning_factor; i++) {
78         
79         int p = CkMyPe() - startpe;
80         if (p<0) 
81             p += CkNumPes();
82
83         p = spanning_factor*p + i;
84
85         if (p > CkNumPes() - 1) break;
86
87         p += startpe;
88         p = p % CkNumPes();
89
90         CkAssert(p>=0 && p < CkNumPes() && p != CkMyPe());
91
92         CmiSyncSend(p, size, msg);
93     }
94
95     CkSendMsgBranch(env->getEpIdx(), EnvToUsr(env), CkMyPe(), 
96                     env->getGroupNum());
97 }
98
99
100 void BroadcastStrategy::handleHypercube(char *msg){
101     envelope *env = (envelope *)msg;
102     int curcycle = env->getSrcPe();
103     int i;
104     int size = env->getTotalsize();
105     
106     double logp = CkNumPes();
107     logp = log(logp)/log(2.0);
108     logp = ceil(logp);
109     
110     //CkPrintf("In hypercube %d, %d\n", (int)logp, curcycle); 
111     
112     /* assert(startpe>=0 && startpe<_Cmi_numpes); */
113     CmiSetHandler(msg, handlerId);
114     CmiSetXHandler(msg, getInstance());    
115
116     for (i = logp - curcycle - 1; i >= 0; i--) {
117         int p = CkMyPe() ^ (1 << i);
118
119         int newcycle = ++curcycle;
120         //CkPrintf("%d --> %d, %d\n", CkMyPe(), p, newcycle); 
121
122         env->setSrcPe(newcycle);
123         if(p < CkNumPes()) {
124             CmiSyncSendFn(p, size, msg);
125         }
126     }
127
128     CkSendMsgBranch(env->getEpIdx(), EnvToUsr(env), CkMyPe(), 
129                     env->getGroupNum());
130 }
131
132
133 //Pack the group id and the entry point of the user message
134 void BroadcastStrategy::pup(PUP::er &p){
135     Strategy::pup(p);    
136     p | spanning_factor;
137     p | _topology;
138 }