| [0b990d] | 1 | //
 | 
|---|
 | 2 | // messimpl.cc
 | 
|---|
 | 3 | //
 | 
|---|
 | 4 | // Copyright (C) 1996 Limit Point Systems, Inc.
 | 
|---|
 | 5 | //
 | 
|---|
 | 6 | // Author: Curtis Janssen <cljanss@limitpt.com>
 | 
|---|
 | 7 | // Maintainer: LPS
 | 
|---|
 | 8 | //
 | 
|---|
 | 9 | // This file is part of the SC Toolkit.
 | 
|---|
 | 10 | //
 | 
|---|
 | 11 | // The SC Toolkit is free software; you can redistribute it and/or modify
 | 
|---|
 | 12 | // it under the terms of the GNU Library General Public License as published by
 | 
|---|
 | 13 | // the Free Software Foundation; either version 2, or (at your option)
 | 
|---|
 | 14 | // any later version.
 | 
|---|
 | 15 | //
 | 
|---|
 | 16 | // The SC Toolkit is distributed in the hope that it will be useful,
 | 
|---|
 | 17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
 | 18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
 | 19 | // GNU Library General Public License for more details.
 | 
|---|
 | 20 | //
 | 
|---|
 | 21 | // You should have received a copy of the GNU Library General Public License
 | 
|---|
 | 22 | // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
 | 
|---|
 | 23 | // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
|---|
 | 24 | //
 | 
|---|
 | 25 | // The U.S. Government is granted a limited license as per AL 91-7.
 | 
|---|
 | 26 | //
 | 
|---|
 | 27 | 
 | 
|---|
 | 28 | #include <string.h>
 | 
|---|
 | 29 | 
 | 
|---|
 | 30 | #include <util/misc/formio.h>
 | 
|---|
 | 31 | #include <util/misc/exenv.h>
 | 
|---|
 | 32 | 
 | 
|---|
 | 33 | #include <util/group/message.h>
 | 
|---|
 | 34 | 
 | 
|---|
 | 35 | #include <util/group/topology.h>
 | 
|---|
 | 36 | #include <util/group/hcube.h>
 | 
|---|
 | 37 | #ifdef HAVE_NX
 | 
|---|
 | 38 | #  include <util/group/messpgon.h>
 | 
|---|
 | 39 | #endif
 | 
|---|
 | 40 | #ifdef HAVE_MPI
 | 
|---|
 | 41 | #  define MPICH_SKIP_MPICXX
 | 
|---|
 | 42 | #  include <mpi.h>
 | 
|---|
 | 43 | #  include <util/group/messmpi.h>
 | 
|---|
 | 44 | #endif
 | 
|---|
 | 45 | 
 | 
|---|
 | 46 | #define DEFAULT_GOP_MAX 320000
 | 
|---|
 | 47 | 
 | 
|---|
 | 48 | using namespace std;
 | 
|---|
 | 49 | using namespace sc;
 | 
|---|
 | 50 | 
 | 
|---|
 | 51 | static ClassDesc MessageGrp_cd(
 | 
|---|
 | 52 |   typeid(MessageGrp),"MessageGrp",1,"public DescribedClass",
 | 
|---|
 | 53 |   0, 0, 0);
 | 
|---|
 | 54 | 
 | 
|---|
 | 55 | MessageGrp::MessageGrp(const Ref<KeyVal>& keyval):
 | 
|---|
 | 56 |   me_(-1),
 | 
|---|
 | 57 |   n_(-1),
 | 
|---|
 | 58 |   index_to_classdesc_(0)
 | 
|---|
 | 59 | {
 | 
|---|
 | 60 |   gop_max_ = keyval->intvalue("gop_max");
 | 
|---|
 | 61 |   if (keyval->error() != KeyVal::OK) gop_max_ = DEFAULT_GOP_MAX;
 | 
|---|
 | 62 |   debug_ = keyval->booleanvalue("debug");
 | 
|---|
 | 63 | }
 | 
|---|
 | 64 | 
 | 
|---|
 | 65 | MessageGrp::MessageGrp():
 | 
|---|
 | 66 |   me_(-1),
 | 
|---|
 | 67 |   n_(-1),
 | 
|---|
 | 68 |   index_to_classdesc_(0)
 | 
|---|
 | 69 | {
 | 
|---|
 | 70 |   gop_max_ = DEFAULT_GOP_MAX;
 | 
|---|
 | 71 |   debug_ = 0;
 | 
|---|
 | 72 | }
 | 
|---|
 | 73 | 
 | 
|---|
 | 74 | MessageGrp::~MessageGrp()
 | 
|---|
 | 75 | {
 | 
|---|
 | 76 |   if (index_to_classdesc_) delete[] index_to_classdesc_;
 | 
|---|
 | 77 | }
 | 
|---|
 | 78 | 
 | 
|---|
 | 79 | static Ref<MessageGrp> default_messagegrp;
 | 
|---|
 | 80 | 
 | 
|---|
 | 81 | void
 | 
|---|
 | 82 | MessageGrp::set_default_messagegrp(const Ref<MessageGrp>& grp)
 | 
|---|
 | 83 | {
 | 
|---|
 | 84 |   default_messagegrp = grp;
 | 
|---|
 | 85 | }
 | 
|---|
 | 86 | 
 | 
|---|
 | 87 | MessageGrp*
 | 
|---|
 | 88 | MessageGrp::get_default_messagegrp()
 | 
|---|
 | 89 | {
 | 
|---|
 | 90 |   if (default_messagegrp.null()) {
 | 
|---|
 | 91 | #if defined(HAVE_MPI) && defined(DEFAULT_MPI)
 | 
|---|
 | 92 |       default_messagegrp = new MPIMessageGrp;
 | 
|---|
 | 93 | #else
 | 
|---|
 | 94 |       default_messagegrp = new ProcMessageGrp;
 | 
|---|
 | 95 | #endif
 | 
|---|
 | 96 |     }
 | 
|---|
 | 97 |   return default_messagegrp.pointer();
 | 
|---|
 | 98 | }
 | 
|---|
 | 99 | 
 | 
|---|
 | 100 | MessageGrp *
 | 
|---|
 | 101 | MessageGrp::initial_messagegrp(int &argc, char** &argv)
 | 
|---|
 | 102 | {
 | 
|---|
 | 103 |   MessageGrp *grp = 0;
 | 
|---|
 | 104 | 
 | 
|---|
 | 105 |   char *keyval_string = 0;
 | 
|---|
 | 106 | 
 | 
|---|
 | 107 |   // see if a message group is given on the command line
 | 
|---|
 | 108 |   if (argc && argv) {
 | 
|---|
 | 109 |       for (int i=0; i<argc; i++) {
 | 
|---|
 | 110 |           if (argv[i] && !strcmp(argv[i], "-messagegrp")) {
 | 
|---|
 | 111 |               char *messagegrp_string = argv[i];
 | 
|---|
 | 112 |               i++;
 | 
|---|
 | 113 |               if (i >= argc) {
 | 
|---|
 | 114 |                   ExEnv::errn() << "-messagegrp must be following by an argument"
 | 
|---|
 | 115 |                        << endl;
 | 
|---|
 | 116 |                   abort();
 | 
|---|
 | 117 |                 }
 | 
|---|
 | 118 |               keyval_string = argv[i];
 | 
|---|
 | 119 |               // move the messagegrp arguments to the end of argv
 | 
|---|
 | 120 |               int j;
 | 
|---|
 | 121 |               for (j=i+1; j<argc; j++) {
 | 
|---|
 | 122 |                   argv[j-2] = argv[j];
 | 
|---|
 | 123 |                 }
 | 
|---|
 | 124 |               argv[j++] = messagegrp_string;
 | 
|---|
 | 125 |               argv[j++] = keyval_string;
 | 
|---|
 | 126 |               // decrement argc to hide the last two arguments
 | 
|---|
 | 127 |               argc -= 2;
 | 
|---|
 | 128 |               break;
 | 
|---|
 | 129 |             }
 | 
|---|
 | 130 |         }
 | 
|---|
 | 131 |     }
 | 
|---|
 | 132 | 
 | 
|---|
 | 133 |   if (!keyval_string) {
 | 
|---|
 | 134 |       // find out if the environment gives the containing message group
 | 
|---|
 | 135 |       keyval_string = getenv("MESSAGEGRP");
 | 
|---|
 | 136 |       if (keyval_string) {
 | 
|---|
 | 137 |           if (!strncmp("MESSAGEGRP=", keyval_string, 11)) {
 | 
|---|
 | 138 |               keyval_string = strchr(keyval_string, '=');
 | 
|---|
 | 139 |             }
 | 
|---|
 | 140 |           if (*keyval_string == '=') keyval_string++;
 | 
|---|
 | 141 |         }
 | 
|---|
 | 142 |     }
 | 
|---|
 | 143 | 
 | 
|---|
 | 144 |   // if keyval input for a message group was found, then
 | 
|---|
 | 145 |   // create it.
 | 
|---|
 | 146 |   if (keyval_string) {
 | 
|---|
 | 147 |       if (keyval_string[0] == '\0') return 0;
 | 
|---|
 | 148 |       //ExEnv::outn() << "Creating MessageGrp from \"" << keyval_string << "\"" << endl;
 | 
|---|
 | 149 |       Ref<ParsedKeyVal> strkv = new ParsedKeyVal();
 | 
|---|
 | 150 |       strkv->parse_string(keyval_string);
 | 
|---|
 | 151 |       Ref<DescribedClass> dc = strkv->describedclassvalue();
 | 
|---|
 | 152 |       grp = dynamic_cast<MessageGrp*>(dc.pointer());
 | 
|---|
 | 153 |       if (dc.null()) {
 | 
|---|
 | 154 |           ExEnv::errn() << "initial_messagegrp: couldn't find a MessageGrp in "
 | 
|---|
 | 155 |                << keyval_string << endl;
 | 
|---|
 | 156 |           abort();
 | 
|---|
 | 157 |         }
 | 
|---|
 | 158 |       else if (!grp) {
 | 
|---|
 | 159 |           ExEnv::errn() << "initial_messagegrp: wanted MessageGrp but got "
 | 
|---|
 | 160 |                << dc->class_name() << endl;
 | 
|---|
 | 161 |           abort();
 | 
|---|
 | 162 |         }
 | 
|---|
 | 163 |       // prevent an accidental delete
 | 
|---|
 | 164 |       grp->reference();
 | 
|---|
 | 165 |       strkv = 0;
 | 
|---|
 | 166 |       dc = 0;
 | 
|---|
 | 167 |       // accidental delete not a problem anymore since all smart pointers
 | 
|---|
 | 168 |       // to grp are dead
 | 
|---|
 | 169 |       grp->dereference();
 | 
|---|
 | 170 |       return grp;
 | 
|---|
 | 171 |     }
 | 
|---|
 | 172 | 
 | 
|---|
 | 173 | #if defined(HAVE_MPI)
 | 
|---|
 | 174 |   int mpiinited;
 | 
|---|
 | 175 | #ifdef ALWAYS_USE_MPI
 | 
|---|
 | 176 |   bool always_use_mpi = true;
 | 
|---|
 | 177 | #else
 | 
|---|
 | 178 |   bool always_use_mpi = false;
 | 
|---|
 | 179 | #endif
 | 
|---|
 | 180 |   MPI_Initialized(&mpiinited);
 | 
|---|
 | 181 |   if (mpiinited || always_use_mpi) {
 | 
|---|
 | 182 |       grp = new MPIMessageGrp(&argc,&argv);
 | 
|---|
 | 183 |       return grp;
 | 
|---|
 | 184 |   }
 | 
|---|
 | 185 | #endif
 | 
|---|
 | 186 | 
 | 
|---|
 | 187 |   return 0;
 | 
|---|
 | 188 | }
 | 
|---|
 | 189 | 
 | 
|---|
 | 190 | void
 | 
|---|
 | 191 | MessageGrp::initialize(int me, int n)
 | 
|---|
 | 192 | {
 | 
|---|
 | 193 |   // This member is called by a CTOR and, ultimately, causes
 | 
|---|
 | 194 |   // 'this' to be converted into a temporary Ref which causes
 | 
|---|
 | 195 |   // this to be deleted (very bad), so reference 'this'
 | 
|---|
 | 196 |   // (and dereference this down below).
 | 
|---|
 | 197 |   this->reference();
 | 
|---|
 | 198 | 
 | 
|---|
 | 199 |   if (topology_.null()) {
 | 
|---|
 | 200 |       topology_ = new HypercubeTopology();
 | 
|---|
 | 201 |     }
 | 
|---|
 | 202 | 
 | 
|---|
 | 203 |   int i;
 | 
|---|
 | 204 |   std::map<std::string,ClassDescP>::iterator J;
 | 
|---|
 | 205 |   
 | 
|---|
 | 206 |   me_ = me;
 | 
|---|
 | 207 |   n_ = n;
 | 
|---|
 | 208 | 
 | 
|---|
 | 209 |   // get all of the classes known on this node
 | 
|---|
 | 210 |   std::map<std::string,ClassDescP>& classes = ClassDesc::all();
 | 
|---|
 | 211 | 
 | 
|---|
 | 212 |   // Keeps count of how many classes are known.
 | 
|---|
 | 213 |   int iclass = 0;
 | 
|---|
 | 214 | 
 | 
|---|
 | 215 |   for (i=0; i<n; i++) {
 | 
|---|
 | 216 |       if (i==me) {
 | 
|---|
 | 217 |           // Find out how many of my classes are not yet in the
 | 
|---|
 | 218 |           // classdesc to index map.
 | 
|---|
 | 219 |           int n_new_class = 0;
 | 
|---|
 | 220 |           int buffer_size = 0;
 | 
|---|
 | 221 |           for (J=classes.begin(); J!=classes.end(); J++) {
 | 
|---|
 | 222 |               if (classdesc_to_index_.find(J->second) == classdesc_to_index_.end()) {
 | 
|---|
 | 223 |                   n_new_class++;
 | 
|---|
 | 224 |                   buffer_size += strlen(J->second->name()) + 1;
 | 
|---|
 | 225 |                 }
 | 
|---|
 | 226 |             }
 | 
|---|
 | 227 |           char* buffer = new char[buffer_size];
 | 
|---|
 | 228 |           char* currentbuffer = buffer;
 | 
|---|
 | 229 |           for (J=classes.begin(); J!=classes.end(); J++) {
 | 
|---|
 | 230 |               if (classdesc_to_index_.find(J->second) == classdesc_to_index_.end()) {
 | 
|---|
 | 231 |                   classdesc_to_index_[J->second] = iclass;
 | 
|---|
 | 232 |                   iclass++;
 | 
|---|
 | 233 | #ifdef DEBUG
 | 
|---|
 | 234 |                   ExEnv::outn() << scprintf("node %d adding class %d = \"%s\"\n",
 | 
|---|
 | 235 |                                    me, iclass, J->second->name());
 | 
|---|
 | 236 | #endif
 | 
|---|
 | 237 |                   strcpy(currentbuffer,J->second->name());
 | 
|---|
 | 238 |                   currentbuffer += strlen(J->second->name()) + 1;
 | 
|---|
 | 239 |                 }
 | 
|---|
 | 240 |             }
 | 
|---|
 | 241 | #ifdef DEBUG
 | 
|---|
 | 242 |           ExEnv::outn() << scprintf("node %d bcast n_new_class = %d\n",me,n_new_class);
 | 
|---|
 | 243 | #endif
 | 
|---|
 | 244 |           bcast(&n_new_class,1,i);
 | 
|---|
 | 245 | #ifdef DEBUG
 | 
|---|
 | 246 |           ExEnv::outn() << scprintf("node %d finished bcast\n",me);
 | 
|---|
 | 247 | #endif
 | 
|---|
 | 248 |           if (n_new_class) {
 | 
|---|
 | 249 |               bcast(&buffer_size,1,i);
 | 
|---|
 | 250 |               bcast(buffer,buffer_size,i);
 | 
|---|
 | 251 |             }
 | 
|---|
 | 252 |           delete[] buffer;
 | 
|---|
 | 253 |         }
 | 
|---|
 | 254 |       else {
 | 
|---|
 | 255 |           int j;
 | 
|---|
 | 256 |           // Get new classnames and indices from node i.
 | 
|---|
 | 257 |           int n_new_class;
 | 
|---|
 | 258 | #ifdef DEBUG
 | 
|---|
 | 259 |           ExEnv::outn() << scprintf("node %d begin recv bcast\n",me);
 | 
|---|
 | 260 | #endif
 | 
|---|
 | 261 |           bcast(&n_new_class,1,i);
 | 
|---|
 | 262 | #ifdef DEBUG
 | 
|---|
 | 263 |           ExEnv::outn() << scprintf("node %d recv bcast n_new_class = %d\n",
 | 
|---|
 | 264 |                            me,n_new_class);
 | 
|---|
 | 265 | #endif
 | 
|---|
 | 266 |           if (n_new_class) {
 | 
|---|
 | 267 |               int buffer_size;
 | 
|---|
 | 268 |               bcast(&buffer_size,1,i);
 | 
|---|
 | 269 |               char* buffer = new char[buffer_size];
 | 
|---|
 | 270 |               char* currentbuffer = buffer;
 | 
|---|
 | 271 |               bcast(buffer,buffer_size,i);
 | 
|---|
 | 272 |               for (j=0; j<n_new_class; j++) {
 | 
|---|
 | 273 |                   ClassDescP cd = ClassDesc::name_to_class_desc(currentbuffer);
 | 
|---|
 | 274 |                   if (cd) {
 | 
|---|
 | 275 | #ifdef DEBUG
 | 
|---|
 | 276 |                       ExEnv::outn() << scprintf("node %d adding \"%s\"\n",
 | 
|---|
 | 277 |                                        me, currentbuffer);
 | 
|---|
 | 278 | #endif
 | 
|---|
 | 279 |                       classdesc_to_index_[cd] = iclass;
 | 
|---|
 | 280 |                     }
 | 
|---|
 | 281 | #ifdef DEBUG
 | 
|---|
 | 282 |                   else {
 | 
|---|
 | 283 |                       ExEnv::outn() << scprintf("node %d failed to add \"%s\"\n",
 | 
|---|
 | 284 |                                        me, currentbuffer);
 | 
|---|
 | 285 |                     }
 | 
|---|
 | 286 | #endif
 | 
|---|
 | 287 |                   iclass++;
 | 
|---|
 | 288 |                   // advance the currentbuffer to the next classname
 | 
|---|
 | 289 |                   while(*currentbuffer != '\0') currentbuffer++;
 | 
|---|
 | 290 |                   currentbuffer++;
 | 
|---|
 | 291 |                 }
 | 
|---|
 | 292 |               delete[] buffer;
 | 
|---|
 | 293 |             }
 | 
|---|
 | 294 |         }
 | 
|---|
 | 295 |     }
 | 
|---|
 | 296 |   nclass_ = iclass;
 | 
|---|
 | 297 | 
 | 
|---|
 | 298 |   // Construct the mapping of index to classdesc.
 | 
|---|
 | 299 |   index_to_classdesc_ = new ClassDescP[iclass];
 | 
|---|
 | 300 |   for (i=0; i<nclass_; i++) {
 | 
|---|
 | 301 |       index_to_classdesc_[i] = 0;
 | 
|---|
 | 302 |     }
 | 
|---|
 | 303 |   for (J=classes.begin(); J!=classes.end(); J++) {
 | 
|---|
 | 304 |       if (classdesc_to_index_.find(J->second) != classdesc_to_index_.end()) {
 | 
|---|
 | 305 |           index_to_classdesc_[classdesc_to_index_[J->second]] = J->second;
 | 
|---|
 | 306 |         }
 | 
|---|
 | 307 |     }
 | 
|---|
 | 308 | 
 | 
|---|
 | 309 |   this->dereference();
 | 
|---|
 | 310 | }
 | 
|---|
 | 311 | 
 | 
|---|
 | 312 | // Sequential send routines
 | 
|---|
 | 313 | 
 | 
|---|
 | 314 | void
 | 
|---|
 | 315 | MessageGrp::send(int target, const double* data, int ndata)
 | 
|---|
 | 316 | {
 | 
|---|
 | 317 |   raw_send(target, data, ndata*sizeof(double));
 | 
|---|
 | 318 | }
 | 
|---|
 | 319 | void
 | 
|---|
 | 320 | MessageGrp::send(int target, const short* data, int ndata)
 | 
|---|
 | 321 | {
 | 
|---|
 | 322 |   raw_send(target, data, ndata*sizeof(short));
 | 
|---|
 | 323 | }
 | 
|---|
 | 324 | void
 | 
|---|
 | 325 | MessageGrp::send(int target, const long* data, int ndata)
 | 
|---|
 | 326 | {
 | 
|---|
 | 327 |   raw_send(target, data, ndata*sizeof(long));
 | 
|---|
 | 328 | }
 | 
|---|
 | 329 | void
 | 
|---|
 | 330 | MessageGrp::send(int target, const float* data, int ndata)
 | 
|---|
 | 331 | {
 | 
|---|
 | 332 |   raw_send(target, data, ndata*sizeof(float));
 | 
|---|
 | 333 | }
 | 
|---|
 | 334 | void
 | 
|---|
 | 335 | MessageGrp::send(int target, const unsigned int* data, int ndata)
 | 
|---|
 | 336 | {
 | 
|---|
 | 337 |   raw_send(target, data, ndata*sizeof(int));
 | 
|---|
 | 338 | }
 | 
|---|
 | 339 | void
 | 
|---|
 | 340 | MessageGrp::send(int target, const int* data, int ndata)
 | 
|---|
 | 341 | {
 | 
|---|
 | 342 |   raw_send(target, data, ndata*sizeof(int));
 | 
|---|
 | 343 | }
 | 
|---|
 | 344 | void
 | 
|---|
 | 345 | MessageGrp::send(int target, const char* data, int ndata)
 | 
|---|
 | 346 | {
 | 
|---|
 | 347 |   raw_send(target, data, ndata);
 | 
|---|
 | 348 | }
 | 
|---|
 | 349 | void
 | 
|---|
 | 350 | MessageGrp::send(int target, const unsigned char* data, int ndata)
 | 
|---|
 | 351 | {
 | 
|---|
 | 352 |   raw_send(target, data, ndata);
 | 
|---|
 | 353 | }
 | 
|---|
 | 354 | void
 | 
|---|
 | 355 | MessageGrp::send(int target, const signed char* data, int ndata)
 | 
|---|
 | 356 | {
 | 
|---|
 | 357 |   raw_send(target, data, ndata);
 | 
|---|
 | 358 | }
 | 
|---|
 | 359 | 
 | 
|---|
 | 360 | // Sequential receive routines
 | 
|---|
 | 361 | 
 | 
|---|
 | 362 | void
 | 
|---|
 | 363 | MessageGrp::recv(int sender, double* data, int ndata)
 | 
|---|
 | 364 | {
 | 
|---|
 | 365 |   raw_recv(sender, data, ndata*sizeof(double));
 | 
|---|
 | 366 | }
 | 
|---|
 | 367 | void
 | 
|---|
 | 368 | MessageGrp::recv(int sender, short* data, int ndata)
 | 
|---|
 | 369 | {
 | 
|---|
 | 370 |   raw_recv(sender, data, ndata*sizeof(short));
 | 
|---|
 | 371 | }
 | 
|---|
 | 372 | void
 | 
|---|
 | 373 | MessageGrp::recv(int sender, long* data, int ndata)
 | 
|---|
 | 374 | {
 | 
|---|
 | 375 |   raw_recv(sender, data, ndata*sizeof(long));
 | 
|---|
 | 376 | }
 | 
|---|
 | 377 | void
 | 
|---|
 | 378 | MessageGrp::recv(int sender, float* data, int ndata)
 | 
|---|
 | 379 | {
 | 
|---|
 | 380 |   raw_recv(sender, data, ndata*sizeof(float));
 | 
|---|
 | 381 | }
 | 
|---|
 | 382 | void
 | 
|---|
 | 383 | MessageGrp::recv(int sender, unsigned int* data, int ndata)
 | 
|---|
 | 384 | {
 | 
|---|
 | 385 |   raw_recv(sender, data, ndata*sizeof(int));
 | 
|---|
 | 386 | }
 | 
|---|
 | 387 | void
 | 
|---|
 | 388 | MessageGrp::recv(int sender, int* data, int ndata)
 | 
|---|
 | 389 | {
 | 
|---|
 | 390 |   raw_recv(sender, data, ndata*sizeof(int));
 | 
|---|
 | 391 | }
 | 
|---|
 | 392 | void
 | 
|---|
 | 393 | MessageGrp::recv(int sender, char* data, int ndata)
 | 
|---|
 | 394 | {
 | 
|---|
 | 395 |   raw_recv(sender, data, ndata);
 | 
|---|
 | 396 | }
 | 
|---|
 | 397 | void
 | 
|---|
 | 398 | MessageGrp::recv(int sender, unsigned char* data, int ndata)
 | 
|---|
 | 399 | {
 | 
|---|
 | 400 |   raw_recv(sender, data, ndata);
 | 
|---|
 | 401 | }
 | 
|---|
 | 402 | void
 | 
|---|
 | 403 | MessageGrp::recv(int sender, signed char* data, int ndata)
 | 
|---|
 | 404 | {
 | 
|---|
 | 405 |   raw_recv(sender, data, ndata);
 | 
|---|
 | 406 | }
 | 
|---|
 | 407 | 
 | 
|---|
 | 408 | // Typed send routines
 | 
|---|
 | 409 | 
 | 
|---|
 | 410 | void
 | 
|---|
 | 411 | MessageGrp::sendt(int target, int type, const double* data, int ndata)
 | 
|---|
 | 412 | {
 | 
|---|
 | 413 |   raw_sendt(target, type, data, ndata*sizeof(double));
 | 
|---|
 | 414 | }
 | 
|---|
 | 415 | void
 | 
|---|
 | 416 | MessageGrp::sendt(int target, int type, const short* data, int ndata)
 | 
|---|
 | 417 | {
 | 
|---|
 | 418 |   raw_sendt(target, type, data, ndata*sizeof(short));
 | 
|---|
 | 419 | }
 | 
|---|
 | 420 | void
 | 
|---|
 | 421 | MessageGrp::sendt(int target, int type, const long* data, int ndata)
 | 
|---|
 | 422 | {
 | 
|---|
 | 423 |   raw_sendt(target, type, data, ndata*sizeof(long));
 | 
|---|
 | 424 | }
 | 
|---|
 | 425 | void
 | 
|---|
 | 426 | MessageGrp::sendt(int target, int type, const float* data, int ndata)
 | 
|---|
 | 427 | {
 | 
|---|
 | 428 |   raw_sendt(target, type, data, ndata*sizeof(float));
 | 
|---|
 | 429 | }
 | 
|---|
 | 430 | void
 | 
|---|
 | 431 | MessageGrp::sendt(int target, int type, const unsigned int* data, int ndata)
 | 
|---|
 | 432 | {
 | 
|---|
 | 433 |   raw_sendt(target, type, data, ndata*sizeof(int));
 | 
|---|
 | 434 | }
 | 
|---|
 | 435 | void
 | 
|---|
 | 436 | MessageGrp::sendt(int target, int type, const int* data, int ndata)
 | 
|---|
 | 437 | {
 | 
|---|
 | 438 |   raw_sendt(target, type, data, ndata*sizeof(int));
 | 
|---|
 | 439 | }
 | 
|---|
 | 440 | void
 | 
|---|
 | 441 | MessageGrp::sendt(int target, int type, const char* data, int ndata)
 | 
|---|
 | 442 | {
 | 
|---|
 | 443 |   raw_sendt(target, type, data, ndata);
 | 
|---|
 | 444 | }
 | 
|---|
 | 445 | void
 | 
|---|
 | 446 | MessageGrp::sendt(int target, int type, const unsigned char* data, int ndata)
 | 
|---|
 | 447 | {
 | 
|---|
 | 448 |   raw_sendt(target, type, data, ndata);
 | 
|---|
 | 449 | }
 | 
|---|
 | 450 | void
 | 
|---|
 | 451 | MessageGrp::sendt(int target, int type, const signed char* data, int ndata)
 | 
|---|
 | 452 | {
 | 
|---|
 | 453 |   raw_sendt(target, type, data, ndata);
 | 
|---|
 | 454 | }
 | 
|---|
 | 455 | 
 | 
|---|
 | 456 | // Typed receive routines
 | 
|---|
 | 457 | 
 | 
|---|
 | 458 | void
 | 
|---|
 | 459 | MessageGrp::recvt(int type, double* data, int ndata)
 | 
|---|
 | 460 | {
 | 
|---|
 | 461 |   raw_recvt(type, data, ndata*sizeof(double));
 | 
|---|
 | 462 | }
 | 
|---|
 | 463 | void
 | 
|---|
 | 464 | MessageGrp::recvt(int type, short* data, int ndata)
 | 
|---|
 | 465 | {
 | 
|---|
 | 466 |   raw_recvt(type, data, ndata*sizeof(short));
 | 
|---|
 | 467 | }
 | 
|---|
 | 468 | void
 | 
|---|
 | 469 | MessageGrp::recvt(int type, long* data, int ndata)
 | 
|---|
 | 470 | {
 | 
|---|
 | 471 |   raw_recvt(type, data, ndata*sizeof(long));
 | 
|---|
 | 472 | }
 | 
|---|
 | 473 | void
 | 
|---|
 | 474 | MessageGrp::recvt(int type, float* data, int ndata)
 | 
|---|
 | 475 | {
 | 
|---|
 | 476 |   raw_recvt(type, data, ndata*sizeof(float));
 | 
|---|
 | 477 | }
 | 
|---|
 | 478 | void
 | 
|---|
 | 479 | MessageGrp::recvt(int type, unsigned int* data, int ndata)
 | 
|---|
 | 480 | {
 | 
|---|
 | 481 |   raw_recvt(type, data, ndata*sizeof(int));
 | 
|---|
 | 482 | }
 | 
|---|
 | 483 | void
 | 
|---|
 | 484 | MessageGrp::recvt(int type, int* data, int ndata)
 | 
|---|
 | 485 | {
 | 
|---|
 | 486 |   raw_recvt(type, data, ndata*sizeof(int));
 | 
|---|
 | 487 | }
 | 
|---|
 | 488 | void
 | 
|---|
 | 489 | MessageGrp::recvt(int type, char* data, int ndata)
 | 
|---|
 | 490 | {
 | 
|---|
 | 491 |   raw_recvt(type, data, ndata);
 | 
|---|
 | 492 | }
 | 
|---|
 | 493 | void
 | 
|---|
 | 494 | MessageGrp::recvt(int type, unsigned char* data, int ndata)
 | 
|---|
 | 495 | {
 | 
|---|
 | 496 |   raw_recvt(type, data, ndata);
 | 
|---|
 | 497 | }
 | 
|---|
 | 498 | void
 | 
|---|
 | 499 | MessageGrp::recvt(int type, signed char* data, int ndata)
 | 
|---|
 | 500 | {
 | 
|---|
 | 501 |   raw_recvt(type, data, ndata);
 | 
|---|
 | 502 | }
 | 
|---|
 | 503 | 
 | 
|---|
 | 504 | // Broadcast operations
 | 
|---|
 | 505 | 
 | 
|---|
 | 506 | void
 | 
|---|
 | 507 | MessageGrp::bcast(double*data, int ndata, int from)
 | 
|---|
 | 508 | {
 | 
|---|
 | 509 |   raw_bcast(data, ndata*sizeof(double), from);
 | 
|---|
 | 510 | }
 | 
|---|
 | 511 | void
 | 
|---|
 | 512 | MessageGrp::bcast(short*data, int ndata, int from)
 | 
|---|
 | 513 | {
 | 
|---|
 | 514 |   raw_bcast(data, ndata*sizeof(short), from);
 | 
|---|
 | 515 | }
 | 
|---|
 | 516 | void
 | 
|---|
 | 517 | MessageGrp::bcast(long*data, int ndata, int from)
 | 
|---|
 | 518 | {
 | 
|---|
 | 519 |   raw_bcast(data, ndata*sizeof(long), from);
 | 
|---|
 | 520 | }
 | 
|---|
 | 521 | void
 | 
|---|
 | 522 | MessageGrp::bcast(float*data, int ndata, int from)
 | 
|---|
 | 523 | {
 | 
|---|
 | 524 |   raw_bcast(data, ndata*sizeof(float), from);
 | 
|---|
 | 525 | }
 | 
|---|
 | 526 | void
 | 
|---|
 | 527 | MessageGrp::bcast(unsigned int*data, int ndata, int from)
 | 
|---|
 | 528 | {
 | 
|---|
 | 529 |   raw_bcast(data, ndata*sizeof(int), from);
 | 
|---|
 | 530 | }
 | 
|---|
 | 531 | void
 | 
|---|
 | 532 | MessageGrp::bcast(int*data, int ndata, int from)
 | 
|---|
 | 533 | {
 | 
|---|
 | 534 |   raw_bcast(data, ndata*sizeof(int), from);
 | 
|---|
 | 535 | }
 | 
|---|
 | 536 | void
 | 
|---|
 | 537 | MessageGrp::bcast(char*data, int ndata, int from)
 | 
|---|
 | 538 | {
 | 
|---|
 | 539 |   raw_bcast(data, ndata, from);
 | 
|---|
 | 540 | }
 | 
|---|
 | 541 | void
 | 
|---|
 | 542 | MessageGrp::bcast(unsigned char*data, int ndata, int from)
 | 
|---|
 | 543 | {
 | 
|---|
 | 544 |   raw_bcast(data, ndata, from);
 | 
|---|
 | 545 | }
 | 
|---|
 | 546 | void
 | 
|---|
 | 547 | MessageGrp::bcast(signed char*data, int ndata, int from)
 | 
|---|
 | 548 | {
 | 
|---|
 | 549 |   raw_bcast(data, ndata, from);
 | 
|---|
 | 550 | }
 | 
|---|
 | 551 | 
 | 
|---|
 | 552 | // Global classdesc indices
 | 
|---|
 | 553 | 
 | 
|---|
 | 554 | int
 | 
|---|
 | 555 | MessageGrp::classdesc_to_index(const ClassDesc* cdptr)
 | 
|---|
 | 556 | {
 | 
|---|
 | 557 |   if (classdesc_to_index_.find((ClassDesc*)cdptr) != classdesc_to_index_.end()) {
 | 
|---|
 | 558 |       return classdesc_to_index_[(ClassDesc*)cdptr];
 | 
|---|
 | 559 |     }
 | 
|---|
 | 560 |   else {
 | 
|---|
 | 561 |       return -1;
 | 
|---|
 | 562 |     }
 | 
|---|
 | 563 | }
 | 
|---|
 | 564 | 
 | 
|---|
 | 565 | const ClassDesc*
 | 
|---|
 | 566 | MessageGrp::index_to_classdesc(int index)
 | 
|---|
 | 567 | {
 | 
|---|
 | 568 |   if (index < 0 || index >= nclass_) {
 | 
|---|
 | 569 |       return 0;
 | 
|---|
 | 570 |     }
 | 
|---|
 | 571 |   else {
 | 
|---|
 | 572 |       return index_to_classdesc_[index];
 | 
|---|
 | 573 |     }
 | 
|---|
 | 574 | }
 | 
|---|
 | 575 | 
 | 
|---|
 | 576 | void
 | 
|---|
 | 577 | MessageGrp::raw_bcast(void* data, int nbyte, int from)
 | 
|---|
 | 578 | {
 | 
|---|
 | 579 |   int nbyte_actual = nbyte;
 | 
|---|
 | 580 |   int tgop_max = nbyte;
 | 
|---|
 | 581 |   if (gop_max_ != 0) {
 | 
|---|
 | 582 |       tgop_max = gop_max_;
 | 
|---|
 | 583 |       gop_max_ = 0;
 | 
|---|
 | 584 |       bcast(nbyte_actual,from);
 | 
|---|
 | 585 |       gop_max_ = tgop_max;
 | 
|---|
 | 586 |     }
 | 
|---|
 | 587 |   for (int idat=0; idat<nbyte_actual; idat+=tgop_max) {
 | 
|---|
 | 588 |       int ndat = (idat+tgop_max>nbyte_actual)?(nbyte_actual-idat):tgop_max;
 | 
|---|
 | 589 |       Ref<GlobalMsgIter> i(topology_->global_msg_iter(this, from));
 | 
|---|
 | 590 |       for (i->forwards(); !i->done(); i->next()) {
 | 
|---|
 | 591 |           if (i->send()) {
 | 
|---|
 | 592 |               raw_send(i->sendto(), &((char*)data)[idat], ndat);
 | 
|---|
 | 593 |             }
 | 
|---|
 | 594 |           if (i->recv()) {
 | 
|---|
 | 595 |               raw_recv(i->recvfrom(), &((char*)data)[idat], ndat);
 | 
|---|
 | 596 |             }
 | 
|---|
 | 597 |         }
 | 
|---|
 | 598 |     }
 | 
|---|
 | 599 | }
 | 
|---|
 | 600 | 
 | 
|---|
 | 601 | void
 | 
|---|
 | 602 | MessageGrp::sync()
 | 
|---|
 | 603 | {
 | 
|---|
 | 604 |   Ref<GlobalMsgIter> i(topology_->global_msg_iter(this, 0));
 | 
|---|
 | 605 | 
 | 
|---|
 | 606 |   for (i->backwards(); !i->done(); i->next()) {
 | 
|---|
 | 607 |       if (i->send()) {
 | 
|---|
 | 608 |           raw_send(i->sendto(), 0, 0);
 | 
|---|
 | 609 |         }
 | 
|---|
 | 610 |       if (i->recv()) {
 | 
|---|
 | 611 |           raw_recv(i->recvfrom(), 0, 0);
 | 
|---|
 | 612 |         }
 | 
|---|
 | 613 |     }
 | 
|---|
 | 614 |   
 | 
|---|
 | 615 |   for (i->forwards(); !i->done(); i->next()) {
 | 
|---|
 | 616 |       if (i->send()) {
 | 
|---|
 | 617 |           raw_send(i->sendto(), 0, 0);
 | 
|---|
 | 618 |         }
 | 
|---|
 | 619 |       if (i->recv()) {
 | 
|---|
 | 620 |           raw_recv(i->recvfrom(), 0, 0);
 | 
|---|
 | 621 |         }
 | 
|---|
 | 622 |     }
 | 
|---|
 | 623 | }
 | 
|---|
 | 624 | 
 | 
|---|
 | 625 | void
 | 
|---|
 | 626 | MessageGrp::collect(const double *part, const int *lengths, double *whole)
 | 
|---|
 | 627 | {
 | 
|---|
 | 628 |   raw_collect(part,lengths,whole,sizeof(double));
 | 
|---|
 | 629 | }
 | 
|---|
 | 630 | 
 | 
|---|
 | 631 | void
 | 
|---|
 | 632 | MessageGrp::raw_collect(const void *part, const int *lengths, void *whole,
 | 
|---|
 | 633 |                         int bytes_per_datum)
 | 
|---|
 | 634 | {
 | 
|---|
 | 635 |   int offset = 0;
 | 
|---|
 | 636 |   for (int i=0; i<n_; i++) {
 | 
|---|
 | 637 |       int nbytes = lengths[i];
 | 
|---|
 | 638 |       if (i==me_) memcpy(&((char*)whole)[offset], part, nbytes);
 | 
|---|
 | 639 |       raw_bcast(&((char*)whole)[offset], nbytes, i);
 | 
|---|
 | 640 |       offset += nbytes;
 | 
|---|
 | 641 |     }
 | 
|---|
 | 642 | }
 | 
|---|
 | 643 | 
 | 
|---|
 | 644 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 645 | 
 | 
|---|
 | 646 | // Local Variables:
 | 
|---|
 | 647 | // mode: c++
 | 
|---|
 | 648 | // c-file-style: "CLJ"
 | 
|---|
 | 649 | // End:
 | 
|---|