These changes add GridCommLB from my prelim work into the Charm++ load
[charm.git] / src / ck-ldb / GridCommLB.C
1 /**************************************************************************
2 ** Greg Koenig (koenig@uiuc.edu)
3 ** November 4, 2004
4 */
5 #include <stdio.h>
6
7 #include "charm++.h"
8 #include "cklists.h"
9
10 #include "GridCommLB.decl.h"
11
12 #include "GridCommLB.h"
13 #include "manager.h"
14
15
16 CreateLBFunc_Def (GridCommLB);
17
18
19 /**************************************************************************
20 **
21 */
22 static void lbinit (void)
23 {
24   LBRegisterBalancer ("GridCommLB", 
25                       CreateGridCommLB, 
26                       AllocateGridCommLB, 
27                       "Load balancer for Grid computing environments");
28 }
29
30
31 /**************************************************************************
32 **
33 */
34 GridCommLB::GridCommLB (const CkLBOptions &opt) : CentralLB (opt)
35 {
36     lbname = (char *) "GridCommLB";
37
38     if (CkMyPe () == 0) {
39       CkPrintf ("[%d] GridCommLB created\n", CkMyPe ());
40     }
41
42     manager_init ();
43 }
44
45
46 /**************************************************************************
47 **
48 */
49 GridCommLB::GridCommLB (CkMigrateMessage *m) : CentralLB (m)
50 {
51   lbname = (char *) "GridCommLB";
52
53   manager_init ();
54 }
55
56
57 /**************************************************************************
58 **
59 */
60 CmiBool GridCommLB::QueryBalanceNow (int step)
61 {
62   // CkPrintf ("[%d] Balancing on step %d\n", CkMyPe (), step);
63   return (CmiTrue);
64 }
65
66
67 /**************************************************************************
68 **
69 */
70 int GridCommLB::Get_Cluster (int pe)
71 {
72   if (pe < (Num_PEs / 2)) {
73     return (0);
74   } else {
75     return (1);
76   }
77 }
78
79
80 /**************************************************************************
81 **
82 */
83 int GridCommLB::Find_Maximum_WAN_Object (int cluster)
84 {
85   int i;
86   int max_index;
87   int max_wan_msgs;
88
89
90   max_index    = -1;
91   max_wan_msgs = -1;
92
93   for (i = 0; i < Num_Objects; i++) {
94     if ((&Object_Data[i])->cluster == cluster) {
95       if ((&Object_Data[i])->to_pe == -1) {
96         if ((&Object_Data[i])->num_wan_msgs > max_wan_msgs) {
97           max_index = i;
98           max_wan_msgs = (&Object_Data[i])->num_wan_msgs;
99         }
100       }
101     }
102   }
103
104   return (max_index);
105 }
106
107
108 /**************************************************************************
109 **
110 */
111 int GridCommLB::Find_Minimum_WAN_PE (int cluster)
112 {
113   int i;
114   int min_index;
115   int min_wan_objs;
116   int min_lan_objs;
117
118
119   min_index = -1;
120   min_wan_objs = INT_MAX;
121   min_lan_objs = INT_MAX;
122
123   for (i = 0; i < Num_PEs; i++) {
124     if (((&PE_Data[i])->available) && ((&PE_Data[i])->cluster == cluster)) {
125       if ((&PE_Data[i])->num_wan_objs < min_wan_objs) {
126         min_index = i;
127         min_wan_objs = (&PE_Data[i])->num_wan_objs;
128         min_lan_objs = (&PE_Data[i])->num_lan_objs;
129       } else if ((&PE_Data[i])->num_wan_objs == min_wan_objs) {
130         if ((&PE_Data[i])->num_lan_objs < min_lan_objs) {
131           min_index = i;
132           min_lan_objs = (&PE_Data[i])->num_lan_objs;
133         }
134       }
135     }
136   }
137
138   return (min_index);
139 }
140
141
142 /**************************************************************************
143 **
144 */
145 void GridCommLB::Assign_Object_To_PE (int target_object, int target_pe)
146 {
147   (&Object_Data[target_object])->to_pe = target_pe;
148
149   (&PE_Data[target_pe])->num_objs++;
150
151   if ((&Object_Data[target_object])->num_lan_msgs > 0) {
152     (&PE_Data[target_pe])->num_lan_objs++;
153     (&PE_Data[target_pe])->num_lan_msgs +=
154         (&Object_Data[target_object])->num_lan_msgs;
155   }
156
157   if ((&Object_Data[target_object])->num_wan_msgs > 0) {
158     (&PE_Data[target_pe])->num_wan_objs++;
159     (&PE_Data[target_pe])->num_wan_msgs +=
160         (&Object_Data[target_object])->num_wan_msgs;
161   }
162 }
163
164
165 /**************************************************************************
166 **
167 */
168 void GridCommLB::work (CentralLB::LDStats *stats, int count)
169 {
170   int i;
171   int send_object;
172   int send_pe;
173   int send_cluster;
174   int recv_object;
175   int recv_pe;
176   int recv_cluster;
177   int target_object;
178   int target_pe;
179   LDCommData *com_data;
180
181
182   stats->makeCommHash ();
183
184   Num_PEs = count;
185   Num_Objects = stats->n_objs;
186
187   PE_Data = new PE_Data_T[Num_PEs];
188   Object_Data = new Object_Data_T[Num_Objects];
189
190   for (i = 0; i < Num_PEs; i++) {
191     (&PE_Data[i])->available    = stats->procs[i].available;
192     (&PE_Data[i])->cluster      = Get_Cluster (i);
193     (&PE_Data[i])->num_objs     = 0;
194     (&PE_Data[i])->num_lan_objs = 0;
195     (&PE_Data[i])->num_lan_msgs = 0;
196     (&PE_Data[i])->num_wan_objs = 0;
197     (&PE_Data[i])->num_wan_msgs = 0;
198   }
199
200   for (i = 0; i < Num_Objects; i++) {
201     (&Object_Data[i])->migratable   = (&stats->objData[i])->migratable;
202     (&Object_Data[i])->cluster      = Get_Cluster (stats->from_proc[i]);
203     (&Object_Data[i])->from_pe      = stats->from_proc[i];
204     (&Object_Data[i])->num_lan_msgs = 0;
205     (&Object_Data[i])->num_wan_msgs = 0;
206
207     if ((&Object_Data[i])->migratable) {
208       (&Object_Data[i])->to_pe = -1;
209     } else {
210       (&Object_Data[i])->to_pe = (&Object_Data[i])->from_pe;
211     }
212   }
213
214   for (i = 0; i < stats->n_comm; i++) {
215     com_data = &(stats->commData[i]);
216     if ((!com_data->from_proc()) && (com_data->recv_type() == LD_OBJ_MSG)) {
217       send_object = stats->getHash (com_data->sender);
218       recv_object = stats->getHash (com_data->receiver.get_destObj());
219
220       send_pe = (&Object_Data[send_object])->from_pe;
221       recv_pe = (&Object_Data[recv_object])->from_pe;
222
223       send_cluster = Get_Cluster (send_pe);
224       recv_cluster = Get_Cluster (recv_pe);
225
226       if (send_cluster == recv_cluster) {
227         (&Object_Data[send_object])->num_lan_msgs += com_data->messages;
228       } else {
229         (&Object_Data[send_object])->num_wan_msgs += com_data->messages;
230       }
231     }
232   }
233
234   // Map objects to PEs in cluster 0.
235   while (1) {
236     target_object = Find_Maximum_WAN_Object (0);
237     target_pe     = Find_Minimum_WAN_PE (0);
238
239     if ((target_object == -1) || (target_pe == -1)) {
240       break;
241     }
242
243     Assign_Object_To_PE (target_object, target_pe);
244   }
245
246   // Map objects to PEs in cluster 1.
247   while (1) {
248     target_object = Find_Maximum_WAN_Object (1);
249     target_pe     = Find_Minimum_WAN_PE (1);
250
251     if ((target_object == -1) || (target_pe == -1)) {
252       break;
253     }
254
255     Assign_Object_To_PE (target_object, target_pe);
256   }
257
258   // Make the assignment of objects to PEs in the load balancer framework.
259   for (i = 0; i < Num_Objects; i++) {
260     stats->to_proc[i] = (&Object_Data[i])->to_pe;
261   }
262 }
263
264
265 #include "GridCommLB.def.h"