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