Skip to content

Commit 8fd929a

Browse files
committed
add struct_fsize.c
1 parent ef7459b commit 8fd929a

File tree

4 files changed

+193
-5
lines changed

4 files changed

+193
-5
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ check_PROGRAMS = mpi_file_set_view \
99
ghost_cell \
1010
indexed_fsize \
1111
hindexed_fsize \
12-
nvars
12+
nvars \
13+
struct_fsize
1314

1415
all: $(check_PROGRAMS)
1516

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
concatenated by MPI_Type_create_hindexed(). Each variable is partitioned
3131
among processes in a 2D block-block fashion. At the end, it checks the file
3232
size whether or not it is expected.
33+
* struct_fsize.c
34+
* Similar to indexed_fsize.c, but using MPI_Type_create_struct() to
35+
concatenate multiple subarray datatypes.
3336
* nvars.c
3437
* Makes a single call to collective write and read by using a fileview of
3538
concatenating multiple subarrays of variables stored in the file and each

struct_fsize.c

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2+
*
3+
* Copyright (C) 2024, Northwestern University
4+
* See COPYRIGHT notice in top-level directory.
5+
*
6+
* This program tests collective write using a file datatype constructed from
7+
* multiple subarray datatypes concatenated by MPI_Type_create_hindexed(). Each
8+
* variable is partitioned among processes in a 2D block-block fashion. At the
9+
* end, it checks the file size whether or not it is expected.
10+
*
11+
* This program is the same as indexed_fsize.c, except it calls
12+
* MPI_Type_create_hindexed(), while indexed_fsize.c.c calls
13+
* MPI_Type_hindexed().
14+
*
15+
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16+
17+
#include <stdio.h>
18+
#include <stdlib.h>
19+
#include <string.h>
20+
#include <unistd.h>
21+
#include <fcntl.h>
22+
#include <sys/types.h>
23+
24+
#include <mpi.h>
25+
26+
#define ERR \
27+
if (err != MPI_SUCCESS) { \
28+
int errorStringLen; \
29+
char errorString[MPI_MAX_ERROR_STRING]; \
30+
MPI_Error_string(err, errorString, &errorStringLen); \
31+
printf("Error at line %d: %s\n",__LINE__,errorString); \
32+
nerrs++; \
33+
goto err_out; \
34+
}
35+
36+
static void
37+
usage(char *argv0)
38+
{
39+
char *help =
40+
"Usage: %s [-hvrc | -n num | -l len ] -f file_name\n"
41+
" [-h] Print this help\n"
42+
" [-v] verbose mode\n"
43+
" [-n num] number of variables to be written\n"
44+
" [-l len] length of local X and Y dimension sizes\n"
45+
" -f filename: output file name\n";
46+
fprintf(stderr, help, argv0);
47+
}
48+
49+
/*----< main() >------------------------------------------------------------*/
50+
int main(int argc, char **argv)
51+
{
52+
extern int optind;
53+
extern char *optarg;
54+
char filename[256], *buf;
55+
int i, rank, nprocs, err, nerrs=0, verbose, omode, nvars, len;
56+
int psizes[2], sizes[2], subsizes[2], starts[2], *blks;
57+
MPI_Aint *disp;
58+
MPI_Datatype *subTypes, fileType;
59+
MPI_File fh;
60+
MPI_Status status;
61+
MPI_Info info=MPI_INFO_NULL;
62+
63+
MPI_Init(&argc,&argv);
64+
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
65+
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
66+
67+
verbose = 0;
68+
nvars = 2; /* default number of variables */
69+
len = 10; /* default dimension size */
70+
filename[0] = '\0';
71+
72+
/* get command-line arguments */
73+
while ((i = getopt(argc, argv, "hvn:l:f:")) != EOF)
74+
switch(i) {
75+
case 'v': verbose = 1;
76+
break;
77+
case 'n': nvars = atoi(optarg);
78+
break;
79+
case 'l': len = atoi(optarg);
80+
break;
81+
case 'f': strcpy(filename, optarg);
82+
break;
83+
case 'h':
84+
default: if (rank==0) usage(argv[0]);
85+
MPI_Finalize();
86+
return 1;
87+
}
88+
89+
if (filename[0] == '\0') {
90+
if (rank==0) usage(argv[0]);
91+
MPI_Finalize();
92+
return 1;
93+
}
94+
95+
if (verbose && rank == 0) {
96+
printf("Number of MPI processes: %d\n",nprocs);
97+
printf("Number of varaibles: %d\n",nvars);
98+
printf("Each subarray is of size: %d x %d (int) = %zd\n",
99+
len, len, sizeof(int)*len*len);
100+
}
101+
102+
/* calculate number of processes along each dimension */
103+
psizes[0] = psizes[1] = 0;
104+
err = MPI_Dims_create(nprocs, 2, psizes); ERR
105+
106+
if (verbose)
107+
printf("%d: 2D rank IDs: %d, %d\n",rank,rank/psizes[1], rank%psizes[1]);
108+
109+
/* create a subarray datatype */
110+
subTypes = (MPI_Datatype*) malloc(sizeof(MPI_Datatype) * nvars);
111+
sizes[0] = len * psizes[0];
112+
sizes[1] = len * psizes[1];
113+
subsizes[0] = len;
114+
subsizes[1] = len;
115+
starts[0] = len * (rank / psizes[1]);
116+
starts[1] = len * (rank % psizes[1]);
117+
err = MPI_Type_create_subarray(2, sizes, subsizes, starts, MPI_ORDER_C,
118+
MPI_BYTE, &subTypes[0]); ERR
119+
120+
if (verbose)
121+
printf("%d: sizes=%d %d subsizes=%d %d starts=%d %d\n",rank,
122+
sizes[0],sizes[1], subsizes[0],subsizes[1], starts[0],starts[1]);
123+
124+
/* concatenate nvars subTypes into fileType */
125+
disp = (MPI_Aint*) malloc(sizeof(MPI_Aint) * nvars);
126+
blks = (int*) malloc(sizeof(int) * nvars);
127+
for (i=0; i<nvars; i++) {
128+
disp[i] = (MPI_Aint)i * sizes[0] * sizes[1];
129+
blks[i] = 1;
130+
if (i > 0) subTypes[i] = subTypes[0];
131+
}
132+
err = MPI_Type_create_struct(nvars, blks, disp, subTypes, &fileType); ERR
133+
err = MPI_Type_commit(&fileType); ERR
134+
135+
err = MPI_Type_free(&subTypes[0]); ERR
136+
free(disp);
137+
free(blks);
138+
139+
/* allocate I/O buffers */
140+
buf = (char*)malloc(nvars * len * len);
141+
142+
/* open file and truncate it to zero sized */
143+
omode = MPI_MODE_CREATE | MPI_MODE_RDWR;
144+
err = MPI_File_open(MPI_COMM_WORLD, filename, omode, info, &fh); ERR
145+
err = MPI_File_set_size(fh, 0); ERR
146+
147+
/* set the file view */
148+
err = MPI_File_set_view(fh, 0, MPI_BYTE, fileType, "native", info); ERR
149+
err = MPI_Type_free(&fileType); ERR
150+
151+
/* write to the file */
152+
err = MPI_File_write_all(fh, buf, len*len*nvars, MPI_BYTE, &status); ERR
153+
154+
/* flush and close the file */
155+
err = MPI_Barrier(MPI_COMM_WORLD); ERR
156+
err = MPI_File_sync(fh); ERR
157+
err = MPI_Barrier(MPI_COMM_WORLD); ERR
158+
err = MPI_File_close(&fh); ERR
159+
err = MPI_Barrier(MPI_COMM_WORLD); ERR
160+
161+
/* check file size */
162+
if (rank == 0) {
163+
int fd = open(filename, O_RDONLY, 0600);
164+
off_t fsize = lseek(fd, 0, SEEK_END);
165+
off_t expected = len * len * nvars * nprocs;
166+
if (fsize != expected) {
167+
printf("Error: expecting file size %lld, but got %lld\n", expected, fsize);
168+
err = 1;
169+
}
170+
else
171+
printf("Test passed\n");
172+
close(fd);
173+
}
174+
MPI_Bcast(&err, 1, MPI_INT, 0, MPI_COMM_WORLD);
175+
if (err > 0) nerrs++;
176+
free(buf);
177+
178+
err_out:
179+
MPI_Finalize();
180+
return (nerrs > 0);
181+
}
182+

test.sh

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ for f in ${check_PROGRAMS} ; do
1313
if test "$f" = "print_mpi_io_hints" ; then
1414
OPTS="testfile"
1515
elif test "$f" = "indexed_fsize" ; then
16-
OPTS="-q -f testfile"
17-
elif test "$f" = "nindexed_fsize" ; then
18-
OPTS="-q -f testfile"
16+
OPTS="-f testfile"
17+
elif test "$f" = "hindexed_fsize" ; then
18+
OPTS="-f testfile"
19+
elif test "$f" = "struct_fsize" ; then
20+
OPTS="-f testfile"
1921
elif test "$f" = "nvars" ; then
20-
OPTS="-q -r -f testfile"
22+
OPTS="-r -f testfile"
2123
fi
2224
CMD="${MPIRUN} ./$f ${OPTS}"
2325
echo "==========================================================="

0 commit comments

Comments
 (0)