00001
00007 #include "BroadcastStrategy.h"
00008
00009
00010 CkpvExtern(CkGroupID, cmgrID);
00011 extern int sfactor;
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 void BroadcastStrategy::initHypercube() {
00027 logp = log((double) CkNumPes())/log(2.0);
00028 logp = ceil(logp);
00029 }
00030
00031
00032
00033
00034 BroadcastStrategy::BroadcastStrategy(int topology) :
00035 Strategy(), CharmStrategy(), _topology(topology) {
00036 spanning_factor = DEFAULT_BROADCAST_SPANNING_FACTOR;
00037 if(sfactor > 0)
00038 spanning_factor = sfactor;
00039
00040 setType(GROUP_STRATEGY);
00041 initHypercube();
00042 }
00043
00044
00045
00046 BroadcastStrategy::BroadcastStrategy(CkArrayID aid, int topology) :
00047 Strategy(), CharmStrategy(), _topology(topology) {
00048
00049 CkAbort("BroadcastStrategy currently works only for groups");
00050 setType(ARRAY_STRATEGY);
00051 ainfo.setDestinationArray(aid);
00052
00053 spanning_factor = DEFAULT_BROADCAST_SPANNING_FACTOR;
00054 if(sfactor > 0)
00055 spanning_factor = sfactor;
00056
00057 initHypercube();
00058
00059
00060 }
00061
00062
00063
00064 void BroadcastStrategy::insertMessage(CharmMessageHolder *cmsg){
00065
00066
00067 char *msg = cmsg->getCharmMessage();
00068
00069 envelope *env = UsrToEnv(msg);
00070 CmiMsgHeaderExt *conv_header = (CmiMsgHeaderExt *) env;
00071
00072 conv_header->root = 0;
00073 if(_topology == USE_HYPERCUBE)
00074 conv_header->xhdl = 0;
00075 else
00076
00077 conv_header->xhdl = CkMyPe();
00078
00079 CkPackMessage(&env);
00080 handleMessage((char *) env);
00081
00082 delete cmsg;
00083 }
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 void BroadcastStrategy::handleMessage(void *msg) {
00097 if(_topology == USE_TREE)
00098 handleTree(msg);
00099 else if(_topology == USE_HYPERCUBE)
00100 handleHypercube(msg);
00101 else CkAbort("Unknown Topology");
00102 }
00103
00104 void BroadcastStrategy::handleTree(void *msg){
00105
00106 envelope *env = (envelope *)msg;
00107 CmiMsgHeaderExt *conv_header = (CmiMsgHeaderExt *) msg;
00108
00109 int startpe = conv_header->xhdl;
00110 int size = env->getTotalsize();
00111
00112 CkAssert(startpe>=0 && startpe < CkNumPes());
00113
00114 CmiSetHandler(msg, CkpvAccess(comlib_handler));
00115
00116 conv_header->stratid = getInstance();
00117
00118
00119
00120 int i;
00121 for (i=1; i<=spanning_factor; i++) {
00122
00123 int p = CkMyPe() - startpe;
00124 if (p<0)
00125 p += CkNumPes();
00126
00127 p = spanning_factor*p + i;
00128
00129 if (p > CkNumPes() - 1) break;
00130
00131 p += startpe;
00132 p = p % CkNumPes();
00133
00134 CkAssert(p>=0 && p < CkNumPes() && p != CkMyPe());
00135
00136 CmiSyncSend(p, size, (char*)msg);
00137 }
00138
00139 if(getType() == GROUP_STRATEGY) {
00140 ComlibPrintf("BroadcastStrategy: delivering message\n");
00141 CkSendMsgBranch(env->getEpIdx(), EnvToUsr(env), CkMyPe(),
00142 env->getGroupNum());
00143 }
00144 else if(getType() == ARRAY_STRATEGY)
00145 ainfo.localBroadcast(env);
00146 }
00147
00148
00149 void BroadcastStrategy::handleHypercube(void *msg){
00150 envelope *env = (envelope *)msg;
00151
00152 CmiMsgHeaderExt *conv_header = (CmiMsgHeaderExt *) msg;
00153
00154 int curcycle = conv_header->xhdl;
00155
00156 int i;
00157 int size = env->getTotalsize();
00158
00159
00160
00161
00162 CmiSetHandler(msg, CkpvAccess(comlib_handler));
00163
00164 conv_header->stratid = getInstance();
00165
00166
00167
00168 for (i = logp - curcycle - 1; i >= 0; i--) {
00169 int p = CkMyPe() ^ (1 << i);
00170
00171 int newcycle = ++curcycle;
00172
00173
00174
00175 conv_header->xhdl = newcycle;
00176
00177 if(p >= CkNumPes()) {
00178 p &= (-1) << i;
00179
00180
00181 if (p < CkNumPes())
00182 p += (CkMyPe() -
00183 (CkMyPe() & ((-1) << i))) % (CkNumPes() - p);
00184 }
00185
00186 if(p < CkNumPes())
00187 CmiSyncSendFn(p, size, (char*)msg);
00188 }
00189
00190 if(getType() == GROUP_STRATEGY) {
00191 ComlibPrintf("BroadcastStrategy: delivering message\n");
00192 CkSendMsgBranch(env->getEpIdx(), EnvToUsr(env), CkMyPe(),
00193 env->getGroupNum());
00194 }
00195 else if(getType() == ARRAY_STRATEGY)
00196 ainfo.localBroadcast(env);
00197 }
00198
00199
00200
00201 void BroadcastStrategy::pup(PUP::er &p){
00202 Strategy::pup(p);
00203 CharmStrategy::pup(p);
00204
00205 p | spanning_factor;
00206 p | _topology;
00207 p | logp;
00208 }
00209