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