GADGET-4
mymalloc.cc
Go to the documentation of this file.
1/*******************************************************************************
2 * \copyright This file is part of the GADGET4 N-body/SPH code developed
3 * \copyright by Volker Springel. Copyright (C) 2014-2020 by Volker Springel
4 * \copyright (vspringel@mpa-garching.mpg.de) and all contributing authors.
5 *******************************************************************************/
6#include "gadgetconfig.h"
7
8#include <fcntl.h>
9#include <math.h>
10#include <mpi.h>
11#include <stddef.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <sys/mman.h>
16#include <sys/stat.h>
17#include <unistd.h>
18
19#include "../data/allvars.h"
20#include "../data/dtypes.h"
21#include "../data/mymalloc.h"
22#include "../logs/logs.h"
23#include "../main/simulation.h"
24#include "../mpi_utils/mpi_utils.h"
25#include "../mpi_utils/shared_mem_handler.h"
26#include "../system/system.h"
27
58void memory::mymalloc_init(int maxmemsize, enum restart_options restartflag)
59{
60 BlockSize = (size_t *)malloc(MAXBLOCKS * sizeof(size_t));
61 Table = (char **)malloc(MAXBLOCKS * sizeof(void *));
62 MovableFlag = (char *)malloc(MAXBLOCKS * sizeof(char));
63 GenericFlag = (char *)malloc(MAXBLOCKS * sizeof(char));
64 BasePointers = (char ***)malloc(MAXBLOCKS * sizeof(void **));
65 VarName = (char *)malloc(MAXBLOCKS * MAXCHARS * sizeof(char));
66 FunctionName = (char *)malloc(MAXBLOCKS * MAXCHARS * sizeof(char));
67 ParentFileName = (char *)malloc(MAXBLOCKS * MAXCHARS * sizeof(char));
68 FileName = (char *)malloc(MAXBLOCKS * MAXCHARS * sizeof(char));
69 LineNumber = (int *)malloc(MAXBLOCKS * sizeof(int));
70 HighMarkTabBuf = (char *)malloc((100 + 4 * MAXCHARS) * (MAXBLOCKS + 10));
71 HighMarkTabBufWithoutGeneric = (char *)malloc((100 + 4 * MAXCHARS) * (MAXBLOCKS + 10));
72
73 memset(VarName, 0, MAXBLOCKS * MAXCHARS);
74 memset(FunctionName, 0, MAXBLOCKS * MAXCHARS);
75 memset(ParentFileName, 0, MAXBLOCKS * MAXCHARS);
76 memset(FileName, 0, MAXBLOCKS * MAXCHARS);
77
78 size_t n = maxmemsize * ((size_t)1024 * 1024);
80
81 // add an extra cache line size to make sure we can guarantee that base returned from MPI_Win_allocate_shared is aligned
82 n += CACHELINESIZE;
83
84 RestartFlag = restartflag;
85
86 MPI_Barrier(MPI_COMM_WORLD); // wait until both regular and ghost processors are here
87
88 double t0 = Logs.second();
89
90 MPI_Info win_info;
91 MPI_Info_create(&win_info);
92 MPI_Info_set(win_info, "alloc_shared_noncontig", "true");
93
94 if(myMPI_Win_allocate_shared(n, 1, win_info, Shmem.SharedMemComm, &Base, &Shmem.SharedMemWin) != MPI_SUCCESS)
95 Terminate("Failed to allocate memory for `Base' (%d Mbytes).\n", All.MaxMemSize);
96
97 /* we now make sure that the allocated local buffer is really aligned, not all MPI libraries guarantee this */
98
99 int off = 0;
100 if((long long)Base / CACHELINESIZE > 0)
101 off = ((long long)Base / CACHELINESIZE + 1) * CACHELINESIZE - (long long)Base;
102
103 /* allign our base */
104 Base += off;
105
106 MPI_Info_free(&win_info);
107
108 double t1 = Logs.second();
109 if(Shmem.World_ThisTask == 0)
110 mpi_printf("MALLOC: Allocation of shared memory took %g sec\n", Logs.timediff(t0, t1));
111
112 TotBytes = FreeBytes = n - CACHELINESIZE;
113
114 AllocatedBytes = 0;
115 Nblocks = 0;
116 HighMarkBytes = 0;
117 HighMarkBytesWithoutGeneric = 0;
118 OldGlobHighMarkMB = 0;
119 OldGlobHighMarkMBWithoutGeneric = 0;
120
121 char mode[2], buf[MAXLEN_PATH_EXTRA];
122
124 strcpy(mode, "w");
125 else
126 strcpy(mode, "a");
127
128 MPI_Bcast(All.OutputDir, sizeof(All.OutputDir), MPI_BYTE, 0, MPI_COMM_WORLD);
129
130 if(Shmem.GhostRank == 0)
131 sprintf(buf, "%s%s", All.OutputDir, "memory.txt");
132 else
133 sprintf(buf, "%s%s", All.OutputDir, "memory_ghostranks.txt");
134
135 if(!(FdMemory = fopen(buf, mode)))
136 Terminate("error in opening file '%s'\n", buf);
137
138 /* tell also the ghost ranks about the total size of the simulation partition */
139 MPI_Bcast(&Shmem.Sim_NTask, 1, MPI_INT, 0, MPI_COMM_WORLD);
140
141 Shmem.GetGhostRankForSimulCommRank = (int *)mymalloc("GetGhostRankForSimulCommRank", Shmem.Sim_NTask * sizeof(int));
142 Shmem.GetShmRankForSimulCommRank = (int *)mymalloc("GetShmRankForSimulCommRank", Shmem.Sim_NTask * sizeof(int));
143 Shmem.GetNodeIDForSimulCommRank = (int *)mymalloc("GetNodeIDForSimulCommRank", Shmem.Sim_NTask * sizeof(int));
144
145 if(Shmem.GhostRank == 0)
146 {
147 MPI_Allgather(&Shmem.MyShmRankInGlobal, 1, MPI_INT, Shmem.GetGhostRankForSimulCommRank, 1, MPI_INT, Shmem.SimulationComm);
148 MPI_Allgather(&Shmem.Island_ThisTask, 1, MPI_INT, Shmem.GetShmRankForSimulCommRank, 1, MPI_INT, Shmem.SimulationComm);
149 MPI_Allgather(&Shmem.Island_Smallest_WorldTask, 1, MPI_INT, Shmem.GetNodeIDForSimulCommRank, 1, MPI_INT, Shmem.SimulationComm);
150 }
151
152 // to make sure that also the ghost processors have this table
153 MPI_Bcast(Shmem.GetGhostRankForSimulCommRank, Shmem.Sim_NTask, MPI_INT, 0, MPI_COMM_WORLD);
154 MPI_Bcast(Shmem.GetShmRankForSimulCommRank, Shmem.Sim_NTask, MPI_INT, 0, MPI_COMM_WORLD);
155
156 /* we also need the base offsets of the other MPI ranks in the same shared memory island */
157 Shmem.SharedMemBaseAddr = (void **)mymalloc("SharedMemBaseAddr", Shmem.Island_NTask * sizeof(void *));
158
159 for(int i = 0; i < Shmem.Island_NTask; i++)
160 {
161 MPI_Aint size;
162 int disp_unit;
164 }
165
166 // now propagte the alignment correction also to the base addresses that all the other processes see
167 int *off_list = (int *)Mem.mymalloc("off_list", Shmem.Island_NTask * sizeof(int));
168
169 MPI_Allgather(&off, 1, MPI_INT, off_list, 1, MPI_INT, Shmem.SharedMemComm);
170
171 for(int i = 0; i < Shmem.Island_NTask; i++)
172 Shmem.SharedMemBaseAddr[i] = (char *)Shmem.SharedMemBaseAddr[i] + off_list[i];
173
174 Mem.myfree(off_list);
175}
176
177int memory::myMPI_Win_allocate_shared(MPI_Aint size, int disp_unit, MPI_Info info, MPI_Comm comm, void *baseptr, MPI_Win *win)
178{
179#ifndef ALLOCATE_SHARED_MEMORY_VIA_POSIX
180 return MPI_Win_allocate_shared(size, disp_unit, info, comm, baseptr, win);
181#else
182
183 char shmpath[NAME_MAX];
184
185 /* Base offsets of the other MPI ranks in our shared memory mapping */
186 Shmem.SharedMemBaseAddrRaw = (char **)malloc(Shmem.Island_NTask * sizeof(char *));
187
188 long long *size_list = (long long *)malloc(Shmem.Island_NTask * sizeof(long long));
189
190 long long loc_bytes = size;
191 MPI_Allgather(&loc_bytes, 1, MPI_LONG_LONG, size_list, 1, MPI_LONG_LONG, comm);
192
193 long long tot_bytes = 0;
194 for(int i = 0; i < Shmem.Island_NTask; i++)
195 tot_bytes += size_list[i];
196
197 if(Shmem.Island_ThisTask == 0)
198 {
199 sprintf(shmpath, "/G4-%lld.dat", (long long)getpid());
200
201 int fd = shm_open(shmpath, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
202 if(fd == -1)
203 Terminate("shm_open failed in creation");
204
205 if(ftruncate(fd, tot_bytes) == -1)
206 Terminate("ftruncate failed");
207
208 /* Map the object into the caller's address space. */
209
210 void *buf = mmap(NULL, tot_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
211 if(buf == MAP_FAILED)
212 Terminate("mmap failed");
213
214 Shmem.SharedMemBaseAddrRaw[0] = (char *)buf;
215 }
216
217 MPI_Bcast(shmpath, NAME_MAX, MPI_BYTE, 0, comm);
218
219 if(Shmem.Island_ThisTask != 0)
220 {
221 int fd = shm_open(shmpath, O_RDWR, 0);
222 if(fd == -1)
223 Terminate("shm open failed in access");
224
225 void *buf = mmap(NULL, tot_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
226 if(buf == MAP_FAILED)
227 Terminate("mmap failed");
228
229 Shmem.SharedMemBaseAddrRaw[0] = (char *)buf;
230 }
231
232 for(int i = 1; i < Shmem.Island_NTask; i++)
233 Shmem.SharedMemBaseAddrRaw[i] = (char *)Shmem.SharedMemBaseAddrRaw[i - 1] + size_list[i - 1];
234
235 char **p = (char **)baseptr;
236
237 *p = Shmem.SharedMemBaseAddrRaw[Shmem.Island_ThisTask];
238
239 free(size_list);
240
241 MPI_Barrier(comm);
242
243 if(Shmem.Island_ThisTask == 0)
244 shm_unlink(shmpath);
245
246 return MPI_SUCCESS;
247#endif
248}
249
250int memory::myMPI_Win_shared_query(MPI_Win win, int rank, MPI_Aint *size, int *disp_unit, void *baseptr)
251{
252#ifndef ALLOCATE_SHARED_MEMORY_VIA_POSIX
253 return MPI_Win_shared_query(win, rank, size, disp_unit, baseptr);
254#else
255
256 char **p = (char **)baseptr;
257
258 *p = Shmem.SharedMemBaseAddrRaw[rank];
259
260 return MPI_SUCCESS;
261#endif
262}
263
264void memory::report_memory_usage(int rank, char *tabbuf)
265{
266 int thistask;
267 MPI_Comm_rank(Communicator, &thistask);
268
269 if(thistask == rank)
270 {
271 char *buf = (char *)mymalloc("buf", (100 + 4 * MAXCHARS) * (Nblocks + 10));
272 int cc = 0;
273 cc += sprintf(buf + cc, "\nMEMORY: Largest Allocation = %g Mbyte | Largest Allocation Without Generic = %g Mbyte\n\n",
274 OldGlobHighMarkMB, OldGlobHighMarkMBWithoutGeneric);
275
276 cc += sprintf(buf + cc, "%s", tabbuf);
277 if(thistask == 0)
278 {
279 if(RestartFlag == RST_BEGIN || RestartFlag == RST_RESUME || RestartFlag == RST_STARTFROMSNAP)
280 {
281 fprintf(FdMemory, "%s", buf);
282 fflush(FdMemory);
283 }
284 }
285 else
286 {
287 MPI_Send(&cc, 1, MPI_INT, 0, TAG_N, Communicator);
288 MPI_Send(buf, cc + 1, MPI_BYTE, 0, TAG_PDATA, Communicator);
289 }
290 myfree(buf);
291 }
292
293 if(thistask == 0 && rank > 0)
294 {
295 int cc;
296 MPI_Recv(&cc, 1, MPI_INT, rank, TAG_N, Communicator, MPI_STATUS_IGNORE);
297 char *buf = (char *)mymalloc("buf", cc + 1);
298 MPI_Recv(buf, cc + 1, MPI_BYTE, rank, TAG_PDATA, Communicator, MPI_STATUS_IGNORE);
299 if(RestartFlag == RST_BEGIN || RestartFlag == RST_RESUME || RestartFlag == RST_STARTFROMSNAP)
300 {
301 fprintf(FdMemory, "%s", buf);
302 fflush(FdMemory);
303 }
304 myfree(buf);
305 }
306}
307
312{
313 int flag = 0;
314 int thistask;
315 MPI_Comm_rank(Communicator, &thistask);
316
317 struct
318 {
319 double mem;
320 int rank;
321 } local, global;
322
323 local.mem = HighMarkBytes * TO_MBYTE_FAC;
324 local.rank = thistask;
325
326 MPI_Allreduce(&local, &global, 1, MPI_DOUBLE_INT, MPI_MAXLOC, Communicator);
327
328 if(global.mem >= 1.05 * OldGlobHighMarkMB)
329 {
330 OldGlobHighMarkMB = global.mem;
331 flag |= 1;
332 }
333
334 local.mem = HighMarkBytesWithoutGeneric * TO_MBYTE_FAC;
335 local.rank = thistask;
336
337 MPI_Allreduce(&local, &global, 1, MPI_DOUBLE_INT, MPI_MAXLOC, Communicator);
338
339 if(global.mem >= 1.05 * OldGlobHighMarkMBWithoutGeneric)
340 {
341 OldGlobHighMarkMBWithoutGeneric = global.mem;
342 flag |= 2;
343 }
344
345 if(flag & 2)
346 report_memory_usage(global.rank, HighMarkTabBufWithoutGeneric);
347
348 if(flag & 1)
349 report_memory_usage(global.rank, HighMarkTabBuf);
350}
351
356{
357 char *buf = (char *)malloc(200 * (Nblocks + 10));
358 dump_memory_table_buffer(buf);
359 printf("%s", buf);
360 free(buf);
361}
362
368int memory::dump_memory_table_buffer(char *p)
369{
370 int cc = 0;
371 size_t totBlocksize = 0;
372 int thistask;
373 MPI_Comm_rank(Communicator, &thistask);
374
375 cc +=
376 sprintf(p + cc, "-------------------------- Allocated Memory Blocks---- ( Step %8d )------------------\n", All.NumCurrentTiStep);
377 cc += sprintf(p + cc, "Task Nr F Variable MBytes Cumulative Function|File|Linenumber\n");
378 cc += sprintf(p + cc, "------------------------------------------------------------------------------------------\n");
379 for(int i = 0; i < Nblocks; i++)
380 {
381 totBlocksize += BlockSize[i];
382
383 cc += sprintf(p + cc, "%4d %5d %d %40s %10.4f %10.4f %s%s()|%s|%d\n", thistask, i, MovableFlag[i], VarName + i * MAXCHARS,
384 BlockSize[i] * TO_MBYTE_FAC, totBlocksize * TO_MBYTE_FAC, ParentFileName + i * MAXCHARS,
385 FunctionName + i * MAXCHARS, FileName + i * MAXCHARS, LineNumber[i]);
386 }
387 cc += sprintf(p + cc, "------------------------------------------------------------------------------------------\n");
388
389 return cc;
390}
391
402void *memory::mymalloc_movable_fullinfo(void *ptr, const char *varname, size_t n, const char *func, const char *file, int line,
403 int movable_flag, int clear_flag, char *callorigin)
404{
405 if((n % CACHELINESIZE) > 0)
406 n = (n / CACHELINESIZE + 1) * CACHELINESIZE;
407
408 if(n < CACHELINESIZE)
409 n = CACHELINESIZE;
410
411 if(Nblocks >= MAXBLOCKS)
412 Terminate("No blocks left in mymalloc_fullinfo() at %s()/%s/line %d. MAXBLOCKS=%d\n", func, file, line, MAXBLOCKS);
413
414 if(n > FreeBytes)
415 {
417 Terminate(
418 "\nNot enough memory in mymalloc_fullinfo() to allocate %g MB for variable '%s' at %s()/%s/line %d (FreeBytes=%g MB).\n",
419 n * TO_MBYTE_FAC, varname, func, file, line, FreeBytes * TO_MBYTE_FAC);
420 }
421 Table[Nblocks] = Base + (TotBytes - FreeBytes);
422 FreeBytes -= n;
423
424 strncpy(VarName + Nblocks * MAXCHARS, varname, MAXCHARS - 1);
425 if(callorigin)
426 {
427 strncpy(ParentFileName + Nblocks * MAXCHARS, callorigin, MAXCHARS - 1);
428 GenericFlag[Nblocks] = 1;
429 AllocatedBytesGeneric += n;
430 }
431 else
432 {
433 memset(ParentFileName + Nblocks * MAXCHARS, 0, MAXCHARS);
434 GenericFlag[Nblocks] = 0;
435 }
436 strncpy(FunctionName + Nblocks * MAXCHARS, func, MAXCHARS - 1);
437 strncpy(FileName + Nblocks * MAXCHARS, file, MAXCHARS - 1);
438 LineNumber[Nblocks] = line;
439
440 AllocatedBytes += n;
441 BlockSize[Nblocks] = n;
442 MovableFlag[Nblocks] = movable_flag;
443 BasePointers[Nblocks] = (char **)ptr;
444
445 Nblocks += 1;
446
447 if(AllocatedBytes - AllocatedBytesGeneric > HighMarkBytesWithoutGeneric)
448 {
449 HighMarkBytesWithoutGeneric = AllocatedBytes - AllocatedBytesGeneric;
450 dump_memory_table_buffer(HighMarkTabBufWithoutGeneric);
451 }
452
453 if(AllocatedBytes > HighMarkBytes)
454 {
455 HighMarkBytes = AllocatedBytes;
456 dump_memory_table_buffer(HighMarkTabBuf);
457 }
458
459 if(clear_flag)
460 memset(Table[Nblocks - 1], 0, n);
461
462 return Table[Nblocks - 1];
463}
464
466{
467 if((n % CACHELINESIZE) > 0)
468 n = (n / CACHELINESIZE + 1) * CACHELINESIZE;
469
470 return n;
471}
472
474{
475 if(Nblocks == 0)
476 Terminate("no allocated blocks that could be returned");
477
478 return Table[Nblocks - 1];
479}
480
490void memory::myfree_movable_fullinfo(void *p, const char *func, const char *file, int line, int movable_flag)
491{
492 if(Nblocks == 0)
493 Terminate("no allocated blocks that could be freed");
494
495 /* first, let's find the block */
496 int nr;
497
498 if(movable_flag)
499 {
500 for(nr = Nblocks - 1; nr >= 0; nr--)
501 if(p == Table[nr])
502 break;
503
504 if(nr < 0)
505 {
507 Terminate("Wrong call of myfree_movable() from %s()/%s/line %d - this block has not been allocated!\n", func, file, line);
508 }
509
510 if(nr < Nblocks - 1) /* the block is not the last allocated block */
511 {
512 /* check that all subsequent blocks are actually movable */
513 for(int i = nr + 1; i < Nblocks; i++)
514 if(MovableFlag[i] == 0)
515 {
517 myflush(stdout);
518 Terminate(
519 "Wrong call of myfree_movable() from %s()/%s/line %d - behind block=%d there are subsequent non-movable allocated "
520 "blocks\n",
521 func, file, line, nr);
522 }
523 }
524 }
525 else
526 {
527 nr = Nblocks - 1;
528 if(p != Table[nr])
529 {
531 Terminate("Wrong call of myfree() at %s()/%s/line %d: not the last allocated block!\n", func, file, line);
532 }
533 }
534
535 if(GenericFlag[nr])
536 AllocatedBytesGeneric -= BlockSize[nr];
537
538 AllocatedBytes -= BlockSize[nr];
539 FreeBytes += BlockSize[nr];
540
541 if(BasePointers[nr])
542 *BasePointers[nr] = NULL;
543
544 if(movable_flag)
545 {
546 ptrdiff_t offset = -BlockSize[nr];
547 size_t length = 0;
548
549 for(int i = nr + 1; i < Nblocks; i++)
550 length += BlockSize[i];
551
552 if(nr < Nblocks - 1)
553 memmove(Table[nr + 1] + offset, Table[nr + 1], length);
554
555 for(int i = nr + 1; i < Nblocks; i++)
556 {
557 Table[i] += offset;
558 *BasePointers[i] = *BasePointers[i] + offset;
559 }
560
561 for(int i = nr + 1; i < Nblocks; i++)
562 {
563 Table[i - 1] = Table[i];
564 BasePointers[i - 1] = BasePointers[i];
565 BlockSize[i - 1] = BlockSize[i];
566 MovableFlag[i - 1] = MovableFlag[i];
567 GenericFlag[i - 1] = GenericFlag[i];
568
569 memmove(VarName + (i - 1) * MAXCHARS, VarName + i * MAXCHARS, MAXCHARS);
570 memmove(FunctionName + (i - 1) * MAXCHARS, FunctionName + i * MAXCHARS, MAXCHARS);
571 memmove(ParentFileName + (i - 1) * MAXCHARS, ParentFileName + i * MAXCHARS, MAXCHARS);
572 memmove(FileName + (i - 1) * MAXCHARS, FileName + i * MAXCHARS, MAXCHARS);
573 LineNumber[i - 1] = LineNumber[i];
574 }
575 }
576
577 Nblocks -= 1;
578}
579
591void *memory::myrealloc_movable_fullinfo(void *p, size_t n, const char *func, const char *file, int line, int movable_flag)
592{
593 if((n % CACHELINESIZE) > 0)
594 n = (n / CACHELINESIZE + 1) * CACHELINESIZE;
595
596 if(n < CACHELINESIZE)
597 n = CACHELINESIZE;
598
599 if(Nblocks == 0)
600 Terminate("no allocated blocks that could be reallocated");
601
602 /* first, let's find the block */
603 int nr;
604
605 if(movable_flag)
606 {
607 for(nr = Nblocks - 1; nr >= 0; nr--)
608 if(p == Table[nr])
609 break;
610
611 if(nr < 0)
612 {
614 Terminate("Wrong call of myrealloc_movable() from %s()/%s/line %d - this block has not been allocated!\n", func, file, line);
615 }
616
617 if(nr < Nblocks - 1) /* the block is not the last allocated block */
618 {
619 /* check that all subsequent blocks are actually movable */
620 for(int i = nr + 1; i < Nblocks; i++)
621 if(MovableFlag[i] == 0)
622 {
624 Terminate(
625 "Wrong call of myrealloc_movable() from %s()/%s/line %d - behind block=%d there are subsequent non-movable "
626 "allocated blocks\n",
627 func, file, line, nr);
628 }
629 }
630 }
631 else
632 {
633 nr = Nblocks - 1;
634
635 if(p != Table[nr])
636 {
638 Terminate("Wrong call of myrealloc() at %s()/%s/line %d - not the last allocated block!\n", func, file, line);
639 }
640 }
641
642 if(GenericFlag[nr])
643 Terminate("unexpected");
644
645 AllocatedBytes -= BlockSize[nr];
646 FreeBytes += BlockSize[nr];
647
648 if(n > FreeBytes)
649 {
651 Terminate("At %s()/%s/line %d: Not enough memory in myremalloc_movable(n=%g MB). previous=%g FreeBytes=%g MB\n", func, file,
652 line, n * TO_MBYTE_FAC, BlockSize[nr] * TO_MBYTE_FAC, FreeBytes * TO_MBYTE_FAC);
653 }
654
655 ptrdiff_t offset = n - BlockSize[nr];
656 size_t length = 0;
657
658 for(int i = nr + 1; i < Nblocks; i++)
659 length += BlockSize[i];
660
661 if(nr < Nblocks - 1)
662 memmove(Table[nr + 1] + offset, Table[nr + 1], length);
663
664 for(int i = nr + 1; i < Nblocks; i++)
665 {
666 Table[i] += offset;
667
668 *BasePointers[i] = *BasePointers[i] + offset;
669 }
670
671 FreeBytes -= n;
672 AllocatedBytes += n;
673 BlockSize[nr] = n;
674
675 if(AllocatedBytes > HighMarkBytes)
676 {
677 HighMarkBytes = AllocatedBytes;
678 dump_memory_table_buffer(HighMarkTabBuf);
679 }
680
681 return Table[nr];
682}
683
685{
686 int errflag = 0, errflag_tot;
687
688 if(maxmemsize > (MemoryOnNode / 1024.0 / TasksInThisNode) && RankInThisNode == 0)
689 {
690 char name[MPI_MAX_PROCESSOR_NAME];
691 int len;
692 MPI_Get_processor_name(name, &len);
693
694 printf("On node '%s', we have %d MPI ranks and at most %g MB available. This is not enough space for MaxMemSize = %g MB\n", name,
695 TasksInThisNode, MemoryOnNode / 1024.0, (double)maxmemsize);
696 errflag = 1;
697 fflush(stdout);
698 }
699
700 if(maxmemsize > (SharedMemoryOnNode / 1024.0 / TasksInThisNode) && RankInThisNode == 0)
701 {
702 char name[MPI_MAX_PROCESSOR_NAME];
703 int len;
704 MPI_Get_processor_name(name, &len);
705
706 printf(
707 "On node '%s', we have %d MPI ranks and at most %g MB of *shared* memory available. This is not enough space for MaxMemSize "
708 "= %g MB\n",
709 name, TasksInThisNode, SharedMemoryOnNode / 1024.0, (double)maxmemsize);
710 errflag = 1;
711 fflush(stdout);
712 }
713
714 MPI_Allreduce(&errflag, &errflag_tot, 1, MPI_INT, MPI_MAX, Communicator);
715
716 if(errflag_tot)
717 Terminate("At least one node has insufficient memory");
718}
global_data_all_processes All
Definition: main.cc:40
double timediff(double t0, double t1)
Definition: logs.cc:488
double second(void)
Definition: logs.cc:471
void * myrealloc_movable_fullinfo(void *p, size_t n, const char *func, const char *file, int line, int movable_flag)
Reallocate an existing movable memory block.
Definition: mymalloc.cc:591
size_t FreeBytes
Definition: mymalloc.h:48
int myMPI_Win_allocate_shared(MPI_Aint size, int disp_unit, MPI_Info info, MPI_Comm comm, void *baseptr, MPI_Win *win)
Definition: mymalloc.cc:177
void * mymalloc_movable_fullinfo(void *ptr, const char *varname, size_t n, const char *func, const char *file, int line, int movable_flag, int clear_flag, char *originflag)
Allocate a movable memory block and store the relative information.
Definition: mymalloc.cc:402
void myfree_movable_fullinfo(void *p, const char *func, const char *file, int line, int movable_flag)
Deallocate a movable memory block.
Definition: mymalloc.cc:490
char * Base
Definition: mymalloc.h:49
void * myfree_query_last_block(void)
Definition: mymalloc.cc:473
void dump_memory_table(void)
Dump the buffer where the memory information is stored to the standard output.
Definition: mymalloc.cc:355
void report_detailed_memory_usage_of_largest_task(void)
Output memory usage for the task with the greatest amount of memory allocated.
Definition: mymalloc.cc:311
void check_maxmemsize_setting(int maxmemsize)
Definition: mymalloc.cc:684
int myMPI_Win_shared_query(MPI_Win win, int rank, MPI_Aint *size, int *disp_unit, void *baseptr)
Definition: mymalloc.cc:250
size_t AllocatedBytes
Definition: mymalloc.h:47
void mymalloc_init(int maxmemsize, enum restart_options restartflag)
Initialize memory manager.
Definition: mymalloc.cc:58
size_t roundup_to_multiple_of_cacheline_size(size_t n)
Definition: mymalloc.cc:465
long long MemoryOnNode
Definition: setcomm.h:42
void mpi_printf(const char *fmt,...)
Definition: setcomm.h:55
int RankInThisNode
Definition: setcomm.h:39
MPI_Comm Communicator
Definition: setcomm.h:31
int TasksInThisNode
Definition: setcomm.h:38
long long SharedMemoryOnNode
Definition: setcomm.h:43
MPI_Comm SharedMemComm
int * GetNodeIDForSimulCommRank
int Island_ThisTask
int Island_NTask
void ** SharedMemBaseAddr
int * GetShmRankForSimulCommRank
MPI_Comm SimulationComm
int Island_Smallest_WorldTask
int * GetGhostRankForSimulCommRank
int MyShmRankInGlobal
MPI_Win SharedMemWin
int World_ThisTask
#define MAXLEN_PATH_EXTRA
Definition: constants.h:301
#define TO_MBYTE_FAC
Definition: constants.h:59
restart_options
Definition: dtypes.h:312
@ RST_STARTFROMSNAP
Definition: dtypes.h:315
@ RST_BEGIN
Definition: dtypes.h:313
@ RST_RESUME
Definition: dtypes.h:314
logs Logs
Definition: main.cc:43
#define Terminate(...)
Definition: macros.h:15
shmem Shmem
Definition: main.cc:45
#define TAG_PDATA
Definition: mpi_utils.h:27
#define TAG_N
Definition: mpi_utils.h:25
#define MAXBLOCKS
Definition: mymalloc.h:19
#define mymalloc(x, y)
Definition: mymalloc.h:26
memory Mem
Definition: main.cc:44
#define myfree(x)
Definition: mymalloc.h:34
#define CACHELINESIZE
Definition: mymalloc.h:17
#define MAXCHARS
Definition: mymalloc.h:20
enum restart_options RestartFlag
Definition: allvars.h:68
char OutputDir[MAXLEN_PATH]
Definition: allvars.h:272
void myflush(FILE *fstream)
Definition: system.cc:125