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