00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "vcom_p.h"
00035
00036 VEMBED(rcsid="$Id: vcom.c,v 1.24 2008/03/12 05:13:58 fetk Exp $")
00037
00038
00039
00040
00041
00042
00043 #if !defined(VINLINE_MALOC)
00044
00045 #endif
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 VPUBLIC int Vcom_init(int *argc, char ***argv)
00063 {
00064 #if defined(HAVE_MPI_H)
00065 return (MPI_SUCCESS == MPI_Init(argc,argv));
00066 #else
00067 return 1;
00068 #endif
00069 }
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 VPUBLIC int Vcom_finalize(void)
00081 {
00082 #if defined(HAVE_MPI_H)
00083 return (MPI_SUCCESS == MPI_Finalize());
00084 #else
00085 return 1;
00086 #endif
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 VPUBLIC Vcom* Vcom_ctor(int commtype)
00101 {
00102 int rc;
00103 Vcom *thee = VNULL;
00104
00105
00106 thee = Vmem_malloc( VNULL, 1, sizeof(Vcom) );
00107 thee->core = Vmem_malloc( VNULL, 1, sizeof(Vcom_core) );
00108
00109
00110 rc = Vcom_ctor2(thee, commtype);
00111
00112
00113 if (rc == 0) {
00114 Vmem_free( VNULL, 1, sizeof(Vcom_core), (void**)&(thee->core) );
00115 Vmem_free( VNULL, 1, sizeof(Vcom), (void**)&thee );
00116 }
00117
00118 return thee;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 VPUBLIC int Vcom_ctor2(Vcom *thee, int commtype)
00135 {
00136 int rc = 0;
00137
00138 #if defined(HAVE_MPI_H)
00139 char estr[MPI_MAX_ERROR_STRING];
00140 int elen, dummy;
00141 Vcom_core *core = thee->core;
00142 #endif
00143
00144
00145
00146
00147
00148 switch ( commtype ) {
00149 case 1:
00150 thee->type = commtype;
00151
00152 #if defined(HAVE_MPI_H)
00153
00154
00155 rc = MPI_Initialized(&dummy);
00156 if (rc != MPI_SUCCESS) {
00157 MPI_Error_string(rc, estr, &elen);
00158 Vnm_print(2, "Vcom_ctor2: MPI_Init returned error: %s\n",
00159 estr);
00160 return 0;
00161 }
00162
00163
00164 rc = MPI_Comm_size(MPI_COMM_WORLD, &(thee->mpi_size));
00165 if (rc != MPI_SUCCESS) {
00166 MPI_Error_string(rc, estr, &elen);
00167 Vnm_print(2, "Vcom_ctor2: MPI_Comm_size returned error: %s\n",
00168 estr);
00169 return 0;
00170 }
00171
00172
00173 rc = MPI_Comm_rank(MPI_COMM_WORLD, &(thee->mpi_rank));
00174 if (rc != MPI_SUCCESS) {
00175 MPI_Error_string(rc, estr, &elen);
00176 Vnm_print(2, "Vcom_ctor2: MPI_Comm_rank returned error: %s\n",
00177 estr);
00178 return 0;
00179 }
00180
00181
00182 core->mpi_comm = MPI_COMM_WORLD;
00183
00184
00185 Vnm_setIoTag(thee->mpi_rank, thee->mpi_size);
00186
00187
00188 Vnm_print(2,"Vcom_ctor2: process %d of %d is ALIVE!\n",
00189 thee->mpi_rank, thee->mpi_size);
00190
00191 rc = 1;
00192 break;
00193
00194 #else
00195
00196
00197 rc = 1;
00198 break;
00199
00200 #endif
00201
00202 default:
00203 Vnm_print(2, "Vcom_ctor2: Invalid communications type!\n");
00204 rc = 0;
00205
00206 }
00207
00208 return rc;
00209 }
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 VPUBLIC int Vcom_resize(Vcom *thee, int newsize)
00226 {
00227 #if defined(HAVE_MPI_H)
00228 int color;
00229 MPI_Comm oldcomm;
00230 Vcom_core *core = thee->core;
00231 #endif
00232
00233 switch (thee->type) {
00234 case 1:
00235 #if defined(HAVE_MPI_H)
00236
00237 if (core->mpi_comm == MPI_COMM_NULL) return 1;
00238 Vcom_barr(thee);
00239
00240
00241 if (newsize > thee->mpi_size) {
00242 Vnm_print(2, "Vcom_resize: Requested number of processors (%d) greater than original size (%d)!\n", newsize, thee->mpi_size);
00243 return 0;
00244 }
00245 if (thee->mpi_rank < newsize) color = 0;
00246 else color = MPI_UNDEFINED;
00247 MPI_Comm_dup(core->mpi_comm, &oldcomm);
00248 if (MPI_Comm_split(oldcomm, color, 0, &(core->mpi_comm))
00249 != MPI_SUCCESS) {
00250 Vnm_print(2, "Vcom_resize: Failed to split communicator!\n");
00251 return 0;
00252 }
00253 MPI_Comm_free(&oldcomm);
00254 if (core->mpi_comm != MPI_COMM_NULL) {
00255 MPI_Comm_rank(core->mpi_comm, &(thee->mpi_rank));
00256 MPI_Comm_size(core->mpi_comm, &(thee->mpi_size));
00257 } else {
00258 thee->mpi_rank = -1;
00259 thee->mpi_size = 0;
00260 }
00261 Vnm_print(0, "Vcom_resize: New comm size = %d\n", thee->mpi_size);
00262 return 1;
00263 #else
00264 Vnm_print(2, "Vcom_resize: Not compiled with MPI!\n");
00265 return 0;
00266 #endif
00267 break;
00268 default:
00269 Vnm_print(2, "Vcom_resize: Invalid communications type!\n");
00270 return 0;
00271 }
00272 }
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 VPUBLIC void Vcom_dtor(Vcom **thee)
00284 {
00285 if ((*thee) != VNULL) {
00286 Vcom_dtor2(*thee);
00287 Vmem_free( VNULL, 1, sizeof(Vcom_core), (void**)&((*thee)->core) );
00288 Vmem_free( VNULL, 1, sizeof(Vcom), (void**)thee );
00289 }
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 VPUBLIC void Vcom_dtor2(Vcom *thee)
00304 {
00305 #if defined(HAVE_MPI_H)
00306 int err;
00307 Vcom_core *core = thee->core;
00308 #endif
00309
00310
00311
00312
00313
00314 switch (thee->type) {
00315
00316 case 1:
00317 #if defined(HAVE_MPI_H)
00318
00319 if ((core->mpi_comm != MPI_COMM_NULL) &&
00320 (core->mpi_comm != MPI_COMM_WORLD)) {
00321 Vnm_print(0, "Vcom_dtor2: Freeing MPI communicator...\n");
00322 MPI_Comm_free(&(core->mpi_comm));
00323 }
00324
00325 #if 0
00326 err = MPI_Finalize();
00327 if (err != MPI_SUCCESS) {
00328 Vnm_print(2, "Vcom_dtor2: MPI_Finalize returned %d\n", err);
00329 }
00330 #endif
00331 #endif
00332 default:
00333 return;
00334 }
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 VPUBLIC int Vcom_send(Vcom *thee, int des, void *buf, int len, int type,
00359 int block)
00360 {
00361 #if defined(HAVE_MPI_H)
00362 int tag = VCOM_MPI_TAG;
00363 MPI_Datatype datatype;
00364 Vcom_core *core = thee->core;
00365 #endif
00366
00367 int err = 1;
00368
00369
00370 VASSERT(thee != VNULL);
00371
00372 if (thee->error != 0) {
00373 Vnm_print(2, "Vcom_send: Have non-zero error state (%d)!\n",
00374 thee->error);
00375 return 0;
00376 }
00377
00378
00379 #if defined(HAVE_MPI_H)
00380 switch(type) {
00381 case 0:
00382 datatype = MPI_BYTE;
00383 break;
00384 case 1:
00385 datatype = MPI_INT;
00386 break;
00387 case 2:
00388 datatype = MPI_DOUBLE;
00389 break;
00390 case 3:
00391 datatype = MPI_CHAR;
00392 break;
00393 default:
00394 Vnm_print(2, "Vcom_send: Bogus datatype (%d), bailing!\n", type);
00395 return 0;
00396 }
00397 #endif
00398
00399
00400 switch(thee->type) {
00401
00402 case 1:
00403 #if defined(HAVE_MPI_H)
00404 if (core->mpi_comm == MPI_COMM_NULL) return 1;
00405
00406 if (block == 1) {
00407 err = MPI_Send(buf, len, datatype, des, tag, core->mpi_comm);
00408 err = (MPI_SUCCESS == err);
00409 } else {
00410 err = MPI_Isend(buf, len, datatype, des, tag, core->mpi_comm,
00411 &(core->mpi_request));
00412 err = (MPI_SUCCESS == err);
00413 }
00414 #else
00415 Vnm_print(2, "Vcom_send: Vcom not compiled with MPI!\n");
00416 return 0;
00417 #endif
00418 break;
00419 default:
00420 Vnm_print(2, "Vcom_send: Invalid communications type!\n");
00421 return 0;
00422 }
00423
00424 return err;
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 VPUBLIC int Vcom_recv(Vcom *thee, int src, void *buf, int len, int type,
00453 int block)
00454 {
00455 int err = 0;
00456
00457 #if defined(HAVE_MPI_H)
00458 int tag = VCOM_MPI_TAG;
00459 MPI_Datatype datatype;
00460 Vcom_core *core = thee->core;
00461 #endif
00462
00463
00464 VASSERT(thee != VNULL);
00465 if (thee->error != 0) {
00466 Vnm_print(2, "Vcom_send: Have non-zero error state (%d)!\n",
00467 thee->error);
00468 return 0;
00469 }
00470
00471
00472 #if defined(HAVE_MPI_H)
00473 switch(type) {
00474 case 0:
00475 datatype = MPI_BYTE;
00476 break;
00477 case 1:
00478 datatype = MPI_INT;
00479 break;
00480 case 2:
00481 datatype = MPI_DOUBLE;
00482 break;
00483 case 3:
00484 datatype = MPI_CHAR;
00485 break;
00486 default:
00487 Vnm_print(2, "Vcom_recv: Bogus datatype (%d), bailing!\n", type);
00488 return 0;
00489 }
00490 #endif
00491
00492
00493 switch(thee->type) {
00494
00495 case 1:
00496 #if defined(HAVE_MPI_H)
00497 if (core->mpi_comm == MPI_COMM_NULL) return 1;
00498
00499 if (block == 1) {
00500 err = MPI_Recv(buf, len, datatype, src, tag,
00501 core->mpi_comm, &(core->mpi_status));
00502 err = (MPI_SUCCESS == err);
00503 } else {
00504 Vnm_print(2, "Vcom_recv: WARNING! Non-blocking receive not implemented!\n");
00505 return 0;
00506 }
00507 #else
00508 Vnm_print(2, "Vcom_recv: Vcom not compiled with MPI!\n");
00509 return 0;
00510 #endif
00511
00512 break;
00513 default:
00514 Vnm_print(2, "Vcom_recv: Invalid communications type!\n");
00515 return 0;
00516 }
00517 return err;
00518 }
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531 VPUBLIC int Vcom_size(Vcom *thee)
00532 {
00533 #if defined(HAVE_MPI_H)
00534 Vcom_core *core = thee->core;
00535 #endif
00536
00537 VASSERT(thee != VNULL);
00538
00539 if ( thee->type == 1) {
00540 #if defined(HAVE_MPI_H)
00541 if (core->mpi_comm == MPI_COMM_NULL) return 0;
00542 return thee->mpi_size;
00543 #else
00544 return 1;
00545 #endif
00546 } else { return -1; }
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 VPUBLIC int Vcom_rank(Vcom *thee)
00561 {
00562 #if defined(HAVE_MPI_H)
00563 Vcom_core *core = thee->core;
00564 #endif
00565
00566 VASSERT(thee != VNULL);
00567
00568 if ( thee->type == 1) {
00569 #if defined(HAVE_MPI_H)
00570 if (core->mpi_comm == MPI_COMM_NULL) return -1;
00571 return thee->mpi_rank;
00572 #else
00573 return 0;
00574 #endif
00575 } else { return -1; }
00576 }
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 VPUBLIC int Vcom_barr(Vcom *thee)
00590 {
00591 #if defined(HAVE_MPI_H)
00592 int err;
00593 Vcom_core *core = thee->core;
00594 #endif
00595
00596 VASSERT(thee != VNULL);
00597
00598 if ( thee->type == 1) {
00599
00600 #if defined(HAVE_MPI_H)
00601 if (core->mpi_comm != MPI_COMM_NULL) {
00602 err = MPI_Barrier(core->mpi_comm);
00603 return (err == MPI_SUCCESS);
00604 } else return 1;
00605 #else
00606 Vnm_print(2, "Vcom_barr: Vcom not compiled with MPI!\n");
00607 return 0;
00608 #endif
00609 } else {
00610 Vnm_print(2, "Vcom_barr: Invalid communications type!\n");
00611 return 0;
00612 }
00613 return 0;
00614 }
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 VPUBLIC int Vcom_getCount(Vcom *thee, int src, int *length, int type)
00634 {
00635 #if defined(HAVE_MPI_H)
00636 MPI_Datatype datatype;
00637 Vcom_core *core = thee->core;
00638 #endif
00639
00640 VASSERT(thee != VNULL);
00641
00642 #if defined(HAVE_MPI_H)
00643 switch(type) {
00644 case 0:
00645 datatype = MPI_BYTE;
00646 break;
00647 case 1:
00648 datatype = MPI_INT;
00649 break;
00650 case 2:
00651 datatype = MPI_DOUBLE;
00652 break;
00653 case 3:
00654 datatype = MPI_CHAR;
00655 break;
00656 default:
00657 Vnm_print(2,"Vcom_getCount: Bogus datatype (%d), bailing!\n",type);
00658 return 0;
00659 }
00660 #endif
00661
00662 if ( thee->type == 1) {
00663 #if defined(HAVE_MPI_H)
00664 if (core->mpi_comm == MPI_COMM_NULL) return 1;
00665 MPI_Probe(src, VCOM_MPI_TAG, core->mpi_comm, &(core->mpi_status));
00666 return MPI_Get_count(&(core->mpi_status), datatype, length);
00667 #else
00668 Vnm_print(2, "Vcom_getCount: Vcom not compiled with MPI!\n");
00669 return -1;
00670 #endif
00671 } else { return -1; }
00672 }
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703 VPUBLIC int Vcom_reduce(Vcom *thee, void *sendbuf, void *recvbuf, int length,
00704 int type, int op)
00705 {
00706 int memsize;
00707
00708 #if defined(HAVE_MPI_H)
00709 MPI_Datatype datatype;
00710 MPI_Op optype;
00711 Vcom_core *core = thee->core;
00712 #endif
00713
00714 VASSERT(thee != VNULL);
00715
00716 #if defined(HAVE_MPI_H)
00717 switch(type) {
00718 case 0:
00719 datatype = MPI_BYTE;
00720 break;
00721 case 1:
00722 datatype = MPI_INT;
00723 break;
00724 case 2:
00725 datatype = MPI_DOUBLE;
00726 break;
00727 case 3:
00728 datatype = MPI_CHAR;
00729 break;
00730 default:
00731 Vnm_print(2, "Vcom_recv: Bogus datatype (%d), bailing!\n", type);
00732 return 0;
00733 }
00734 switch(op) {
00735 case 0:
00736 optype = MPI_SUM;
00737 break;
00738 case 1:
00739 optype = MPI_PROD;
00740 break;
00741 case 2:
00742 optype = MPI_MIN;
00743 break;
00744 case 3:
00745 optype = MPI_MAX;
00746 break;
00747 default:
00748 Vnm_print(2, "Vcom_reduce: Bogus optype (%d), bailing!\n", type);
00749 return 0;
00750 }
00751 #endif
00752
00753 if ( thee->type == 1) {
00754
00755 #if defined(HAVE_MPI_H)
00756
00757 if (core->mpi_comm == MPI_COMM_NULL) return 1;
00758 return MPI_Allreduce(sendbuf, recvbuf, length, datatype, optype,
00759 core->mpi_comm);
00760
00761 #else
00762 Vnm_print(0, "Vcom_reduce: Not compiled with MPI, doing simple copy.\n");
00763 switch(type) {
00764 case 0:
00765 memsize = 1;
00766 break;
00767 case 1:
00768 memsize = sizeof(int);
00769 break;
00770 case 2:
00771 memsize = sizeof(double);
00772 break;
00773 case 3:
00774 memsize = sizeof(char);
00775 break;
00776 default:
00777 Vnm_print(2, "Vcom_recv: Bogus datatype (%d), bailing!\n", type);
00778 return 0;
00779 }
00780
00781 memcpy(recvbuf, sendbuf, memsize*length);
00782 return 1;
00783
00784 #endif
00785
00786 } else { return -1; }
00787 }
00788