af9bcf1a60fbbe744284c8997b7d3654508a38ac
[charm.git] / examples / charm++ / commlib / multicast / pgm.C
1 #include <stdlib.h>
2 #include <alloca.h>
3 #include <time.h>
4 #include <string.h>
5
6 #include "pgm.h"
7
8 /* Proxies to allow charm structures to talk to each other */
9 CProxy_Main mainProxy;
10 CProxy_Source src;
11 CProxy_Destination dest;
12
13 /* Declaration of the three readonly variables used to hold the instances of
14    multicast strategies. In this way the association with the ProxySections can
15    be performed on any processor. */
16 ComlibInstanceHandle strat_direct;
17 ComlibInstanceHandle strat_ring;
18 ComlibInstanceHandle strat_multiring;
19
20 char *strategyName[3] = {"DirectMulticastStrategy", "RingMulticastStrategy", "MultiRingStrategy"};
21
22 Main::Main(CkArgMsg *m) {
23   count = 0;
24
25   // some hardcoded values
26   nsrc = 1000;
27   ndest = 1000;
28   int mcastFactor = 50;
29   iteration = 0;
30
31   mainProxy = thishandle;
32
33   // create the random mapping of sender-receiver
34   char **matrix = (char **) alloca(nsrc * sizeof(char*));
35   matrix[0] = (char *) malloc(nsrc * ndest * sizeof(char));
36   memset(matrix[0], 0, nsrc * ndest * sizeof(char));
37   for (int i=1; i<nsrc; ++i) matrix[i] = matrix[i-1] + ndest;
38
39   srand48(time(NULL));
40   for (int i=0; i<nsrc; ++i) {
41     for (int j=0; j<mcastFactor; ++j) {
42       int k = int(drand48() * ndest);
43       matrix[i][k] = 1;
44     }
45   }
46
47   // create the source and destination proxies
48   src = CProxy_Source::ckNew();
49   int *indices = (int *) alloca (mcastFactor * sizeof(int));
50   for (int i=0; i<nsrc; ++i) {
51     int idx = 0;
52     //CkPrintf("%d: sending to ",i);
53     for (int j=0; j<ndest; ++j) {
54       if (matrix[i][j] > 0) {
55         indices[idx++] = j;
56         //CkPrintf("%d ",j);
57       }
58     }
59     //CkPrintf("\n");
60     src[i].insert(idx, indices);
61   }
62   src.doneInserting();
63
64   dest = CProxy_Destination::ckNew();
65   int empty = 0;
66   for (int i=0; i<ndest; ++i) {
67     int cnt = 0;
68     for (int j=0; j<nsrc; ++j)
69       if (matrix[j][i] > 0) cnt++;
70     //CkPrintf("dest %d: receiving from %d\n",i,cnt);
71     dest[i].insert(cnt);
72     if (cnt == 0) empty++;
73   }
74   dest.doneInserting();
75   ndest -= empty;
76
77   // create the strategies and register them to commlib
78   CharmStrategy *strategy = new DirectMulticastStrategy(dest);
79   strat_direct = ComlibRegister(strategy);
80
81   strategy = new RingMulticastStrategy(dest);
82   strat_ring = ComlibRegister(strategy);
83
84   strategy = new MultiRingMulticast(dest);
85   strat_multiring = ComlibRegister(strategy);
86
87   CkPrintf("Starting new iteration\n");
88   src.start(++iteration);
89 }
90
91 /* invoked when the multicast has finished, will start next iteration, or end the program */
92 void Main::done() {
93   if (++count == ndest) {
94     CkPrintf("Iteration %d (%s) finished\n", iteration,strategyName[iteration-1]);
95     count = 0;
96     if (iteration == 3) CkExit();
97     else {
98       CkPrintf("Starting new iteration\n");
99       src.start(++iteration);
100     }
101   }
102 }
103
104
105 Source::Source(int n, int *indices) {
106   CkArrayIndexMax *elems = (CkArrayIndexMax*) alloca(n * sizeof(CkArrayIndexMax));
107   for (int i=0; i<n; ++i) elems[i] = CkArrayIndex1D(indices[i]);
108
109   /* Create the ProxySections and associate them with the three different
110      instances of commlib multicasts. */
111   direct_section = CProxySection_Destination::ckNew(dest, elems, n);
112   ComlibAssociateProxy(&strat_direct, direct_section);
113
114   ring_section = CProxySection_Destination::ckNew(dest, elems, n);
115   ComlibAssociateProxy(&strat_ring, ring_section);
116
117   multiring_section = CProxySection_Destination::ckNew(dest, elems, n);
118   ComlibAssociateProxy(&strat_multiring, multiring_section);
119 }
120
121 void Source::start(int i) {
122   MyMulticastMessage *msg = new (10000) MyMulticastMessage();
123   //CkPrintf("Source %d: starting multicast %d\n",thisIndex,i);
124   // Perform a multicast, using one of the strategies through the associated proxies
125   switch (i) {
126   case 1:
127     direct_section.receive(msg);
128     break;
129   case 2:
130     ring_section.receive(msg);
131     break;
132   case 3:
133     multiring_section.receive(msg);
134     break;
135   default:
136     CkAbort("Invalid iteration");
137   }
138 }
139
140
141 Destination::Destination(int senders) {
142   nsrc = senders;
143   waiting = senders;
144   //CkPrintf("dest %d: waiting for %d messages\n",thisIndex,senders);
145 }
146
147 void Destination::receive(MyMulticastMessage *m) {
148   delete m;
149   //CkPrintf("Destination %d: received, remaining %d\n",thisIndex,waiting);
150   if (--waiting == 0) {
151     // all messages received, send message to main
152     //CkPrintf("Destination %d: received all\n",thisIndex);
153     waiting = nsrc;
154     mainProxy.done();
155   }
156 }
157
158 #include "pgm.def.h"