/* * Setup hindexed-block type info and handlers. * * A hindexed-block datatype is created by using following parameters. * nblock: Number of blocks. * blocklen: Number of elements in each block. * stride: Strided number of elements between two adjacent blocks. The byte * displacement of each block is set as (index of current block * stride * size of oldtype). * lb: Lower bound of the new datatype. * oldtype: Datatype of element. */ static int MTestTypeHindexedBlockCreate(MPI_Aint nblock, MPI_Aint blocklen, MPI_Aint stride, MPI_Aint lb, MPI_Datatype oldtype, const char *typename_prefix, MTestDatatype * mtype) { int merr; char type_name[128]; int i; MTestTypeReset(mtype); merr = MPI_Type_size(oldtype, &mtype->basesize); if (merr) MTestPrintError(merr); mtype->displ_in_bytes = (MPI_Aint *) malloc(nblock * sizeof(MPI_Aint)); if (!mtype->displ_in_bytes) { char errmsg[128] = { 0 }; sprintf(errmsg, "Out of memory in %s", __FUNCTION__); MTestError(errmsg); } mtype->nblock = nblock; mtype->blksize = blocklen * mtype->basesize; for (i = 0; i < nblock; i++) { mtype->displ_in_bytes[i] = (lb + stride * i) * mtype->basesize; } /* Hindexed-block uses displacement in bytes */ merr = MPI_Type_create_hindexed_block(nblock, blocklen, mtype->displ_in_bytes, oldtype, &mtype->datatype); if (merr) MTestPrintError(merr); merr = MPI_Type_commit(&mtype->datatype); if (merr) MTestPrintError(merr); memset(type_name, 0, sizeof(type_name)); sprintf(type_name, "%s %s (%ld nblock %ld blocklen %ld stride %ld lb)", typename_prefix, "hindex_block", nblock, blocklen, stride, lb); merr = MPI_Type_set_name(mtype->datatype, (char *) type_name); if (merr) MTestPrintError(merr); /* Reuse indexed-block functions, because all of them only use displ_in_bytes */ mtype->InitBuf = MTestTypeIndexedBlockInit; mtype->FreeBuf = MTestTypeFree; mtype->CheckBuf = MTestTypeIndexedBlockCheckbuf; return merr; }
/* hindexed_block_contig_test() * * Tests behavior with a hindexed_block that can be converted to a * contig easily. This is specifically for coverage. * * Returns the number of errors encountered. */ int hindexed_block_contig_test(void) { int buf[4] = { 7, -1, -2, -3 }; int err, errs = 0; int i, count = 1; MPI_Aint disp = 0; MPI_Datatype newtype; int size, int_size; MPI_Aint extent; err = MPI_Type_create_hindexed_block(count, 1, &disp, MPI_INT, &newtype); if (err != MPI_SUCCESS) { if (verbose) { fprintf(stderr, "error creating struct type in hindexed_block_contig_test()\n"); } errs++; } MPI_Type_size(MPI_INT, &int_size); err = MPI_Type_size(newtype, &size); if (err != MPI_SUCCESS) { if (verbose) { fprintf(stderr, "error obtaining type size in hindexed_block_contig_test()\n"); } errs++; } if (size != int_size) { if (verbose) { fprintf(stderr, "error: size != int_size in hindexed_block_contig_test()\n"); } errs++; } err = MPI_Type_extent(newtype, &extent); if (err != MPI_SUCCESS) { if (verbose) { fprintf(stderr, "error obtaining type extent in hindexed_block_contig_test()\n"); } errs++; } if (extent != int_size) { if (verbose) { fprintf(stderr, "error: extent != int_size in hindexed_block_contig_test()\n"); } errs++; } MPI_Type_commit(&newtype); err = pack_and_unpack((char *) buf, 1, newtype, 4 * sizeof(int)); if (err != 0) { if (verbose) { fprintf(stderr, "error packing/unpacking in hindexed_block_contig_test()\n"); } errs += err; } for (i = 0; i < 4; i++) { int goodval; switch (i) { case 0: goodval = 7; break; default: goodval = 0; /* pack_and_unpack() zeros before unpack */ break; } if (buf[i] != goodval) { errs++; if (verbose) fprintf(stderr, "buf[%d] = %d; should be %d\n", i, buf[i], goodval); } } MPI_Type_free(&newtype); return errs; }
/* hindexed_block_vector_test() * * Tests behavior with a hindexed_block of some vector types; * this shouldn't be easily convertable into anything else. * * Returns the number of errors encountered. */ int hindexed_block_vector_test(void) { #define NELT (18) int buf[NELT] = { -1, -1, -1, 1, -2, 2, -3, -3, -3, -4, -4, -4, 3, -5, 4, 5, -6, 6 }; int expected[NELT] = { 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 3, 0, 4, 5, 0, 6 }; int err, errs = 0; int i, count = 3; MPI_Aint disp[] = { 1, 4, 5 }; MPI_Datatype vectype, newtype; int size, int_size; MPI_Aint extent; /* create a vector type of 2 ints, skipping one in between */ err = MPI_Type_vector(2, 1, 2, MPI_INT, &vectype); if (err != MPI_SUCCESS) { if (verbose) { fprintf(stderr, "error creating vector type in hindexed_block_contig_test()\n"); } errs++; } MPI_Type_commit(&vectype); MPI_Type_extent(vectype, &extent); for (i = 0; i < count; i++) disp[i] *= extent; err = MPI_Type_create_hindexed_block(count, 1, disp, vectype, &newtype); if (err != MPI_SUCCESS) { if (verbose) { fprintf(stderr, "error creating hindexed_block type in hindexed_block_contig_test()\n"); } errs++; } MPI_Type_commit(&newtype); err = MPI_Type_size(newtype, &size); if (err != MPI_SUCCESS) { if (verbose) { fprintf(stderr, "error obtaining type size in hindexed_block_contig_test()\n"); } errs++; } MPI_Type_size(MPI_INT, &int_size); if (size != 6 * int_size) { if (verbose) { fprintf(stderr, "error: size != 6 * int_size in hindexed_block_contig_test()\n"); } errs++; } MPI_Type_extent(newtype, &extent); err = pack_and_unpack((char *) buf, 1, newtype, NELT * sizeof(int)); if (err != 0) { if (verbose) { fprintf(stderr, "error packing/unpacking in hindexed_block_vector_test()\n"); } errs += err; } for (i = 0; i < NELT; i++) { if (buf[i] != expected[i]) { errs++; if (verbose) fprintf(stderr, "buf[%d] = %d; should be %d\n", i, buf[i], expected[i]); } } MPI_Type_free(&vectype); MPI_Type_free(&newtype); return errs; }
int main(int argc, char **argv) { MPI_File fh; MPI_Datatype file_type, mem_type; int *data = NULL; int *verify = NULL; int data_size = DATA_SIZE; int i, j, k, nr_errors = 0; MPI_Aint disp[BLK_COUNT]; int block_lens[BLK_COUNT]; char *filename = "unnamed.dat"; MPI_Status status; MPI_Request request; MPI_Init(&argc, &argv); disp[0] = (MPI_Aint) (PAD); disp[1] = (MPI_Aint) (data_size * 1 + PAD); disp[2] = (MPI_Aint) (data_size * 2 + PAD); block_lens[0] = data_size; block_lens[1] = data_size; block_lens[2] = data_size; data = malloc(data_size); verify = malloc(data_size * BLK_COUNT + HEADER + PAD); for (i = 0; i < data_size / sizeof(int); i++) data[i] = i; MPI_Type_create_hindexed_block(BLK_COUNT, data_size, disp, MPI_BYTE, &file_type); MPI_Type_commit(&file_type); MPI_Type_create_hvector(BLK_COUNT, data_size, 0, MPI_BYTE, &mem_type); MPI_Type_commit(&mem_type); if (1 < argc) filename = argv[1]; CHECK(MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_RDWR | MPI_MODE_CREATE | MPI_MODE_DELETE_ON_CLOSE, MPI_INFO_NULL, &fh) != 0); CHECK(MPI_File_set_view(fh, HEADER, MPI_BYTE, file_type, "native", MPI_INFO_NULL)); /* write everything */ CHECK(MPI_File_iwrite_at_all(fh, 0, data, 1, mem_type, &request)); MPI_Wait(&request, &status); /* verify */ CHECK(MPI_File_set_view(fh, 0, MPI_BYTE, MPI_BYTE, "native", MPI_INFO_NULL)); CHECK(MPI_File_iread_at_all(fh, 0, verify, (HEADER + PAD + BLK_COUNT * DATA_SIZE) / sizeof(int), MPI_INT, &request)); MPI_Wait(&request, &status); /* header and block padding should have no data */ for (i = 0; i < (HEADER + PAD) / sizeof(int); i++) { if (verify[i] != 0) { nr_errors++; fprintf(stderr, "expected 0, read %d\n", verify[i]); } } /* blocks are replicated */ for (j = 0; j < BLK_COUNT; j++) { for (k = 0; k < (DATA_SIZE / sizeof(int)); k++) { if (verify[(HEADER + PAD) / sizeof(int) + k + j * (DATA_SIZE / sizeof(int))] != data[k]) { nr_errors++; fprintf(stderr, "expcted %d, read %d\n", data[k], verify[(HEADER + PAD) / sizeof(int) + k + j * (DATA_SIZE / sizeof(int))]); } i++; } } MPI_File_close(&fh); MPI_Type_free(&mem_type); MPI_Type_free(&file_type); if (nr_errors == 0) printf(" No Errors\n"); MPI_Finalize(); free(data); return 0; }