1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3 *
4 * (C) 2008 by Argonne National Laboratory.
5 * See COPYRIGHT in top-level directory.
6 */
7 /* Wei-keng Liao (wkliao@ece.northwestern.edu) September 8, 2008 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <mpi.h>
12
13 #define YLEN 5
14 #define XLEN 10
15 #define SUB_XLEN 3
16
17 /* rjl: I was just too lazy to compute this at run-time */
18 char compare_buf[XLEN*4][YLEN*4] = {
19 {'0','1','2',0,0,'3','4','5',0,0,'D','E','F',0,0,'G','H','I'},
20 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
21 {'6','7','8',0,0,'9',':',';',0,0,'J','K','L',0,0,'M','N','O'},
22 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
23 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
24 {'X','Y','Z',0,0,'[','\\',']',0,0,'l','m','n',0,0,'o','p','q'},
25 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
26 {'^','_','`',0,0,'a','b','c',0,0,'r','s','t',0,0,'u','v','w'},
27 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
28 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
29 {'0','1','2',0,0,'3','4','5',0,0,'D','E','F',0,0,'G','H','I'},
30 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
31 {'6','7','8',0,0,'9',':',';',0,0,'J','K','L',0,0,'M','N','O'},
32 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
33 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
34 {'X','Y','Z',0,0,'[','\\',']',0,0,'l','m','n',0,0,'o','p','q'},
35 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
36 {'^','_','`',0,0,'a','b','c',0,0,'r','s','t',0,0,'u','v','w'},
37 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
38 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
39 };
40
41
42 /* set this if you want a dump of the global array
43 #define VERBOSE 1
44 */
45
46 /*----< main() >------------------------------------------------------------*/
main(int argc,char ** argv)47 int main(int argc, char **argv) {
48 int i, j, err, rank, np, num_io;
49 char *buf, *filename;
50 int rank_dim[2], array_of_sizes[2];
51 int array_of_subsizes[2];
52 int count, *blocklengths, global_array_size;
53 MPI_Count ftype_size;
54 MPI_Aint *displacements;
55 MPI_File fh;
56 MPI_Datatype ftype;
57 MPI_Status status;
58 MPI_Offset offset=0;
59 int nr_errors=0;
60 #ifdef VERBOSE
61 int k;
62 #endif
63
64 MPI_Init(&argc, &argv);
65 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
66 MPI_Comm_size(MPI_COMM_WORLD, &np);
67
68 if (np != 4) {
69 if (!rank) printf("Please run with 4 processes. Exiting ...\n\n");
70 MPI_Finalize();
71 return 1;
72 }
73
74 filename = argv[1];
75
76 num_io = 2;
77
78 /*-----------------------------------------------------------------------*/
79 /* process rank in each dimension */
80 rank_dim[0] = rank / 2;
81 rank_dim[1] = rank % 2;
82
83 /* global 2D array size */
84 array_of_sizes[0] = YLEN * 2;
85 array_of_sizes[1] = XLEN * 2;
86
87 global_array_size = array_of_sizes[0] * array_of_sizes[1];
88
89 array_of_subsizes[0] = YLEN / 2;
90 array_of_subsizes[1] = XLEN * SUB_XLEN / 5;
91
92 offset = rank_dim[0] * YLEN * array_of_sizes[1] +
93 rank_dim[1] * XLEN;
94
95 /* define data type for file view */
96 count = array_of_subsizes[0] * 2; /* 2 is the no. blocks along X */
97 blocklengths = (int*) malloc(count*sizeof(int));
98 displacements = (MPI_Aint*)malloc(count*sizeof(MPI_Aint));
99 for (i=0; i<count; i++)
100 blocklengths[i] = array_of_subsizes[1] / 2;
101 for (i=0; i<array_of_subsizes[0]; i++)
102 for (j=0; j<2; j++)
103 displacements[i*2+j] = offset + i*2*array_of_sizes[1] + j * XLEN/2;
104 MPI_Type_create_hindexed(count, blocklengths, displacements, MPI_CHAR, &ftype);
105 MPI_Type_commit(&ftype);
106 MPI_Type_size_x(ftype, &ftype_size);
107
108 /* subarray's layout in the global array
109
110 P0's 's layout P1's layout
111 [ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9] | [ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9]
112 [ 0] 0 1 2 3 4 5 | D E F G H I
113 [ 1] |
114 [ 2] 6 7 8 9 : ; | J K L M N O
115 [ 3] |
116 [ 4] |
117 [ 5] |
118 [ 6] |
119 [ 7] |
120 [ 8] |
121 [ 9] |
122
123 P2's 's layout P3's layout
124 [ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9] | [ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9]
125 [ 0] |
126 [ 1] |
127 [ 2] |
128 [ 3] |
129 [ 4] |
130 [ 5] X Y Z [ \ ] | l m n o p q
131 [ 6] |
132 [ 7] ^ _ ` a b c | r s t u v w
133 [ 8] |
134 [ 9] |
135 */
136
137 /* initialize the write buffer */
138 buf = (char*) malloc(array_of_subsizes[0]*array_of_subsizes[1]);
139 for (i=0; i<array_of_subsizes[0]*array_of_subsizes[1]; i++)
140 buf[i] = '0' + rank*20 + i%79;
141
142 /* zero file contents ---------------------------------------------------*/
143 if (rank == 0) {
144 char *wr_buf = (char*) calloc(num_io*global_array_size,1);
145 MPI_File_open(MPI_COMM_SELF, filename,
146 MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);
147 MPI_File_write(fh, wr_buf, num_io*global_array_size, MPI_CHAR, &status);
148 MPI_File_close(&fh);
149 free(wr_buf);
150 }
151 /* open the file --------------------------------------------------------*/
152 err = MPI_File_open(MPI_COMM_WORLD, filename,
153 MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);
154 if (err != MPI_SUCCESS) {
155 printf("Error: MPI_File_open() filename %s\n",filename);
156 MPI_Abort(MPI_COMM_WORLD, -1);
157 exit(1);
158 }
159
160 /* MPI collective write */
161 for (i=0; i<num_io; i++) {
162 offset = i * global_array_size;
163 /* set the file view */
164 MPI_File_set_view(fh, offset, MPI_BYTE, ftype, "native", MPI_INFO_NULL);
165 MPI_File_write_all(fh, buf, ftype_size, MPI_CHAR, &status);
166 }
167 MPI_File_close(&fh);
168
169 /* read and print file contents -----------------------------------------*/
170 if (rank == 0) {
171 char *ptr;
172 char *rd_buf = (char*) calloc(num_io*global_array_size,1);
173 MPI_File_open(MPI_COMM_SELF, filename, MPI_MODE_RDONLY, MPI_INFO_NULL, &fh);
174 MPI_File_read(fh, rd_buf, num_io*global_array_size, MPI_CHAR, &status);
175 MPI_File_close(&fh);
176
177 #ifdef VERBOSE
178 printf("-------------------------------------------------------\n");
179 printf(" [");
180 for (i=0; i<2; i++) {
181 for (j=0; j<XLEN; j++) printf(" %d",j);
182 printf(" ");
183 }
184 printf("]\n\n");
185
186
187 ptr = rd_buf;
188 for (k=0; k<num_io; k++) {
189 for (i=0; i<2*YLEN; i++) {
190 printf("[%2d]",k*2*YLEN+i);
191 for (j=0; j<2*XLEN; j++) {
192 if (j>0 && j%XLEN==0) printf(" ");
193 if (*ptr != 0)
194 printf(" %c",*ptr);
195 else
196 printf(" ");
197 ptr++;
198 }
199 printf("\n");
200 }
201 printf("\n");
202 }
203 #endif
204 ptr = rd_buf;
205 for(i=0; i<2*YLEN*num_io; i++) {
206 for(j=0; j<2*XLEN; j++) {
207 if( *ptr != compare_buf[i][j]) {
208 fprintf(stderr, "expected %d got %d at [%d][%d]\n",
209 *ptr, compare_buf[i][j], i, j);
210 nr_errors++;
211 }
212 ptr++;
213 }
214 }
215 free(rd_buf);
216
217 if (nr_errors == 0)
218 fprintf(stdout, " No Errors\n");
219 else
220 fprintf(stderr, "Found %d errors\n", nr_errors);
221 }
222
223 free(blocklengths);
224 free(displacements);
225 free(buf);
226 MPI_Type_free(&ftype);
227 MPI_Finalize();
228 return 0;
229 }
230
231 /* command-line outputs are: (the global array is written twice)
232
233 % mpiexec -n 4 wkl_subarray
234 -------------------------------------------------------
235 [ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 ]
236
237 [ 0] 0 1 2 3 4 5 D E F G H I
238 [ 1]
239 [ 2] 6 7 8 9 : ; J K L M N O
240 [ 3]
241 [ 4]
242 [ 5] X Y Z [ \ ] l m n o p q
243 [ 6]
244 [ 7] ^ _ ` a b c r s t u v w
245 [ 8]
246 [ 9]
247
248 [10] 0 1 2 3 4 5 D E F G H I
249 [11]
250 [12] 6 7 8 9 : ; J K L M N O
251 [13]
252 [14]
253 [15] X Y Z [ \ ] l m n o p q
254 [16]
255 [17] ^ _ ` a b c r s t u v w
256 [18]
257 [19]
258
259 */
260
261