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