00001
00002
00003
00004
00005
00006 #include "mpi.h"
00007 #include <stdio.h>
00008 #include <string.h>
00009 #include <stdlib.h>
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #define STARTING_SIZE 5000
00024
00025 int test_file(char *filename, int mynod, int nprocs, char * cb_hosts,
00026 char *msg, int verbose);
00027
00028 #define ADIOI_Free free
00029 #define ADIOI_Malloc malloc
00030 #define FPRINTF fprintf
00031
00032
00033 struct ADIO_cb_name_arrayD {
00034 int refct;
00035 int namect;
00036 char **names;
00037 };
00038 typedef struct ADIO_cb_name_arrayD *ADIO_cb_name_array;
00039
00040 void handle_error(int errcode, char *str);
00041 int cb_gather_name_array(MPI_Comm comm, ADIO_cb_name_array *arrayp);
00042 void default_str(int mynod, int len, ADIO_cb_name_array array, char *dest);
00043 void reverse_str(int mynod, int len, ADIO_cb_name_array array, char *dest);
00044 void reverse_alternating_str(int mynod, int len, ADIO_cb_name_array array, char *dest);
00045 void simple_shuffle_str(int mynod, int len, ADIO_cb_name_array array, char *dest);
00046
00047
00048 void handle_error(int errcode, char *str)
00049 {
00050 char msg[MPI_MAX_ERROR_STRING];
00051 int resultlen;
00052 MPI_Error_string(errcode, msg, &resultlen);
00053 fprintf(stderr, "%s: %s\n", str, msg);
00054 MPI_Abort(MPI_COMM_WORLD, 1);
00055 }
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 int cb_gather_name_array(MPI_Comm comm, ADIO_cb_name_array *arrayp)
00071 {
00072
00073
00074
00075
00076
00077 char my_procname[MPI_MAX_PROCESSOR_NAME], **procname = 0;
00078 int *procname_len = NULL, my_procname_len, *disp = NULL, i;
00079 int commsize, commrank;
00080 ADIO_cb_name_array array = NULL;
00081
00082 MPI_Comm_size(comm, &commsize);
00083 MPI_Comm_rank(comm, &commrank);
00084
00085 MPI_Get_processor_name(my_procname, &my_procname_len);
00086
00087
00088 array = (ADIO_cb_name_array) malloc(sizeof(*array));
00089 if (array == NULL) {
00090 return -1;
00091 }
00092 array->refct = 1;
00093
00094 if (commrank == 0) {
00095
00096 array->namect = commsize;
00097
00098 array->names = (char **) ADIOI_Malloc(sizeof(char *) * commsize);
00099 if (array->names == NULL) {
00100 return -1;
00101 }
00102 procname = array->names;
00103
00104 procname_len = (int *) ADIOI_Malloc(commsize * sizeof(int));
00105 if (procname_len == NULL) {
00106 return -1;
00107 }
00108 }
00109 else {
00110
00111 array->namect = 0;
00112 array->names = NULL;
00113 }
00114
00115 MPI_Gather(&my_procname_len, 1, MPI_INT,
00116 procname_len, 1, MPI_INT, 0, comm);
00117
00118 if (commrank == 0) {
00119 #ifdef CB_CONFIG_LIST_DEBUG
00120 for (i=0; i < commsize; i++) {
00121 FPRINTF(stderr, "len[%d] = %d\n", i, procname_len[i]);
00122 }
00123 #endif
00124
00125 for (i=0; i < commsize; i++) {
00126
00127
00128
00129
00130 procname_len[i]++;
00131 procname[i] = malloc(procname_len[i]);
00132 if (procname[i] == NULL) {
00133 return -1;
00134 }
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 disp = malloc(commsize * sizeof(int));
00146 disp[0] = 0;
00147 for (i=1; i < commsize; i++) {
00148 disp[i] = (int) (procname[i] - procname[0]);
00149 }
00150
00151 }
00152
00153
00154 if (commrank == 0) {
00155 MPI_Gatherv(my_procname, my_procname_len + 1, MPI_CHAR,
00156 procname[0], procname_len, disp, MPI_CHAR,
00157 0, comm);
00158 }
00159 else {
00160
00161
00162
00163 MPI_Gatherv(my_procname, my_procname_len + 1, MPI_CHAR,
00164 NULL, NULL, NULL, MPI_CHAR, 0, comm);
00165 }
00166
00167 if (commrank == 0) {
00168
00169 free(disp);
00170 free(procname_len);
00171
00172 #ifdef CB_CONFIG_LIST_DEBUG
00173 for (i=0; i < commsize; i++) {
00174 fprintf(stderr, "name[%d] = %s\n", i, procname[i]);
00175 }
00176 #endif
00177 }
00178
00179 *arrayp = array;
00180 return 0;
00181 }
00182
00183 void default_str(int mynod, int len, ADIO_cb_name_array array, char *dest)
00184 {
00185 char *ptr;
00186 int i, p;
00187 if (!mynod) {
00188 ptr = dest;
00189 for (i=0; i<array->namect; i++ ) {
00190 p = snprintf(ptr, len, "%s,", array->names[i]);
00191 ptr += p;
00192 }
00193
00194 dest[strlen(dest) - 1] = '\0';
00195 }
00196 MPI_Bcast(dest, len, MPI_CHAR, 0, MPI_COMM_WORLD);
00197 }
00198 void reverse_str(int mynod, int len, ADIO_cb_name_array array, char *dest)
00199 {
00200 char *ptr;
00201 int i, p;
00202 if (!mynod) {
00203 ptr = dest;
00204 for (i=(array->namect - 1); i >= 0; i-- ) {
00205 p = snprintf(ptr, len, "%s,", array->names[i]);
00206 ptr += p;
00207 }
00208 dest[strlen(dest) - 1] = '\0';
00209 }
00210 MPI_Bcast(dest, len, MPI_CHAR, 0, MPI_COMM_WORLD);
00211 }
00212
00213 void reverse_alternating_str(int mynod, int len, ADIO_cb_name_array array, char *dest)
00214 {
00215 char *ptr;
00216 int i, p;
00217 if (!mynod) {
00218 ptr = dest;
00219
00220 for (i=(array->namect - 1); i>= 0; i-=2 ) {
00221 p = snprintf(ptr, len, "%s,", array->names[i]);
00222 ptr += p;
00223 }
00224
00225 for (i=(array->namect - 2); i > 0; i-=2 ) {
00226 p = snprintf(ptr, len, "%s,", array->names[i]);
00227 ptr += p;
00228 }
00229 dest[strlen(dest) - 1] = '\0';
00230 }
00231 MPI_Bcast(dest, len, MPI_CHAR, 0, MPI_COMM_WORLD);
00232 }
00233
00234 void simple_shuffle_str(int mynod, int len, ADIO_cb_name_array array, char *dest)
00235 {
00236 char *ptr;
00237 int i, p;
00238 if (!mynod) {
00239 ptr = dest;
00240 for (i=(array->namect / 2 ); i < array->namect; i++) {
00241 p = snprintf(ptr, len, "%s,", array->names[i]);
00242 ptr += p;
00243 }
00244 for (i=0; i < (array->namect / 2); i++ ) {
00245 p = snprintf(ptr, len, "%s,", array->names[i]);
00246 ptr += p;
00247 }
00248 dest[strlen(dest) - 1] = '\0';
00249 }
00250 MPI_Bcast(dest, len, MPI_CHAR, 0, MPI_COMM_WORLD);
00251 }
00252
00253 int main(int argc, char **argv)
00254 {
00255 int i, mynod, nprocs, len, errs=0, sum_errs=0, verbose=0;
00256 char *filename;
00257 char * cb_config_string;
00258 int cb_config_len;
00259 ADIO_cb_name_array array;
00260
00261
00262 MPI_Init(&argc,&argv);
00263 MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
00264 MPI_Comm_rank(MPI_COMM_WORLD, &mynod);
00265
00266
00267
00268
00269 if (!mynod) {
00270 i = 1;
00271
00272 while ((i < argc) && strcmp("-fname", *argv)) {
00273 i++;
00274 argv++;
00275 }
00276 if (i >= argc) {
00277 fprintf(stderr, "\n*# Usage: noncontig_coll -fname filename\n\n");
00278 MPI_Abort(MPI_COMM_WORLD, 1);
00279 }
00280 argv++;
00281 len = strlen(*argv);
00282 filename = (char *) malloc(len+1);
00283 strcpy(filename, *argv);
00284 MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD);
00285 MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD);
00286 }
00287 else {
00288 MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD);
00289 filename = (char *) malloc(len+1);
00290 MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD);
00291 }
00292
00293
00294 cb_gather_name_array(MPI_COMM_WORLD, &array);
00295
00296
00297 if (!mynod) {
00298 if (array->namect < 2 ) {
00299 fprintf(stderr, "Run this test on two or more hosts\n");
00300 MPI_Abort(MPI_COMM_WORLD, 1);
00301 }
00302 }
00303
00304 if (!mynod) {
00305 cb_config_len = 0;
00306 for (i=0; i < array->namect; i++) {
00307
00308 cb_config_len += strlen(array->names[i]) + 1;
00309 }
00310 ++cb_config_len;
00311 }
00312 MPI_Bcast(&cb_config_len, 1, MPI_INT, 0, MPI_COMM_WORLD);
00313 if ( (cb_config_string = malloc(cb_config_len)) == NULL ) {
00314 perror("malloc");
00315 MPI_Abort(MPI_COMM_WORLD, 1);
00316 }
00317
00318
00319 errs += test_file(filename, mynod, nprocs, NULL, "collective w/o hinting", verbose);
00320
00321
00322 default_str(mynod, cb_config_len, array, cb_config_string);
00323 errs += test_file(filename, mynod, nprocs, cb_config_string, "collective w/ hinting: default order", verbose);
00324
00325
00326 reverse_str(mynod, cb_config_len, array, cb_config_string);
00327 errs += test_file(filename, mynod, nprocs, cb_config_string, "collective w/ hinting: reverse order", verbose);
00328
00329
00330 reverse_alternating_str(mynod, cb_config_len, array, cb_config_string);
00331 errs += test_file(filename, mynod, nprocs, cb_config_string,"collective w/ hinting: permutation1", verbose);
00332
00333
00334 simple_shuffle_str(mynod, cb_config_len, array, cb_config_string);
00335 errs += test_file(filename, mynod, nprocs, cb_config_string, "collective w/ hinting: permutation2", verbose);
00336
00337 MPI_Allreduce(&errs, &sum_errs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
00338
00339 if (!mynod) {
00340 if (sum_errs) fprintf(stderr, "Found %d error cases\n", sum_errs);
00341 else printf(" No Errors\n");
00342 }
00343 free(filename);
00344 free(cb_config_string);
00345 MPI_Finalize();
00346 return 0;
00347 }
00348
00349 #define SEEDER(x,y,z) ((x)*1000000 + (y) + (x)*(z))
00350
00351 int test_file(char *filename, int mynod, int nprocs, char * cb_hosts, char *msg, int verbose)
00352 {
00353 MPI_Datatype typevec, newtype, t[3];
00354 int *buf, i, b[3], errcode, errors=0;
00355 MPI_File fh;
00356 MPI_Aint d[3];
00357 MPI_Status status;
00358 int SIZE = (STARTING_SIZE/nprocs)*nprocs;
00359 MPI_Info info;
00360
00361 if (mynod==0 && verbose) fprintf(stderr, "%s\n", msg);
00362
00363 buf = (int *) malloc(SIZE*sizeof(int));
00364 if (buf == NULL) {
00365 perror("test_file");
00366 MPI_Abort(MPI_COMM_WORLD, -1);
00367 }
00368
00369
00370 if (cb_hosts != NULL ) {
00371 MPI_Info_create(&info);
00372 MPI_Info_set(info, "cb_config_list", cb_hosts);
00373 } else {
00374 info = MPI_INFO_NULL;
00375 }
00376
00377 MPI_Type_vector(SIZE/nprocs, 1, nprocs, MPI_INT, &typevec);
00378
00379 b[0] = b[1] = b[2] = 1;
00380 d[0] = 0;
00381 d[1] = mynod*sizeof(int);
00382 d[2] = SIZE*sizeof(int);
00383 t[0] = MPI_LB;
00384 t[1] = typevec;
00385 t[2] = MPI_UB;
00386
00387 MPI_Type_struct(3, b, d, t, &newtype);
00388 MPI_Type_commit(&newtype);
00389 MPI_Type_free(&typevec);
00390
00391 if (!mynod) {
00392 if(verbose) fprintf(stderr, "\ntesting noncontiguous in memory, noncontiguous in file using collective I/O\n");
00393 MPI_File_delete(filename, info);
00394 }
00395 MPI_Barrier(MPI_COMM_WORLD);
00396
00397 errcode = MPI_File_open(MPI_COMM_WORLD, filename,
00398 MPI_MODE_CREATE | MPI_MODE_RDWR, info, &fh);
00399 if (errcode != MPI_SUCCESS) {
00400 handle_error(errcode, "MPI_File_open");
00401 }
00402
00403 MPI_File_set_view(fh, 0, MPI_INT, newtype, "native", info);
00404
00405 for (i=0; i<SIZE; i++) buf[i] = SEEDER(mynod,i,SIZE);
00406 errcode = MPI_File_write_all(fh, buf, 1, newtype, &status);
00407 if (errcode != MPI_SUCCESS) {
00408 handle_error(errcode, "nc mem - nc file: MPI_File_write_all");
00409 }
00410
00411 MPI_Barrier(MPI_COMM_WORLD);
00412
00413 for (i=0; i<SIZE; i++) buf[i] = -1;
00414
00415 errcode = MPI_File_read_at_all(fh, 0, buf, 1, newtype, &status);
00416 if (errcode != MPI_SUCCESS) {
00417 handle_error(errcode, "nc mem - nc file: MPI_File_read_at_all");
00418 }
00419
00420
00421
00422
00423
00424
00425
00426
00427 for (i=0; i<mynod; i++ ) {
00428 if ( buf[i] != -1 ) {
00429 if(verbose) fprintf(stderr, "Process %d: buf is %d, should be -1\n", mynod, buf[i]);
00430 errors++;
00431 }
00432 }
00433
00434
00435
00436
00437 for(; i<SIZE; i++) {
00438 if ( ((i-mynod)%nprocs) && buf[i] != -1) {
00439 if(verbose) fprintf(stderr, "Process %d: buf %d is %d, should be -1\n",
00440 mynod, i, buf[i]);
00441 errors++;
00442 }
00443 if ( !((i-mynod)%nprocs) && buf[i] != SEEDER(mynod,i,SIZE) ) {
00444 if(verbose) fprintf(stderr, "Process %d: buf %d is %d, should be %d\n",
00445 mynod, i, buf[i], SEEDER(mynod,i,SIZE));
00446 errors++;
00447 }
00448 }
00449 MPI_File_close(&fh);
00450
00451 MPI_Barrier(MPI_COMM_WORLD);
00452
00453 if (!mynod) {
00454 if(verbose) fprintf(stderr, "\ntesting noncontiguous in memory, contiguous in file using collective I/O\n");
00455 MPI_File_delete(filename, info);
00456 }
00457 MPI_Barrier(MPI_COMM_WORLD);
00458
00459 MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_CREATE | MPI_MODE_RDWR,
00460 info, &fh);
00461
00462 for (i=0; i<SIZE; i++) buf[i] = SEEDER(mynod,i,SIZE);
00463 errcode = MPI_File_write_at_all(fh, mynod*(SIZE/nprocs)*sizeof(int),
00464 buf, 1, newtype, &status);
00465 if (errcode != MPI_SUCCESS)
00466 handle_error(errcode, "nc mem - c file: MPI_File_write_at_all");
00467
00468 MPI_Barrier(MPI_COMM_WORLD);
00469
00470 for (i=0; i<SIZE; i++) buf[i] = -1;
00471
00472 errcode = MPI_File_read_at_all(fh, mynod*(SIZE/nprocs)*sizeof(int),
00473 buf, 1, newtype, &status);
00474 if (errcode != MPI_SUCCESS)
00475 handle_error(errcode, "nc mem - c file: MPI_File_read_at_all");
00476
00477
00478 for (i=0; i<mynod; i++ ) {
00479 if ( buf[i] != -1 ) {
00480 if(verbose) fprintf(stderr, "Process %d: buf is %d, should be -1\n", mynod, buf[i]);
00481 errors++;
00482 }
00483 }
00484 for(; i<SIZE; i++) {
00485 if ( ((i-mynod)%nprocs) && buf[i] != -1) {
00486 if(verbose) fprintf(stderr, "Process %d: buf %d is %d, should be -1\n",
00487 mynod, i, buf[i]);
00488 errors++;
00489 }
00490 if ( !((i-mynod)%nprocs) && buf[i] != SEEDER(mynod,i,SIZE)) {
00491 if(verbose) fprintf(stderr, "Process %d: buf %d is %d, should be %d\n",
00492 mynod, i, buf[i], SEEDER(mynod,i,SIZE) );
00493 errors++;
00494 }
00495 }
00496
00497 MPI_File_close(&fh);
00498
00499 MPI_Barrier(MPI_COMM_WORLD);
00500
00501 if (!mynod) {
00502 if(verbose) fprintf(stderr, "\ntesting contiguous in memory, noncontiguous in file using collective I/O\n");
00503 MPI_File_delete(filename, info);
00504 }
00505 MPI_Barrier(MPI_COMM_WORLD);
00506
00507 MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_CREATE | MPI_MODE_RDWR,
00508 info, &fh);
00509
00510 MPI_File_set_view(fh, 0, MPI_INT, newtype, "native", info);
00511
00512 for (i=0; i<SIZE; i++) buf[i] = SEEDER(mynod, i, SIZE);
00513 errcode = MPI_File_write_all(fh, buf, SIZE, MPI_INT, &status);
00514 if (errcode != MPI_SUCCESS)
00515 handle_error(errcode, "c mem - nc file: MPI_File_write_all");
00516
00517 MPI_Barrier(MPI_COMM_WORLD);
00518
00519 for (i=0; i<SIZE; i++) buf[i] = -1;
00520
00521 errcode = MPI_File_read_at_all(fh, 0, buf, SIZE, MPI_INT, &status);
00522 if (errcode != MPI_SUCCESS)
00523 handle_error(errcode, "c mem - nc file: MPI_File_read_at_all");
00524
00525
00526 for (i=0; i<SIZE; i++) {
00527 if (buf[i] != SEEDER(mynod, i, SIZE)) {
00528 if(verbose) fprintf(stderr, "Process %d: buf %d is %d, should be %d\n", mynod, i, buf[i], SEEDER(mynod, i, SIZE));
00529 errors++;
00530 }
00531 }
00532
00533 MPI_File_close(&fh);
00534
00535 MPI_Type_free(&newtype);
00536 free(buf);
00537 if (info != MPI_INFO_NULL) MPI_Info_free(&info);
00538 return errors;
00539 }