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 }