GADGET-4
system.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
12#include "gadgetconfig.h"
13
14#include <gsl/gsl_rng.h>
15#include <math.h>
16#include <mpi.h>
17#include <signal.h>
18#include <stdarg.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <strings.h>
23#include <sys/resource.h>
24#include <sys/statvfs.h>
25#include <sys/time.h>
26#include <sys/types.h>
27#include <time.h>
28#include <unistd.h>
29
30#include "../data/allvars.h"
31#include "../data/dtypes.h"
32#include "../data/mymalloc.h"
33#include "../io/io.h"
34#include "../logs/logs.h"
35#include "../main/main.h"
36#include "../main/simulation.h"
37#include "../mpi_utils/mpi_utils.h"
38#include "../system/system.h"
39
42void init_rng(int thistask)
43{
44 random_generator = gsl_rng_alloc(gsl_rng_ranlxd1);
45
46 gsl_rng_set(random_generator, 42 + thistask); /* start-up seed, choose different on each rank */
47}
48
49double get_random_number(void) { return gsl_rng_uniform(random_generator); }
50
51void subdivide_evenly(long long N, int pieces, int index_bin, long long *first, int *count)
52{
53 if(N / pieces > INT_MAX)
54 Terminate("overflow");
55
56 int nbase = N / pieces;
57 int additional = N % pieces;
58 *first = index_bin * ((long long)nbase) + ((index_bin < additional) ? index_bin : additional);
59 *count = nbase + (index_bin < additional);
60}
61
62void subdivide_evenly(int N, int pieces, int index_bin, int *first, int *count)
63{
64 int nbase = N / pieces;
65 int additional = N % pieces;
66 *first = index_bin * nbase + ((index_bin < additional) ? index_bin : additional);
67 *count = nbase + (index_bin < additional);
68}
69
70void subdivide_evenly_get_bin(int N, int pieces, int index, int *bin)
71{
72 int nbase = N / pieces;
73 int additional = N % pieces;
74
75 if(index < additional * (nbase + 1))
76 *bin = index / (nbase + 1);
77 else
78 *bin = (index - additional) / nbase;
79}
80
81void permutate_chunks_in_list(int ncount, int *list)
82{
83#define WALK_N_PIECES 32
84#define WALK_N_SIZE 500
86 int nchunk = 1;
87 int nchunksize = ncount;
89 if(ncount > WALK_N_PIECES * WALK_N_SIZE)
90 {
91 nchunk = WALK_N_PIECES;
92 nchunksize = WALK_N_SIZE;
93 }
94
95 int currentchunk = 0;
97 int *chunked_TargetList = (int *)Mem.mymalloc("chunked_TargetList", ncount * sizeof(int));
98 for(int n = 0, nextparticle = 0; n < ncount; n++)
99 {
100 int i = nextparticle;
101
102 chunked_TargetList[n] = list[i];
103 if(i < ncount)
104 {
105 nextparticle++;
106
107 if((nextparticle % nchunksize) == 0)
108 nextparticle += (nchunk - 1) * nchunksize;
109
110 if(nextparticle >= ncount)
111 {
112 currentchunk++;
113 if(currentchunk < nchunk)
114 nextparticle = currentchunk * nchunksize;
115 }
116 }
117 }
118
119 for(int n = 0; n < ncount; n++)
120 list[n] = chunked_TargetList[n];
121
122 Mem.myfree(chunked_TargetList);
123}
124
125void myflush(FILE *fstream)
126{
127#ifdef REDUCE_FLUSH
128 /* do nothing */
129 (void)fstream;
130#else
131 fflush(fstream);
132#endif
133}
134
135#ifdef DEBUG
136#include <fenv.h>
138{
139#if defined(DEBUG_ENABLE_FPU_EXCEPTIONS) && defined(__linux__)
140 /* enable floating point exceptions */
141
142 extern int feenableexcept(int __excepts);
143 feenableexcept(FE_DIVBYZERO | FE_INVALID);
144
145 /* Note: FPU exceptions appear not to work properly
146 * when the Intel C-Compiler for Linux is used
147 */
148#endif
149
150 /* set core-dump size to infinity */
151 rlimit rlim;
152 getrlimit(RLIMIT_CORE, &rlim);
153 rlim.rlim_cur = RLIM_INFINITY;
154 setrlimit(RLIMIT_CORE, &rlim);
155
156 /* MPICH catches the signales SIGSEGV, SIGBUS, and SIGFPE....
157 * The following statements reset things to the default handlers,
158 * which will generate a core file.
159 */
160 signal(SIGSEGV, SIG_DFL);
161 signal(SIGBUS, SIG_DFL);
162 signal(SIGFPE, SIG_DFL);
163 signal(SIGINT, SIG_DFL);
164}
165#endif
166
167long long sim::report_comittable_memory(long long *MemTotal, long long *Committed_AS, long long *SwapTotal, long long *SwapFree)
168{
169 FILE *fd;
170 char buf[1024];
171
172 if((fd = fopen("/proc/meminfo", "r")))
173 {
174 while(1)
175 {
176 if(fgets(buf, 500, fd) != buf)
177 break;
178
179 if(bcmp(buf, "MemTotal", 8) == 0)
180 {
181 *MemTotal = atoll(buf + 10);
182 }
183 if(strncmp(buf, "Committed_AS", 12) == 0)
184 {
185 *Committed_AS = atoll(buf + 14);
186 }
187 if(strncmp(buf, "SwapTotal", 9) == 0)
188 {
189 *SwapTotal = atoll(buf + 11);
190 }
191 if(strncmp(buf, "SwapFree", 8) == 0)
192 {
193 *SwapFree = atoll(buf + 10);
194 }
195 }
196 fclose(fd);
197 }
198
199 return (*MemTotal - *Committed_AS);
200}
201
202// returns kByte
204{
205 struct statvfs buf;
206
207 if(statvfs("/dev/shm", &buf) == 0)
208 {
209 return (1024.0 * (uint64_t)buf.f_bsize * ((uint64_t)(buf.f_bavail))) * TO_MBYTE_FAC;
210 }
211 else
212 return 0;
213}
214
216{
217 long long *sizelist, maxsize[7], minsize[7];
218 double avgsize[7];
219 int i, imem, mintask[7], maxtask[7];
220 long long Mem[7];
221 char label[512];
222
223 Mem[0] = report_comittable_memory(&Mem[1], &Mem[2], &Mem[3], &Mem[4]);
224 Mem[5] = Mem[1] - Mem[0];
225
227
228 MemoryOnNode = Mem[1];
230
231 for(imem = 0; imem < 7; imem++)
232 {
233 sizelist = (long long *)malloc(NTask * sizeof(long long));
234 MPI_Allgather(&Mem[imem], sizeof(long long), MPI_BYTE, sizelist, sizeof(long long), MPI_BYTE, Communicator);
235
236 for(i = 1, mintask[imem] = 0, maxtask[imem] = 0, maxsize[imem] = minsize[imem] = sizelist[0], avgsize[imem] = sizelist[0];
237 i < NTask; i++)
238 {
239 if(sizelist[i] > maxsize[imem])
240 {
241 maxsize[imem] = sizelist[i];
242 maxtask[imem] = i;
243 }
244 if(sizelist[i] < minsize[imem])
245 {
246 minsize[imem] = sizelist[i];
247 mintask[imem] = i;
248 }
249 avgsize[imem] += sizelist[i];
250 }
251
252 free(sizelist);
253 }
254
255 if(ThisTask == 0)
256 {
257 printf(
258 "\n-------------------------------------------------------------------------------------------------------------------------"
259 "\n");
260 for(imem = 0; imem < 7; imem++)
261 {
262 switch(imem)
263 {
264 case 0:
265 sprintf(label, "AvailMem");
266 break;
267 case 1:
268 sprintf(label, "Total Mem");
269 break;
270 case 2:
271 sprintf(label, "Committed_AS");
272 break;
273 case 3:
274 sprintf(label, "SwapTotal");
275 break;
276 case 4:
277 sprintf(label, "SwapFree");
278 break;
279 case 5:
280 sprintf(label, "AllocMem");
281 break;
282 case 6:
283 sprintf(label, "avail /dev/shm");
284 break;
285 }
286 printf("%s:\t Largest = %10.2f Mb (on task=%4d), Smallest = %10.2f Mb (on task=%4d), Average = %10.2f Mb\n", label,
287 maxsize[imem] / (1024.0), maxtask[imem], minsize[imem] / (1024.0), mintask[imem], avgsize[imem] / (1024.0 * NTask));
288 }
289 printf(
290 "-------------------------------------------------------------------------------------------------------------------------"
291 "\n");
292 }
293
294 char name[MPI_MAX_PROCESSOR_NAME];
295
296 if(ThisTask == maxtask[2])
297 {
298 int len;
299 MPI_Get_processor_name(name, &len);
300 }
301
302 MPI_Bcast(name, MPI_MAX_PROCESSOR_NAME, MPI_BYTE, maxtask[2], Communicator);
303
304 if(ThisTask == 0)
305 {
306 printf("Task=%d has the maximum commited memory and is host: %s\n", ThisTask, name);
307 printf(
308 "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
309 "\n");
310 }
311
312 fflush(stdout);
313}
314
315/* the following function finds the last significant bit, as in the linux kernel */
316int my_fls(unsigned int x)
317{
318 int r = 32;
319
320 if(!x)
321 return 0;
322 if(!(x & 0xffff0000u))
323 {
324 x <<= 16;
325 r -= 16;
326 }
327 if(!(x & 0xff000000u))
328 {
329 x <<= 8;
330 r -= 8;
331 }
332 if(!(x & 0xf0000000u))
333 {
334 x <<= 4;
335 r -= 4;
336 }
337 if(!(x & 0xc0000000u))
338 {
339 x <<= 2;
340 r -= 2;
341 }
342 if(!(x & 0x80000000u))
343 {
344 x <<= 1;
345 r -= 1;
346 }
347 return r;
348}
long long MemoryOnNode
Definition: setcomm.h:42
int ThisTask
Definition: setcomm.h:33
int NTask
Definition: setcomm.h:32
MPI_Comm Communicator
Definition: setcomm.h:31
long long SharedMemoryOnNode
Definition: setcomm.h:43
long long report_free_size_in_tmpfs(void)
Definition: system.cc:203
void mpi_report_comittable_memory(void)
Definition: system.cc:215
long long report_comittable_memory(long long *MemTotal, long long *Committed_AS, long long *SwapTotal, long long *SwapFree)
Definition: system.cc:167
#define TO_MBYTE_FAC
Definition: constants.h:59
#define Terminate(...)
Definition: macros.h:15
memory Mem
Definition: main.cc:44
void subdivide_evenly_get_bin(int N, int pieces, int index, int *bin)
Definition: system.cc:70
void permutate_chunks_in_list(int ncount, int *list)
Definition: system.cc:81
gsl_rng * random_generator
Definition: system.cc:40
int my_fls(unsigned int x)
Definition: system.cc:316
void subdivide_evenly(long long N, int pieces, int index_bin, long long *first, int *count)
Definition: system.cc:51
void init_rng(int thistask)
Definition: system.cc:42
#define WALK_N_PIECES
void myflush(FILE *fstream)
Definition: system.cc:125
#define WALK_N_SIZE
double get_random_number(void)
Definition: system.cc:49
void enable_core_dumps_and_fpu_exceptions(void)