SIONlib  1.7.2
Scalable I/O library for parallel access to task-local files
sion_internal_startptr.c
Go to the documentation of this file.
1 /****************************************************************************
2 ** SIONLIB http://www.fz-juelich.de/jsc/sionlib **
3 *****************************************************************************
4 ** Copyright (c) 2008-2018 **
5 ** Forschungszentrum Juelich, Juelich Supercomputing Centre **
6 ** **
7 ** See the file COPYRIGHT in the package base directory for details **
8 ****************************************************************************/
9 
14 #define _XOPEN_SOURCE 700
15 
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <stdarg.h>
19 #include <string.h>
20 #include <time.h>
21 
22 #include <sys/time.h>
23 
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <errno.h>
28 
29 #include <unistd.h>
30 
31 #include "sion.h"
32 #include "sion_debug.h"
33 #include "sion_error_handler.h"
34 #include "sion_internal.h"
35 #include "sion_metadata.h"
36 #include "sion_filedesc.h"
37 #include "sion_tools.h"
38 #include "sion_fd.h"
39 #include "sion_file.h"
40 #include "sion_hints.h"
41 #include "sion_printts.h"
42 #include "sion_internal_startptr.h"
43 #include "sion_internal_collstat.h"
44 
45 /* INTERNAL */
46 
47 #define DFUNCTION "_sion_calculate_set_alignment"
48 sion_int64 _sion_calculate_set_alignment( _sion_filedesc *sion_filedesc, int t) {
49  sion_int64 lsize=SION_SIZE_NOT_VALID;
50 
51  /* alignment: fsv 3, WRITE: -> align lsize */
52  /* : fsv 3, READ: -> align lsize */
53  /* : fsv 4, WRITE: -> align lsize+chunksize */
54  /* : fsv 4, READ: -> lsize=chunksize */
55 
56  if (sion_filedesc->fileversion<=3) {
57  lsize = (sion_filedesc->all_chunksizes[t] % sion_filedesc->fsblksize == 0) ?
58  sion_filedesc->all_chunksizes[t] :
59  ((sion_filedesc->all_chunksizes[t] / sion_filedesc->fsblksize) + 1) * sion_filedesc->fsblksize;
60  DPRINTFP((2048, DFUNCTION, _SION_DEFAULT_RANK, "old file version (<=3) task=%d lsize=%ld\n", t, (long) lsize));
61  } else {
62  if (sion_filedesc->mode==SION_FILEMODE_WRITE) {
63  lsize = (sion_filedesc->all_chunksizes[t] % sion_filedesc->fsblksize == 0) ?
64  sion_filedesc->all_chunksizes[t] :
65  ((sion_filedesc->all_chunksizes[t] / sion_filedesc->fsblksize) + 1) * sion_filedesc->fsblksize;
66  /* expand chunksize for alignment */
67  sion_filedesc->all_chunksizes[t] = lsize;
68  DPRINTFP((2048, DFUNCTION, _SION_DEFAULT_RANK, "new file version (>3) task=%d lsize=%ld, WRITE chunksize set\n", t, (long) lsize));
69  } else {
70  lsize = sion_filedesc->all_chunksizes[t];
71  DPRINTFP((2048, DFUNCTION, _SION_DEFAULT_RANK, "new file version (>3) task=%d lsize=%ld, READ no align\n", t, (long) lsize));
72  }
73  }
74 
75  return(lsize);
76 }
77 #undef DFUNCTION
78 
85 #define DFUNCTION "_sion_get_size_metadatablock1"
86 int _sion_get_size_metadatablock1( _sion_filedesc *sion_filedesc )
87 {
88  int rc = 0;
89  int firstsize;
90 
91  /* calculate size of first block for meta-information */
92  firstsize = strlen(SION_ID) + 8 * sizeof(sion_int32) /* length of SION_ID + endianness+fsblksize+ntasks */
93  /* + nfiles+filenumber+3*versioninfo */
94  + SION_FILENAME_LENGTH /* prefix */
95  + sion_filedesc->ntasks * sizeof(sion_int64) + sion_filedesc->ntasks * sizeof(sion_int64) /* globalranks + chunksizes */
96  + sizeof(sion_int32) + 3 * sizeof(sion_int64); /* maxblocks + start_of_varheader + 2 x 64bit-flags */
97  rc=firstsize;
98 
99  return(rc);
100 }
101 #undef DFUNCTION
102 
109 #define DFUNCTION "_sion_calculate_startpointers"
110 int _sion_calculate_startpointers( _sion_filedesc *sion_filedesc )
111 {
112 
113  int rc = SION_SUCCESS;
114  int i, firstsize;
115  sion_int64 lsize;
116 
117  DPRINTFP((2, DFUNCTION, _SION_DEFAULT_RANK, "enter ntasks=%d fsblksize=%d chunksizes[0]=%lld\n",
118  sion_filedesc->ntasks, sion_filedesc->fsblksize, sion_filedesc->all_chunksizes[0]));
119 
120  firstsize=_sion_get_size_metadatablock1(sion_filedesc);
121 
122 #ifdef WFLARGEMETABLOCK
123  if (firstsize<4*1024*1024) firstsize=4*1024*1024;
124 #endif
125 
126  DPRINTFP((2, DFUNCTION, _SION_DEFAULT_RANK, "firstsize=%d\n", firstsize));
127 
128  sion_filedesc->all_startpointers[0] = (firstsize % sion_filedesc->fsblksize == 0) ?
129  firstsize :
130  ((firstsize / sion_filedesc->fsblksize) + 1) * sion_filedesc->fsblksize;
131 
132  i = 0;
133  DPRINTFP((2048, DFUNCTION, _SION_DEFAULT_RANK, " startpointers[%2d]=%10lld (%10.4fMB) chunksizes[%2d]=%8lld\n",
134  i, sion_filedesc->all_startpointers[i], sion_filedesc->all_startpointers[i] / 1024.0 / 1024.0, i, sion_filedesc->all_chunksizes[i]));
135  sion_filedesc->globalskip = 0;
136  for (i = 1; i < sion_filedesc->ntasks; i++) {
137 
138  lsize=_sion_calculate_set_alignment(sion_filedesc,i-1);
139 
140  sion_filedesc->globalskip += lsize;
141  sion_filedesc->all_startpointers[i] = sion_filedesc->all_startpointers[i - 1] + lsize;
142 
143 
144  DPRINTFP((2048, DFUNCTION, _SION_DEFAULT_RANK, " startpointers[%2d]=%10lld (%10.4fMB) chunksizes[%2d]=%8lld chunksizes[%2d]=%8lld\n",
145  i, sion_filedesc->all_startpointers[i], sion_filedesc->all_startpointers[i] / 1024.0 / 1024.0, i, sion_filedesc->all_chunksizes[i], i-1, sion_filedesc->all_chunksizes[i-1]));
146  }
147 
148  lsize=_sion_calculate_set_alignment(sion_filedesc,sion_filedesc->ntasks - 1);
149  sion_filedesc->globalskip += lsize;
150 
151  DPRINTFP((2, DFUNCTION, _SION_DEFAULT_RANK, "leave globalskip is %lld\n", sion_filedesc->globalskip));
152  return (rc);
153 }
154 #undef DFUNCTION
155 
156 
164 #define DFUNCTION "_sion_calculate_num_collector"
165 int _sion_calculate_num_collector( _sion_filedesc *sion_filedesc, _sion_collstat *collstat, int *num_collectors) {
166  int rc = SION_SUCCESS;
167  int max_num_collectors;
168 
169 
170  /* max. number: one fsblksize per collector */
171  max_num_collectors = (int) (collstat->gsize/sion_filedesc->fsblksize);
172  if(collstat->gsize%sion_filedesc->fsblksize>0) max_num_collectors++;
173  DPRINTFP((2, DFUNCTION, _SION_DEFAULT_RANK, "max_num_collectors=%d\n", max_num_collectors));
174 
175  if(sion_filedesc->collsize>0) {
176  /* user defined collsize (number of tasks per collector) */
177  *num_collectors = (int) (sion_filedesc->ntasks/sion_filedesc->collsize);
178  if(sion_filedesc->ntasks%sion_filedesc->collsize>0) (*num_collectors)++;
179 
180  /* limit the user specification */
181  if(*num_collectors > max_num_collectors) *num_collectors=max_num_collectors;
182 
183  DPRINTFP((32, DFUNCTION, _SION_DEFAULT_RANK, "user given collsize %d -> set num_collectors to %d\n",
184  sion_filedesc->collsize,*num_collectors));
185  } else {
186 
187  /* determine number of collectors by heuristic */
188  *num_collectors = max_num_collectors;
189 
190  /* limit the user specification */
191  if(*num_collectors>sion_filedesc->ntasks) *num_collectors=sion_filedesc->ntasks;
192 
193  /* some heuristics */
194  if ((sion_filedesc->ntasks>=512) && (*num_collectors>32)) *num_collectors=32;
195  else if((sion_filedesc->ntasks>=256) && (*num_collectors>16)) *num_collectors=16;
196  else if((sion_filedesc->ntasks>=128) && (*num_collectors>8)) *num_collectors=8;
197  else if((sion_filedesc->ntasks>=64) && (*num_collectors>8)) *num_collectors=8;
198  else if((sion_filedesc->ntasks>=32) && (*num_collectors>8)) *num_collectors=8;
199  else if((sion_filedesc->ntasks>=16) && (*num_collectors>4)) *num_collectors=4;
200 
201  /* TODO: check I/O infrastructure characteristics for better values */
202 
203  DPRINTFP((2, DFUNCTION, _SION_DEFAULT_RANK, "SIONlib heuristic collsize=%d num_collectors=%d\n",
204  sion_filedesc->collsize, *num_collectors));
205  }
206 
207  /* data per collector */
208  collstat->avg_data_per_collector = (
209  (sion_int64) (collstat->gsize / *num_collectors)
210  / sion_filedesc->fsblksize
211  )
212  * sion_filedesc->fsblksize;
213 
214  if((collstat->gsize / *num_collectors)%sion_filedesc->fsblksize>0) collstat->avg_data_per_collector+=sion_filedesc->fsblksize;
215  DPRINTFP((32, DFUNCTION, _SION_DEFAULT_RANK, "avg_data_per_collectors=%ld\n",(long) collstat->avg_data_per_collector));
216 
217 
218  return(rc);
219 }
220 #undef DFUNCTION
221 
228 #define DFUNCTION "_sion_calculate_startpointers_collective"
229 int _sion_calculate_startpointers_collective( _sion_filedesc *sion_filedesc )
230 {
231 
232  int rc = SION_SUCCESS;
233  int i, firstsize, num_collectors, numsender, lastcoll, s;
234 
235  sion_int64 currentsize, aligned_size, startpointer;
236  _sion_collstat *collstat;
237 
238  DPRINTFP((2, DFUNCTION, _SION_DEFAULT_RANK, "enter ntasks=%d fsblksize=%d chunksizes[0]=%lld\n",
239  sion_filedesc->ntasks, sion_filedesc->fsblksize, sion_filedesc->all_chunksizes[0]));
240 
241  if (sion_filedesc->fileversion<=3) {
242  return(_sion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,
243  "_sion_calculate_startpointers_collective: files with old sionlib file format (<3) can not be read by collective calls, please use standard read calls, aborting ...\n"));
244  }
245 
246  /* statistics */
247  collstat=_sion_create_and_init_collstat(sion_filedesc);
248 
249  /* calculate size of first block for meta-information */
250  collstat->firstsize=firstsize=_sion_get_size_metadatablock1(sion_filedesc);
251  _sion_calculate_num_collector(sion_filedesc, collstat, &num_collectors);
252  collstat->req_num_collectors=num_collectors;
253 
254  DPRINTFP((2, DFUNCTION, _SION_DEFAULT_RANK, "firstsize=%d collsize=%d num_collectors=%d\n",
255  firstsize, sion_filedesc->collsize, num_collectors));
256 
257  numsender=1;lastcoll=0;
258  currentsize=sion_filedesc->all_chunksizes[0];
259 
260  /* 1ST STEP: calculate mapping to collectors */
261  for (i = 1; i < sion_filedesc->ntasks; i++) {
262  if( (currentsize+sion_filedesc->all_chunksizes[i]<=collstat->avg_data_per_collector) ||
263  (sion_filedesc->all_coll_capability[i]==SION_CAPABILITY_ONLY_SENDER ) ) {
264  /* task will add to last collector */
265  currentsize +=sion_filedesc->all_chunksizes[i];
266  numsender++;
267  } else { /* new collector needed */
268 
269  /* adjust last senders */
270  for(s=lastcoll;s<i;s++) {
271  sion_filedesc->all_coll_collector[s]=lastcoll;
272  sion_filedesc->all_coll_collsize[s] =numsender;
273  }
274 
275  /* expand last one of group to align next one */
276  if (sion_filedesc->mode==SION_FILEMODE_WRITE) {
277  aligned_size = ((sion_int64) currentsize/sion_filedesc->fsblksize) * sion_filedesc->fsblksize;
278  if(currentsize%sion_filedesc->fsblksize>0) aligned_size+=sion_filedesc->fsblksize;
279 
280  DPRINTFP((128, DFUNCTION, _SION_DEFAULT_RANK, " align chunksizes[%2d]=%8lld + %lld\n",
281  i-1, sion_filedesc->all_chunksizes[i-1], aligned_size-currentsize));
282 
283  sion_filedesc->all_chunksizes[i-1]+=aligned_size-currentsize;
284  }
285 
286  /* init data for next collector */
287  numsender = 1; lastcoll= i; currentsize = sion_filedesc->all_chunksizes[i];
288  }
289  }
290 
291  /* align last sender */
292  if (sion_filedesc->mode==SION_FILEMODE_WRITE) {
293  aligned_size = ((sion_int64) currentsize/sion_filedesc->fsblksize) * sion_filedesc->fsblksize;
294  if(currentsize%sion_filedesc->fsblksize>0) aligned_size+=sion_filedesc->fsblksize;
295  DPRINTFP((128, DFUNCTION, _SION_DEFAULT_RANK, " align chunksizes[%2d]=%8lld + %lld\n",
296  sion_filedesc->ntasks-1, sion_filedesc->all_chunksizes[sion_filedesc->ntasks-1], aligned_size-currentsize));
297  sion_filedesc->all_chunksizes[sion_filedesc->ntasks-1]+=aligned_size-currentsize;
298  }
299 
300  /* adjust sender of last collector */
301  for(s=lastcoll;s<sion_filedesc->ntasks;s++) {
302  sion_filedesc->all_coll_collector[s]=lastcoll;
303  sion_filedesc->all_coll_collsize[s]=numsender;
304  }
305 
306  /* 2ND STEP: calculate startpointers */
307 
308  /* align first, not necessary, only for debugging */
309  /* startpointer=firstsize; */
310  startpointer = (firstsize % sion_filedesc->fsblksize == 0) ? firstsize : ((firstsize / sion_filedesc->fsblksize) + 1) * sion_filedesc->fsblksize;
311  sion_filedesc->globalskip = 0;
312  /* calculate mapping to collectors */
313  for (i = 0; i < sion_filedesc->ntasks; i++) {
314  sion_filedesc->all_startpointers[i] = startpointer;
315  startpointer += sion_filedesc->all_chunksizes[i];
316  sion_filedesc->globalskip += sion_filedesc->all_chunksizes[i];
317  }
318 
319  /* statistics */
320  if(sion_filedesc->colldebug>=1) {
321  _sion_update_collstat(collstat,sion_filedesc);
322  _sion_print_collstat(collstat, sion_filedesc);
323  }
324 
325  _sion_debugprint_collstat(collstat, sion_filedesc);
326 
327  _sion_destroy_collstat(collstat);
328 
329  DPRINTFP((2, DFUNCTION, _SION_DEFAULT_RANK, "leave globalskip is %lld\n", sion_filedesc->globalskip));
330  return (rc);
331 }
332 #undef DFUNCTION
333 
334 
341 #define DFUNCTION "_sion_calculate_startpointers_collective_merge"
342 int _sion_calculate_startpointers_collective_merge( _sion_filedesc *sion_filedesc )
343 {
344 
345  int rc = SION_SUCCESS;
346  int i, firstsize, num_collectors, numsender, lastcoll, s;
347 
348  sion_int64 currentsize, newsize, aligned_size, startpointer;
349  _sion_collstat *collstat;
350 
351  DPRINTFP((2, DFUNCTION, _SION_DEFAULT_RANK, "enter ntasks=%d fsblksize=%d chunksizes[0]=%lld\n",
352  sion_filedesc->ntasks, sion_filedesc->fsblksize, sion_filedesc->all_chunksizes[0]));
353 
354  if (sion_filedesc->fileversion<=3) {
355  return(_sion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,
356  "_sion_calculate_startpointers_collective: files with old sionlib file format (<3) can not be read by collective calls, please use standard read calls, aborting ...\n"));
357  }
358 
359  /* statistics */
360  collstat=_sion_create_and_init_collstat(sion_filedesc);
361 
362  /* calculate size of first block for meta-information */
363  collstat->firstsize=firstsize=_sion_get_size_metadatablock1(sion_filedesc);
364  _sion_calculate_num_collector(sion_filedesc, collstat, &num_collectors);
365  collstat->req_num_collectors=num_collectors;
366 
367  DPRINTFP((2, DFUNCTION, _SION_DEFAULT_RANK, "firstsize=%d collsize=%d num_collectors=%d\n",
368  firstsize, sion_filedesc->collsize, num_collectors));
369 
370  numsender=1;lastcoll=0;
371  currentsize=sion_filedesc->all_chunksizes[0];
372 
373  DPRINTFP((128, DFUNCTION, _SION_DEFAULT_RANK, " currentsize=%lld chunksizes[%2d]=%8lld\n",
374  currentsize, 0, sion_filedesc->all_chunksizes[0]));
375 
376  /* 1ST STEP: calculate mapping to collectors */
377  for (i = 1; i < sion_filedesc->ntasks; i++) {
378  if( (currentsize+sion_filedesc->all_chunksizes[i]<=collstat->avg_data_per_collector) ||
379  (sion_filedesc->all_coll_capability[i]==SION_CAPABILITY_ONLY_SENDER ) ) {
380  /* task will add to last collector */
381  currentsize +=sion_filedesc->all_chunksizes[i];
382  numsender++;
383  DPRINTFP((128, DFUNCTION, _SION_DEFAULT_RANK, " currentsize=%lld chunksizes[%2d]=%8lld\n",
384  currentsize, i, sion_filedesc->all_chunksizes[i]));
385  } else { /* new collector needed */
386 
387 
388  /* increase chunksize of last collector */
389  if (sion_filedesc->mode==SION_FILEMODE_WRITE) {
390  newsize=currentsize;
391 
392  /* expand chunksize to align next one */
393  aligned_size = ((sion_int64) newsize/sion_filedesc->fsblksize) * sion_filedesc->fsblksize;
394  if(newsize%sion_filedesc->fsblksize>0) aligned_size+=sion_filedesc->fsblksize;
395 
396  DPRINTFP((128, DFUNCTION, _SION_DEFAULT_RANK, " resize chunksizes[%2d]=%8lld + %lld\n",
397  lastcoll, sion_filedesc->all_chunksizes[lastcoll], aligned_size-sion_filedesc->all_chunksizes[lastcoll]));
398  sion_filedesc->all_chunksizes[lastcoll]=aligned_size;
399 
400  for(s=lastcoll+1;s<i;s++) {
401  /* leave chunksize of sender on aligned original size to
402  allow storing data in intermeadiate non-collective
403  flushes */
404  _sion_calculate_set_alignment(sion_filedesc,s);
405 
406  /* adjust chunksize of the sender to one file system block as spare space */
407  /* sion_filedesc->all_chunksizes[s]=sion_filedesc->fsblksize; */
408  }
409 
410  }
411 
412  /* adjust last senders */
413  for(s=lastcoll;s<i;s++) {
414  sion_filedesc->all_coll_collector[s]=lastcoll;
415  sion_filedesc->all_coll_collsize[s] =numsender;
416  }
417 
418  /* init data for next collector */
419  numsender = 1; lastcoll= i; currentsize = sion_filedesc->all_chunksizes[i];
420  }
421  }
422 
423  /* align last sender */
424  if (sion_filedesc->mode==SION_FILEMODE_WRITE) {
425  newsize=currentsize;
426 
427  /* expand chunksize to align next one */
428  aligned_size = ((sion_int64) newsize/sion_filedesc->fsblksize) * sion_filedesc->fsblksize;
429  if(newsize%sion_filedesc->fsblksize>0) aligned_size+=sion_filedesc->fsblksize;
430 
431  DPRINTFP((128, DFUNCTION, _SION_DEFAULT_RANK, " resize chunksizes[%2d]=%8lld + %lld\n",
432  lastcoll, sion_filedesc->all_chunksizes[lastcoll], aligned_size-sion_filedesc->all_chunksizes[lastcoll]));
433  sion_filedesc->all_chunksizes[lastcoll]=aligned_size;
434 
435  /* adjust chunksize of the sender to one file system block as spare space */
436  for(s=lastcoll+1;s<i;s++) {
437  /* leave chunksize of sender on aligned original size to
438  allow storing data in intermeadiate non-collective
439  flushes */
440  _sion_calculate_set_alignment(sion_filedesc,s);
441 
442  /* adjust chunksize of the sender to one file system block as spare space */
443  /* sion_filedesc->all_chunksizes[s]=sion_filedesc->fsblksize; */
444  }
445  }
446 
447  /* adjust sender of last collector */
448  for(s=lastcoll;s<sion_filedesc->ntasks;s++) {
449  sion_filedesc->all_coll_collector[s]=lastcoll;
450  sion_filedesc->all_coll_collsize[s]=numsender;
451  }
452 
453  /* 2ND STEP: calculate startpointers */
454 
455  /* align first, not necessary, only for debugging */
456  /* startpointer=firstsize; */
457  startpointer = (firstsize % sion_filedesc->fsblksize == 0) ? firstsize : ((firstsize / sion_filedesc->fsblksize) + 1) * sion_filedesc->fsblksize;
458  sion_filedesc->globalskip = 0;
459  /* calculate mapping to collectors */
460  for (i = 0; i < sion_filedesc->ntasks; i++) {
461  sion_filedesc->all_startpointers[i] = startpointer;
462  startpointer += sion_filedesc->all_chunksizes[i];
463  sion_filedesc->globalskip += sion_filedesc->all_chunksizes[i];
464  }
465 
466  /* statistics */
467  if(sion_filedesc->colldebug>=1) {
468  _sion_update_collstat(collstat,sion_filedesc);
469  _sion_print_collstat(collstat, sion_filedesc);
470  }
471 
472  _sion_debugprint_collstat(collstat, sion_filedesc);
473 
474  _sion_destroy_collstat(collstat);
475 
476  DPRINTFP((2, DFUNCTION, _SION_DEFAULT_RANK, "leave globalskip is %lld\n", sion_filedesc->globalskip));
477  return (rc);
478 }
479 #undef DFUNCTION
480 
481 
482 
Sion File Descriptor Structure.
Definition: sion_filedesc.h:79
sion_int32 * all_coll_collector
sion_int32 * all_coll_capability
#define SION_CAPABILITY_ONLY_SENDER
Definition: sion_filedesc.h:55
sion_int64 * all_startpointers
sion_int64 * all_chunksizes
#define DFUNCTION
Calculates the size of the first meta data block.
#define SION_FILEMODE_WRITE
Definition: sion_filedesc.h:38
Sion Time Stamp Header.
sion_int32 * all_coll_collsize
#define SION_ID
Definition: sion_metadata.h:14