IOR
aiori-NCMPI.c
Go to the documentation of this file.
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  */
4 /******************************************************************************\
5 * *
6 * Copyright (c) 2003, The Regents of the University of California *
7 * See the file COPYRIGHT for a complete copyright notice and license. *
8 * *
9 ********************************************************************************
10 *
11 * Implement abstract I/O interface for Parallel NetCDF (NCMPI).
12 *
13 \******************************************************************************/
14 
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <sys/stat.h>
22 #include <pnetcdf.h>
23 
24 #include "ior.h"
25 #include "iordef.h"
26 #include "aiori.h"
27 #include "utilities.h"
28 
29 #define NUM_DIMS 3 /* number of dimensions to data set */
30 
31 /*
32  * NCMPI_CHECK will display a custom error message and then exit the program
33  */
34 #define NCMPI_CHECK(NCMPI_RETURN, MSG) do { \
35  int _NCMPI_RETURN = (NCMPI_RETURN); \
36  \
37  if (_NCMPI_RETURN != NC_NOERR) { \
38  fprintf(stdout, "** error **\n"); \
39  fprintf(stdout, "ERROR in %s (line %d): %s.\n", \
40  __FILE__, __LINE__, MSG); \
41  fprintf(stdout, "ERROR: %s.\n", ncmpi_strerror(_NCMPI_RETURN)); \
42  fprintf(stdout, "** exiting **\n"); \
43  exit(EXIT_FAILURE); \
44  } \
45 } while(0)
46 
47 /**************************** P R O T O T Y P E S *****************************/
48 
49 static int GetFileMode(int flags);
50 
51 static aiori_fd_t *NCMPI_Create(char *, int iorflags, aiori_mod_opt_t *);
52 static aiori_fd_t *NCMPI_Open(char *, int iorflags, aiori_mod_opt_t *);
55 static void NCMPI_Close(aiori_fd_t *, aiori_mod_opt_t *);
56 static void NCMPI_Delete(char *, aiori_mod_opt_t *);
57 static char *NCMPI_GetVersion();
58 static void NCMPI_Fsync(aiori_fd_t *, aiori_mod_opt_t *);
60 static int NCMPI_Access(const char *, int, aiori_mod_opt_t *);
61 
62 /************************** D E C L A R A T I O N S ***************************/
64 
65 static void NCMPI_xfer_hints(aiori_xfer_hint_t * params){
66  hints = params;
67 
68  MPIIO_xfer_hints(params);
69 }
70 
71 typedef struct {
73 
74  /* runtime variables */
75  int var_id; /* variable id handle for data set */
79 
80 
81 static option_help * NCMPI_options(aiori_mod_opt_t ** init_backend_options, aiori_mod_opt_t * init_values){
82  ncmpi_options_t * o = malloc(sizeof(ncmpi_options_t));
83  if (init_values != NULL){
84  memcpy(o, init_values, sizeof(ncmpi_options_t));
85  }else{
86  memset(o, 0, sizeof(ncmpi_options_t));
87  }
88  *init_backend_options = (aiori_mod_opt_t*) o;
89 
90  option_help h [] = {
91  {0, "ncmpi.hintsFileName","Full name for hints file", OPTION_OPTIONAL_ARGUMENT, 's', & o->mpio.hintsFileName},
92  {0, "ncmpi.showHints", "Show MPI hints", OPTION_FLAG, 'd', & o->mpio.showHints},
93  {0, "ncmpi.preallocate", "Preallocate file size", OPTION_FLAG, 'd', & o->mpio.preallocate},
94  {0, "ncmpi.useStridedDatatype", "put strided access into datatype", OPTION_FLAG, 'd', & o->mpio.useStridedDatatype},
95  {0, "ncmpi.useFileView", "Use MPI_File_set_view", OPTION_FLAG, 'd', & o->mpio.useFileView},
97  };
98  option_help * help = malloc(sizeof(h));
99  memcpy(help, h, sizeof(h));
100  return help;
101 }
102 
104  .name = "NCMPI",
105  .name_legacy = NULL,
106  .create = NCMPI_Create,
107  .open = NCMPI_Open,
108  .xfer = NCMPI_Xfer,
109  .close = NCMPI_Close,
110  .delete = NCMPI_Delete,
111  .get_version = NCMPI_GetVersion,
112  .fsync = NCMPI_Fsync,
113  .get_file_size = NCMPI_GetFileSize,
114  .statfs = aiori_posix_statfs,
115  .mkdir = aiori_posix_mkdir,
116  .rmdir = aiori_posix_rmdir,
117  .access = NCMPI_Access,
118  .stat = aiori_posix_stat,
119  .get_options = NCMPI_options,
120  .xfer_hints = NCMPI_xfer_hints,
121 };
122 
123 /***************************** F U N C T I O N S ******************************/
124 
125 /*
126  * Create and open a file through the NCMPI interface.
127  */
128 static aiori_fd_t *NCMPI_Create(char *testFileName, int iorflags, aiori_mod_opt_t * param)
129 {
130  int *fd;
131  int fd_mode;
132  MPI_Info mpiHints = MPI_INFO_NULL;
133  ncmpi_options_t * o = (ncmpi_options_t*) param;
134 
135  /* read and set MPI file hints from hintsFile */
136  SetHints(&mpiHints, o->mpio.hintsFileName);
137  if (rank == 0 && o->mpio.showHints) {
138  fprintf(stdout, "\nhints passed to MPI_File_open() {\n");
139  ShowHints(&mpiHints);
140  fprintf(stdout, "}\n");
141  }
142 
143  fd = (int *)malloc(sizeof(int));
144  if (fd == NULL)
145  ERR("malloc() failed");
146 
147  fd_mode = GetFileMode(iorflags);
148  NCMPI_CHECK(ncmpi_create(testComm, testFileName, fd_mode,
149  mpiHints, fd), "cannot create file");
150 
151  /* free up the mpiHints object */
152  if (mpiHints != MPI_INFO_NULL)
153  MPI_CHECK(MPI_Info_free(&mpiHints), "cannot free file info");
154 
155 #if defined(PNETCDF_VERSION_MAJOR) && (PNETCDF_VERSION_MAJOR > 1 || PNETCDF_VERSION_MINOR >= 2)
156  /* ncmpi_get_file_info is first available in 1.2.0 */
157  if (rank == 0 && o->mpio.showHints) {
158  MPI_Info info_used;
159  NCMPI_CHECK(ncmpi_get_file_info(*fd, &info_used), "cannot inquire file info");
160  /* print the MPI file hints currently used */
161  fprintf(stdout, "\nhints returned from opened file {\n");
162  ShowHints(&info_used);
163  fprintf(stdout, "}\n");
164  MPI_CHECK(MPI_Info_free(&info_used), "cannot free file info");
165  }
166 #endif
167 
168  return (aiori_fd_t*)(fd);
169 }
170 
171 /*
172  * Open a file through the NCMPI interface.
173  */
174 static aiori_fd_t *NCMPI_Open(char *testFileName, int iorflags, aiori_mod_opt_t * param)
175 {
176  int *fd;
177  int fd_mode;
178  MPI_Info mpiHints = MPI_INFO_NULL;
179  ncmpi_options_t * o = (ncmpi_options_t*) param;
180 
181  /* read and set MPI file hints from hintsFile */
182  SetHints(&mpiHints, o->mpio.hintsFileName);
183  if (rank == 0 && o->mpio.showHints) {
184  fprintf(stdout, "\nhints passed to MPI_File_open() {\n");
185  ShowHints(&mpiHints);
186  fprintf(stdout, "}\n");
187  }
188 
189  fd = (int *)malloc(sizeof(int));
190  if (fd == NULL)
191  ERR("malloc() failed");
192 
193  fd_mode = GetFileMode(iorflags);
194  NCMPI_CHECK(ncmpi_open(testComm, testFileName, fd_mode,
195  mpiHints, fd), "cannot open file");
196 
197  /* free up the mpiHints object */
198  if (mpiHints != MPI_INFO_NULL)
199  MPI_CHECK(MPI_Info_free(&mpiHints), "cannot free file info");
200 
201 #if defined(PNETCDF_VERSION_MAJOR) && (PNETCDF_VERSION_MAJOR > 1 || PNETCDF_VERSION_MINOR >= 2)
202  /* ncmpi_get_file_info is first available in 1.2.0 */
203  if (rank == 0 && o->mpio.showHints) {
204  MPI_Info info_used;
205  MPI_CHECK(ncmpi_get_file_info(*fd, &info_used),
206  "cannot inquire file info");
207  /* print the MPI file hints currently used */
208  fprintf(stdout, "\nhints returned from opened file {\n");
209  ShowHints(&info_used);
210  fprintf(stdout, "}\n");
211  MPI_CHECK(MPI_Info_free(&info_used), "cannot free file info");
212  }
213 #endif
214 
215  return (aiori_fd_t*)(fd);
216 }
217 
218 /*
219  * Write or read access to file using the NCMPI interface.
220  */
221 static IOR_offset_t NCMPI_Xfer(int access, aiori_fd_t *fd, IOR_size_t * buffer, IOR_offset_t transferSize, IOR_offset_t offset, aiori_mod_opt_t * param)
222 {
223  signed char *bufferPtr = (signed char *)buffer;
224  ncmpi_options_t * o = (ncmpi_options_t*) param;
225  int var_id, dim_id[NUM_DIMS];
226  MPI_Offset bufSize[NUM_DIMS], offsets[NUM_DIMS];
227  IOR_offset_t segmentPosition;
228  int segmentNum, transferNum;
229 
230  /* determine by offset if need to start data set */
231  if (hints->filePerProc == TRUE) {
232  segmentPosition = (IOR_offset_t) 0;
233  } else {
234  segmentPosition = (IOR_offset_t) ((rank + rankOffset) % hints->numTasks) * hints->blockSize;
235  }
236  if ((int)(offset - segmentPosition) == 0) {
237  o->startDataSet = TRUE;
238  /*
239  * this toggle is for the read check operation, which passes through
240  * this function twice; note that this function will open a data set
241  * only on the first read check and close only on the second
242  */
243  if (access == READCHECK) {
244  o->firstReadCheck = ! o->firstReadCheck;
245  }
246  }
247 
248  if (o->startDataSet == TRUE &&
249  (access != READCHECK || o->firstReadCheck == TRUE)) {
250  if (access == WRITE) {
251  int numTransfers = hints->blockSize / hints->transferSize;
252 
253  /* reshape 1D array to 3D array:
254  [segmentCount*numTasks][numTransfers][transferSize]
255  Requirement: none of these dimensions should be > 4G,
256  */
257  NCMPI_CHECK(ncmpi_def_dim
258  (*(int *)fd, "segments_times_np",
259  NC_UNLIMITED, &dim_id[0]),
260  "cannot define data set dimensions");
261  NCMPI_CHECK(ncmpi_def_dim
262  (*(int *)fd, "number_of_transfers",
263  numTransfers, &dim_id[1]),
264  "cannot define data set dimensions");
265  NCMPI_CHECK(ncmpi_def_dim
266  (*(int *)fd, "transfer_size",
267  hints->transferSize, &dim_id[2]),
268  "cannot define data set dimensions");
269  NCMPI_CHECK(ncmpi_def_var
270  (*(int *)fd, "data_var", NC_BYTE, NUM_DIMS,
271  dim_id, &var_id),
272  "cannot define data set variables");
273  NCMPI_CHECK(ncmpi_enddef(*(int *)fd),
274  "cannot close data set define mode");
275 
276  } else {
277  NCMPI_CHECK(ncmpi_inq_varid
278  (*(int *)fd, "data_var", &var_id),
279  "cannot retrieve data set variable");
280  }
281 
282  if (hints->collective == FALSE) {
283  NCMPI_CHECK(ncmpi_begin_indep_data(*(int *)fd),
284  "cannot enable independent data mode");
285  }
286 
287  o->var_id = var_id;
288  o->startDataSet = FALSE;
289  }
290 
291  var_id = o->var_id;
292 
293  /* calculate the segment number */
294  segmentNum = offset / (hints->numTasks * hints->blockSize);
295 
296  /* calculate the transfer number in each block */
297  transferNum = offset % hints->blockSize / hints->transferSize;
298 
299  /* read/write the 3rd dim of the dataset, each is of
300  amount param->transferSize */
301  bufSize[0] = 1;
302  bufSize[1] = 1;
303  bufSize[2] = transferSize;
304 
305  offsets[0] = segmentNum * hints->numTasks + rank;
306  offsets[1] = transferNum;
307  offsets[2] = 0;
308 
309  /* access the file */
310  if (access == WRITE) { /* WRITE */
311  if (hints->collective) {
312  NCMPI_CHECK(ncmpi_put_vara_schar_all
313  (*(int *)fd, var_id, offsets, bufSize, bufferPtr),
314  "cannot write to data set");
315  } else {
316  NCMPI_CHECK(ncmpi_put_vara_schar
317  (*(int *)fd, var_id, offsets, bufSize, bufferPtr),
318  "cannot write to data set");
319  }
320  } else { /* READ or CHECK */
321  if (hints->collective == TRUE) {
322  NCMPI_CHECK(ncmpi_get_vara_schar_all
323  (*(int *)fd, var_id, offsets, bufSize, bufferPtr),
324  "cannot read from data set");
325  } else {
326  NCMPI_CHECK(ncmpi_get_vara_schar
327  (*(int *)fd, var_id, offsets, bufSize, bufferPtr),
328  "cannot read from data set");
329  }
330  }
331 
332  return (transferSize);
333 }
334 
335 /*
336  * Perform fsync().
337  */
338 static void NCMPI_Fsync(aiori_fd_t *fd, aiori_mod_opt_t * param)
339 {
340  NCMPI_CHECK(ncmpi_sync(*(int *)fd), "cannot sync file");
341 }
342 
343 /*
344  * Close a file through the NCMPI interface.
345  */
346 static void NCMPI_Close(aiori_fd_t *fd, aiori_mod_opt_t * param)
347 {
348  NCMPI_CHECK(ncmpi_close(*(int *)fd), "cannot close file");
349  free(fd);
350 }
351 
352 /*
353  * Delete a file through the NCMPI interface.
354  */
355 static void NCMPI_Delete(char *testFileName, aiori_mod_opt_t * param)
356 {
357  NCMPI_CHECK(ncmpi_delete(testFileName, MPI_INFO_NULL), "cannot delete file");
358 }
359 
360 /*
361  * Determine api version.
362  */
363 static char* NCMPI_GetVersion()
364 {
365  return (char *)ncmpi_inq_libvers();
366 }
367 
368 /*
369  * Return the correct file mode for NCMPI.
370  */
371 static int GetFileMode(int flags)
372 {
373  int fd_mode = 0;
374 
375  /* set IOR file flags to NCMPI flags */
376  /* -- file open flags -- */
377  if (flags & IOR_RDONLY) {
378  fd_mode |= NC_NOWRITE;
379  }
380  if (flags & IOR_WRONLY) {
381  WARN("File write only not implemented in NCMPI");
382  }
383  if (flags & IOR_RDWR) {
384  fd_mode |= NC_WRITE;
385  }
386  if (flags & IOR_APPEND) {
387  WARN("File append not implemented in NCMPI");
388  }
389  if (flags & IOR_CREAT) {
390  fd_mode |= NC_CLOBBER;
391  }
392  if (flags & IOR_EXCL) {
393  WARN("Exclusive access not implemented in NCMPI");
394  }
395  if (flags & IOR_TRUNC) {
396  fd_mode |= NC_CLOBBER;
397  }
398  if (flags & IOR_DIRECT) {
399  WARN("O_DIRECT not implemented in NCMPI");
400  }
401 
402  /* to enable > 4GB variable size */
403  fd_mode |= NC_64BIT_DATA;
404 
405  return (fd_mode);
406 }
407 
408 /*
409  * Use MPIIO call to get file size.
410  */
412  char *testFileName)
413 {
414  return(MPIIO_GetFileSize(opt, testFileName));
415 }
416 
417 /*
418  * Use MPIIO call to check for access.
419  */
420 static int NCMPI_Access(const char *path, int mode, aiori_mod_opt_t *param)
421 {
422  return(MPIIO_Access(path, mode, param));
423 }
static char * NCMPI_GetVersion()
Definition: aiori-NCMPI.c:363
void ShowHints(MPI_Info *mpiHints)
Definition: utilities.c:717
#define LAST_OPTION
Definition: option.h:39
struct benchmark_options o
Definition: md-workbench.c:133
IOR_offset_t blockSize
Definition: aiori.h:72
static aiori_fd_t * NCMPI_Create(char *, int iorflags, aiori_mod_opt_t *)
Definition: aiori-NCMPI.c:128
static void NCMPI_Delete(char *, aiori_mod_opt_t *)
Definition: aiori-NCMPI.c:355
#define READCHECK
Definition: iordef.h:103
static aiori_xfer_hint_t * hints
Definition: aiori-NCMPI.c:63
int showHints
Definition: aiori.h:165
#define IOR_APPEND
Definition: aiori.h:31
IOR_offset_t MPIIO_GetFileSize(aiori_mod_opt_t *module_options, char *testFileName)
Definition: aiori-MPIIO.c:579
ior_aiori_t ncmpi_aiori
Definition: aiori-NCMPI.c:103
#define IOR_RDONLY
Definition: aiori.h:28
#define MPI_CHECK(MPI_STATUS, MSG)
Definition: aiori-debug.h:97
#define WRITE
Definition: iordef.h:100
int aiori_posix_stat(const char *path, struct stat *buf, aiori_mod_opt_t *module_options)
Definition: aiori.c:230
#define IOR_CREAT
Definition: aiori.h:32
#define IOR_EXCL
Definition: aiori.h:34
static aiori_fd_t * NCMPI_Open(char *, int iorflags, aiori_mod_opt_t *)
Definition: aiori-NCMPI.c:174
int MPIIO_Access(const char *path, int mode, aiori_mod_opt_t *module_options)
Definition: aiori-MPIIO.c:130
MPI_Comm testComm
Definition: utilities.c:73
#define IOR_TRUNC
Definition: aiori.h:33
#define WARN(MSG)
Definition: aiori-debug.h:45
int collective
Definition: aiori.h:66
void MPIIO_xfer_hints(aiori_xfer_hint_t *params)
Definition: aiori-MPIIO.c:102
static void NCMPI_Fsync(aiori_fd_t *, aiori_mod_opt_t *)
Definition: aiori-NCMPI.c:338
static void NCMPI_Close(aiori_fd_t *, aiori_mod_opt_t *)
Definition: aiori-NCMPI.c:346
char * hintsFileName
Definition: aiori.h:170
IOR_offset_t transferSize
Definition: aiori.h:73
#define NUM_DIMS
Definition: aiori-NCMPI.c:29
#define IOR_WRONLY
Definition: aiori.h:29
#define FALSE
Definition: iordef.h:76
int rankOffset
Definition: utilities.c:71
mpiio_options_t mpio
Definition: aiori-NCMPI.c:72
long long int IOR_size_t
Definition: iordef.h:124
int aiori_posix_rmdir(const char *path, aiori_mod_opt_t *module_options)
Definition: aiori.c:220
static option_help * NCMPI_options(aiori_mod_opt_t **init_backend_options, aiori_mod_opt_t *init_values)
Definition: aiori-NCMPI.c:81
static IOR_offset_t NCMPI_Xfer(int, aiori_fd_t *, IOR_size_t *, IOR_offset_t, IOR_offset_t, aiori_mod_opt_t *)
Definition: aiori-NCMPI.c:221
int aiori_posix_mkdir(const char *path, mode_t mode, aiori_mod_opt_t *module_options)
Definition: aiori.c:215
static int GetFileMode(int flags)
Definition: aiori-NCMPI.c:371
int useFileView
Definition: aiori.h:166
int useStridedDatatype
Definition: aiori.h:169
int aiori_posix_statfs(const char *path, ior_aiori_statfs_t *stat_buf, aiori_mod_opt_t *module_options)
Definition: aiori.c:169
void SetHints(MPI_Info *mpiHints, char *hintsFileName)
Definition: utilities.c:656
#define ERR(MSG)
Definition: aiori-debug.h:75
int preallocate
Definition: aiori.h:167
#define IOR_RDWR
Definition: aiori.h:30
static IOR_offset_t NCMPI_GetFileSize(aiori_mod_opt_t *, char *)
Definition: aiori-NCMPI.c:411
static int NCMPI_Access(const char *, int, aiori_mod_opt_t *)
Definition: aiori-NCMPI.c:420
#define NCMPI_CHECK(NCMPI_RETURN, MSG)
Definition: aiori-NCMPI.c:34
char * name
Definition: aiori.h:88
int filePerProc
Definition: aiori.h:65
long long int IOR_offset_t
Definition: iordef.h:123
int rank
Definition: utilities.c:70
#define TRUE
Definition: iordef.h:80
#define IOR_DIRECT
Definition: aiori.h:35
static void NCMPI_xfer_hints(aiori_xfer_hint_t *params)
Definition: aiori-NCMPI.c:65
#define NULL
Definition: iordef.h:84