/********************************************************************* * * Copyright (C) 2013, Northwestern University and Argonne National Laboratory * See COPYRIGHT notice in top-level directory. * *********************************************************************/ /* $Id$ */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This example, generalized from column_wise.c, makes a number of nonblocking * API calls, each writes a block of columns into a 2D integer array. In other * words, the I/O pattern is a blocked cyclic along X dimension. * * Each process writes NX columns in total. The block length is controlled by * block_len. In this example, block_len is set to 2. Blocks are layout in a * cyclic fashion in the file. This example can test if PnetCDF can coalesce * file offsets and lengths when constructing a merged filetype. * * The compile and run commands are given below, together with an ncmpidump of * the output file. In this example, block_len = 2. * * % mpicc -O2 -o block_cyclic block_cyclic.c -lpnetcdf * % mpiexec -l -n 4 ./block_cyclic /pvfs2/wkliao/testfile.nc * 0: 0: NY=10 myNX= 4 myOff= 0 * 1: 1: NY=10 myNX= 4 myOff= 4 * 2: 2: NY=10 myNX= 4 myOff= 8 * 3: 3: NY=10 myNX= 4 myOff= 12 * 0: [i=0] iput() start= 0 0 count= 10 1 * 0: [i=1] iput() start= 0 1 count= 10 1 * 0: [i=2] iput() start= 0 8 count= 10 1 * 0: [i=3] iput() start= 0 9 count= 10 1 * 1: [i=0] iput() start= 0 2 count= 10 1 * 1: [i=1] iput() start= 0 3 count= 10 1 * 1: [i=2] iput() start= 0 10 count= 10 1 * 1: [i=3] iput() start= 0 11 count= 10 1 * 2: [i=0] iput() start= 0 4 count= 10 1 * 2: [i=1] iput() start= 0 5 count= 10 1 * 2: [i=2] iput() start= 0 12 count= 10 1 * 2: [i=3] iput() start= 0 13 count= 10 1 * 3: [i=0] iput() start= 0 6 count= 10 1 * 3: [i=1] iput() start= 0 7 count= 10 1 * 3: [i=2] iput() start= 0 14 count= 10 1 * 3: [i=3] iput() start= 0 15 count= 10 1 * * % ncmpidump /pvfs2/wkliao/testfile.nc * netcdf testfile { * // file format: CDF-5 (big variables) * dimensions: * Y = 10 ; * X = 16 ; * variables: * int var(Y, X) ; * data: * * var = * 10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13, * 10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13, * 10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13, * 10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13, * 10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13, * 10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13, * 10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13, * 10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13, * 10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13, * 10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13 ; * } * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include /* strcpy(), strncpy() */ #include /* getopt() */ #include #include #include #define NY 10 #define NX 4 #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) #endif #define ERR {if(err!=NC_NOERR){printf("Error at line %d in %s: %s\n", __LINE__,__FILE__, ncmpi_strerror(err));nerrs++;}} static void usage(char *argv0) { char *help = "Usage: %s [-h] | [-q] [file_name]\n" " [-h] Print help\n" " [-q] Quiet mode (reports when fail)\n" " [filename] output netCDF file name\n"; fprintf(stderr, help, argv0); } int main(int argc, char** argv) { extern int optind; char filename[256]; int i, j, verbose=1, rank, nprocs, err, num_reqs, nerrs=0; int ncid, cmode, varid, dimid[2], *reqs, *sts, **buf; MPI_Offset myNX, G_NX, myOff, block_start, block_len; MPI_Offset start[2], count[2]; MPI_Info info; int bb_enabled=0; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nprocs); /* get command-line arguments */ while ((i = getopt(argc, argv, "hq")) != EOF) switch(i) { case 'q': verbose = 0; break; case 'h': default: if (rank==0) usage(argv[0]); MPI_Finalize(); return 1; } if (argv[optind] == NULL) strcpy(filename, "testfile.nc"); else snprintf(filename, 256, "%s", argv[optind]); /* set an MPI-IO hint to disable file offset alignment for fixed-size * variables */ MPI_Info_create(&info); MPI_Info_set(info, "nc_var_align_size", "1"); /* create a new file for writing ----------------------------------------*/ cmode = NC_CLOBBER | NC_64BIT_DATA; err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, info, &ncid); ERR { int flag; char hint[MPI_MAX_INFO_VAL]; MPI_Info infoused; ncmpi_inq_file_info(ncid, &infoused); MPI_Info_get(infoused, "nc_burst_buf", MPI_MAX_INFO_VAL - 1, hint, &flag); if (flag && strcasecmp(hint, "enable") == 0) bb_enabled = 1; MPI_Info_free(&infoused); } MPI_Info_free(&info); /* the global array is NY * (NX * nprocs) */ G_NX = NX * nprocs; myOff = NX * rank; myNX = NX; if (verbose) printf("%2d: NY=%d myNX=%3lld myOff=%3lld\n",rank,NY,myNX,myOff); err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]); ERR err = ncmpi_def_dim(ncid, "X", G_NX, &dimid[1]); ERR err = ncmpi_def_var(ncid, "var", NC_INT, 2, dimid, &varid); ERR err = ncmpi_enddef(ncid); ERR /* First, fill the entire array with zeros, using a blocking I/O. Every process writes a subarray of size NY * myNX */ buf = (int**) malloc(myNX * sizeof(int*)); buf[0] = (int*) calloc(NY * myNX, sizeof(int)); start[0] = 0; start[1] = myOff; count[0] = NY; count[1] = myNX; err = ncmpi_put_vara_int_all(ncid, varid, start, count, buf[0]); free(buf[0]); if (bb_enabled) { err = ncmpi_flush(ncid); ERR } /* initialize the buffer with rank ID. Also make the case interesting, by allocating buffers separately */ for (i=0; i myNX) block_len = myNX; start[0] = 0; start[1] = rank * block_len; count[0] = NY; count[1] = 1; num_reqs = 0; for (i=0; i 0) buf[i] = buf[i-1] + global_ny; for (j=0; j myNX) block_len = myNX; start[0] = 0; start[1] = rank * block_len; count[0] = global_ny; count[1] = 1; num_reqs = 0; for (i=0; i 0) printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n", sum_size); } MPI_Finalize(); return (nerrs > 0); }