FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
runtime.cpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
7#include <kernel/runtime.hpp>
9#include <kernel/util/dist.hpp>
10#include <kernel/util/memory_pool.hpp>
11#include <kernel/util/os_windows.hpp>
13#ifdef FEAT_HAVE_DEATH_HANDLER
14#include <death_handler.h>
15#endif
16
17#include <cstdlib>
18#include <fstream>
19#include <cstring>
20#include <cstdlib>
21
22#if defined(__linux) || defined(__unix__)
23#include <sys/types.h>
24#include <unistd.h>
25#include <execinfo.h>
26#endif
27
28#ifdef FEAT_HAVE_MPI
29#include <mpi.h>
30#endif
31
32#ifdef FEAT_HAVE_CUDA
33#include <kernel/util/cuda_util.hpp>
34#endif
35
36#ifdef FEAT_HAVE_CUDSS
37#include <cudss.h>
38#endif
39
40using namespace FEAT;
41
42// static member initialization
43bool Runtime::_initialized = false;
44bool Runtime::_finalized = false;
45bool Runtime::SyncGuard::sync_on = true;
46
47#ifdef FEAT_HAVE_CUDSS
48static cudssHandle_t feat_cudss_handle = nullptr;
49#endif
50
51void Runtime::initialize(int& argc, char**& argv)
52{
57#if defined(_WIN32) && defined(FEAT_TESTING_VC)
60#endif
61
62 if (_initialized)
63 {
64 std::cerr << "ERROR: Runtime::initialize called twice!\n";
65 std::cerr.flush();
67 }
68 if (_finalized)
69 {
70 std::cerr << "ERROR: Runtime::initialize called after Runtime::finalize!\n";
71 std::cerr.flush();
73 }
74
75 // initialize Dist operations
76 if(!Dist::initialize(argc, argv))
77 {
78 std::cerr << "ERROR: Failed to initialize Dist operations!\n";
79 std::cerr.flush();
81 }
82
83 // get the MPI world comm rank of this process
84 const int my_rank = Dist::Comm::world().rank();
85
86 // initialize likwid marker api
88 // initialize memory pool for main memory
90
91#ifdef FEAT_HAVE_CUDA
92 // initialize memory pool for CUDA memory
93 Util::cuda_initialize(my_rank, 1, 1, Util::cuda_get_device_count());
94 Util::cuda_set_blocksize(256, 256, 256, 256, 256, 128);
95#endif
96
97#ifdef FEAT_HAVE_CUDSS
98 if(CUDSS_STATUS_SUCCESS != cudssCreate(&feat_cudss_handle))
99 {
100 std::cerr << "ERROR: Failed to initialize cuDSS handle!\n";
101 std::cerr.flush();
103 }
104#ifdef FEAT_HAVE_MPI
105 // set communication layer to nullptr, so cuDSS will read its path from $CUDSS_COMM_LIB; this
106 // must *not* be called in non-MPI mode, because cuDSS would try to call MPI routines otherwise
107 cudssSetCommLayer(feat_cudss_handle, nullptr);
108#endif // FEAT_HAVE_MPI
109#endif // FEAT_HAVE_CUDSS
110
111 // check whether '---debug [<ranks...>]' option is given
112 // if so, then trigger a breakpoint for the specified ranks
113 for(int iarg = 1; iarg < argc; ++iarg)
114 {
115 if(strcmp(argv[iarg], "---build-info") == 0)
116 {
117 // dump some information about our build to the console
118 if(my_rank == 0)
119 {
120 std::cout << "--- FEAT BUILD INFORMATION ---\n";
121 // 123456789-123456789-123456789-
122 std::cout << "__cplusplus...................: " << __cplusplus << "\n";
123#ifdef __STDC_VERSION__
124 std::cout << "__STDC_VERSION__..............: " << __STDC_VERSION__ << "\n";
125#else
126 std::cout << "__STDC_VERSION__..............: -N/A-\n";
127#endif
128#ifdef __STDC_HOSTED__
129 std::cout << "__STDC_HOSTED__...............: " << __STDC_HOSTED__ << "\n";
130#else
131 std::cout << "__STDC_HOSTED__...............: -N/A-\n";
132#endif
133#ifdef __STDCPP_THREADS__
134 std::cout << "__STDCPP_THREADS__............: " << __STDCPP_THREADS__ << "\n";
135#else
136 std::cout << "__STDCPP_THREADS__............: -N/A-\n";
137#endif
138#ifdef _OPENMP
139 std::cout << "_OPENMP.......................: yes\n";
140#else
141 std::cout << "_OPENMP.......................: no\n";
142#endif
143 std::cout << "FEAT Version..................: " << FEAT::version_major << "." << FEAT::version_minor << "." << FEAT::version_patch << "\n";
144#ifdef FEAT_GIT_SHA1
145 std::cout << "FEAT_GIT_SHA1.................: " << FEAT_GIT_SHA1 << "\n";
146#else
147 std::cout << "FEAT_GIT_SHA1.................: -N/A-\n";
148#endif
149#ifdef FEAT_BUILD_ID
150 std::cout << "FEAT_BUILD_ID.................: " << FEAT_BUILD_ID << "\n";
151#else
152 std::cout << "FEAT_BUILD_ID.................: -N/A-\n";
153#endif
154#ifdef FEAT_SOURCE_DIR
155 std::cout << "FEAT_SOURCE_DIR...............: " << FEAT_SOURCE_DIR << "\n";
156#else
157 std::cout << "FEAT_SOURCE_DIR...............: -N/A-\n";
158#endif
159#ifdef FEAT_BUILD_DIR
160 std::cout << "FEAT_BUILD_DIR................: " << FEAT_BUILD_DIR << "\n";
161#else
162 std::cout << "FEAT_BUILD_DIR................: -N/A-\n";
163#endif
164#ifdef FEAT_COMPILER
165 std::cout << "FEAT_COMPILER.................: " << FEAT_COMPILER << "\n";
166#else
167 std::cout << "FEAT_COMPILER.................: -N/A-\n";
168#endif
169#ifdef FEAT_COMPILER_GNU
170 std::cout << "FEAT_COMPILER_GNU.............: " << FEAT_COMPILER_GNU << "\n";
171#else
172 std::cout << "FEAT_COMPILER_GNU.............: -N/A-\n";
173#endif
174#ifdef FEAT_COMPILER_CLANG
175 std::cout << "FEAT_COMPILER_CLANG...........: " << FEAT_COMPILER_CLANG << "\n";
176#else
177 std::cout << "FEAT_COMPILER_CLANG...........: -N/A-\n";
178#endif
179#ifdef FEAT_COMPILER_CRAY
180 std::cout << "FEAT_COMPILER_CRAY............: " << FEAT_COMPILER_CRAY << "\n";
181#else
182 std::cout << "FEAT_COMPILER_CRAY............: -N/A-\n";
183#endif
184#ifdef FEAT_COMPILER_INTEL
185 std::cout << "FEAT_COMPILER_INTEL...........: " << FEAT_COMPILER_INTEL << "\n";
186#else
187 std::cout << "FEAT_COMPILER_INTEL...........: -N/A-\n";
188#endif
189#ifdef FEAT_COMPILER_MICROSOFT
190 std::cout << "FEAT_COMPILER_MICROSOFT.......: " << FEAT_COMPILER_MICROSOFT << "\n";
191#else
192 std::cout << "FEAT_COMPILER_MICROSOFT.......: -N/A-\n";
193#endif
194#ifdef FEAT_DEBUG_MODE
195 std::cout << "FEAT_DEBUG_MODE...............: yes\n";
196#else
197 std::cout << "FEAT_DEBUG_MODE...............: no\n";
198#endif
199#ifdef FEAT_EICKT
200 std::cout << "FEAT_EICKT....................: yes\n";
201#else
202 std::cout << "FEAT_EICKT....................: no\n";
203#endif
204#ifdef FEAT_INDEX_U32
205 std::cout << "FEAT_INDEX_U32................: yes\n";
206#else
207 std::cout << "FEAT_INDEX_U32................: no\n";
208#endif
209#ifdef FEAT_MPI_THREAD_MULTIPLE
210 std::cout << "FEAT_MPI_THREAD_MULTIPLE......: yes\n";
211#else
212 std::cout << "FEAT_MPI_THREAD_MULTIPLE......: no\n";
213#endif
214#ifdef FEAT_NO_CONFIG
215 std::cout << "FEAT_NO_CONFIG................: yes\n";
216#else
217 std::cout << "FEAT_NO_CONFIG................: no\n";
218#endif
219#ifdef FEAT_OVERRIDE_MPI_OPS
220 std::cout << "FEAT_OVERRIDE_MPI_OPS.........: yes\n";
221#else
222 std::cout << "FEAT_OVERRIDE_MPI_OPS.........: no\n";
223#endif
224#ifdef FEAT_USE_MKL_LEGACY_SPMV
225 std::cout << "FEAT_USE_MKL_LEGACY_SPMV......: yes\n";
226#else
227 std::cout << "FEAT_USE_MKL_LEGACY_SPMV......: no\n";
228#endif
229#ifdef FEAT_UNROLL_BANDED
230 std::cout << "FEAT_UNROLL_BANDED............: yes\n";
231#else
232 std::cout << "FEAT_UNROLL_BANDED............: no\n";
233#endif
234#ifdef FEAT_HAVE_ALGLIB
235 std::cout << "FEAT_HAVE_ALGLIB..............: yes\n";
236#else
237 std::cout << "FEAT_HAVE_ALGLIB..............: no\n";
238#endif
239#ifdef FEAT_HAVE_BOOST
240 std::cout << "FEAT_HAVE_BOOST...............: yes\n";
241#else
242 std::cout << "FEAT_HAVE_BOOST...............: no\n";
243#endif
244#ifdef FEAT_HAVE_CGAL
245 std::cout << "FEAT_HAVE_CGAL................: yes\n";
246#else
247 std::cout << "FEAT_HAVE_CGAL................: no\n";
248#endif
249#ifdef FEAT_HAVE_CUDA
250 std::cout << "FEAT_HAVE_CUDA................: yes\n";
251#else
252 std::cout << "FEAT_HAVE_CUDA................: no\n";
253#endif
254#ifdef FEAT_HAVE_CUDSS
255 std::cout << "FEAT_HAVE_CUDSS...............: yes\n";
256#else
257 std::cout << "FEAT_HAVE_CUDSS...............: no\n";
258#endif
259#ifdef FEAT_HAVE_DEATH_HANDLER
260 std::cout << "FEAT_HAVE_DEATH_HANDLER.......: yes\n";
261#else
262 std::cout << "FEAT_HAVE_DEATH_HANDLER.......: no\n";
263#endif
264#ifdef FEAT_HAVE_FPARSER
265 std::cout << "FEAT_HAVE_FPARSER.............: yes\n";
266#else
267 std::cout << "FEAT_HAVE_FPARSER.............: no\n";
268#endif
269#ifdef FEAT_HAVE_FLOATX
270 std::cout << "FEAT_HAVE_FLOATX..............: yes\n";
271#else
272 std::cout << "FEAT_HAVE_FLOATX..............: no\n";
273#endif
274#ifdef FEAT_HAVE_HALFMATH
275 std::cout << "FEAT_HAVE_HALFMATH............: yes\n";
276#else
277 std::cout << "FEAT_HAVE_HALFMATH............: no\n";
278#endif
279#ifdef FEAT_HAVE_HYPRE
280 std::cout << "FEAT_HAVE_HYPRE...............: yes\n";
281#else
282 std::cout << "FEAT_HAVE_HYPRE...............: no\n";
283#endif
284#ifdef FEAT_HAVE_MESHHEXER
285 std::cout << "FEAT_HAVE_MESHHEXER...........: yes\n";
286#else
287 std::cout << "FEAT_HAVE_MESHHEXER...........: no\n";
288#endif
289#ifdef FEAT_HAVE_METIS
290 std::cout << "FEAT_HAVE_METIS...............: yes\n";
291#else
292 std::cout << "FEAT_HAVE_METIS...............: no\n";
293#endif
294#ifdef FEAT_HAVE_MKL
295 std::cout << "FEAT_HAVE_MKL.................: yes\n";
296#else
297 std::cout << "FEAT_HAVE_MKL.................: no\n";
298#endif
299#ifdef FEAT_HAVE_MUMPS
300 std::cout << "FEAT_HAVE_MUMPS...............: yes\n";
301#else
302 std::cout << "FEAT_HAVE_MUMPS...............: no\n";
303#endif
304#ifdef FEAT_HAVE_MPI
305 std::cout << "FEAT_HAVE_MPI.................: yes\n";
306#else
307 std::cout << "FEAT_HAVE_MPI.................: no\n";
308#endif
309#ifdef FEAT_HAVE_OMP
310 std::cout << "FEAT_HAVE_OMP.................: yes\n";
311#else
312 std::cout << "FEAT_HAVE_OMP.................: no\n";
313#endif
314#ifdef FEAT_HAVE_PARMETIS
315 std::cout << "FEAT_HAVE_PARMETIS............: yes\n";
316#else
317 std::cout << "FEAT_HAVE_PARMETIS............: no\n";
318#endif
319#ifdef FEAT_HAVE_PMP
320 std::cout << "FEAT_HAVE_PMP.................: yes\n";
321#else
322 std::cout << "FEAT_HAVE_PMP.................: no\n";
323#endif
324#ifdef FEAT_HAVE_QUADMATH
325 std::cout << "FEAT_HAVE_QUADMATH............: yes\n";
326#else
327 std::cout << "FEAT_HAVE_QUADMATH............: no\n";
328#endif
329#ifdef FEAT_HAVE_SUITESPARSE
330 std::cout << "FEAT_HAVE_SUITESPARSE.........: yes\n";
331#else
332 std::cout << "FEAT_HAVE_SUITESPARSE.........: no\n";
333#endif
334#ifdef FEAT_HAVE_SUPERLU_DIST
335 std::cout << "FEAT_HAVE_SUPERLU_DIST........: yes\n";
336#else
337 std::cout << "FEAT_HAVE_SUPERLU_DIST........: no\n";
338#endif
339#ifdef FEAT_HAVE_TRIANGLE
340 std::cout << "FEAT_HAVE_TRIANGLE............: yes\n";
341#else
342 std::cout << "FEAT_HAVE_TRIANGLE............: no\n";
343#endif
344#ifdef FEAT_HAVE_TRILINOS
345 std::cout << "FEAT_HAVE_TRILINOS............: yes\n";
346#else
347 std::cout << "FEAT_HAVE_TRILINOS............: no\n";
348#endif
349#ifdef FEAT_HAVE_UMFPACK
350 std::cout << "FEAT_HAVE_UMFPACK.............: yes\n";
351#else
352 std::cout << "FEAT_HAVE_UMFPACK.............: no\n";
353#endif
354#ifdef FEAT_HAVE_ZFP
355 std::cout << "FEAT_HAVE_ZFP.................: yes\n";
356#else
357 std::cout << "FEAT_HAVE_ZFP.................: no\n";
358#endif
359#ifdef FEAT_HAVE_ZLIB
360 std::cout << "FEAT_HAVE_ZLIB................: yes\n";
361#else
362 std::cout << "FEAT_HAVE_ZLIB................: no\n";
363#endif
364#ifdef FEAT_HAVE_ZOLTAN
365 std::cout << "FEAT_HAVE_ZOLTAN..............: yes\n";
366#else
367 std::cout << "FEAT_HAVE_ZOLTAN..............: no\n";
368#endif
369 std::cout << "--- END OF FEAT BUILD INFORMATION ---\n";
370 std::cout.flush();
371 }
372 }
373
374 if(strcmp(argv[iarg], "---print-pid") == 0)
375 {
376#ifdef FEAT_HAVE_MPI
377#if defined(_WIN32)
378 std::cout << "Process ID " << std::setw(6) << Windows::get_current_process_id() << " runs rank " << my_rank << "\n";
379#elif defined(__linux) || defined(__unix__)
380 std::cout << "Process ID " << std::setw(6) << getpid() << " runs rank " << my_rank << "\n";
381#endif // defined(_WIN32)
382#else // no FEAT_HAVE_MPI
383#if defined(_WIN32)
384 std::cout << "Process ID " << std::setw(6) << Windows::get_current_process_id() << "\n";
385#elif defined(__linux) || defined(__unix__)
386 std::cout << "Process ID " << std::setw(6) << getpid() << "\n";
387#endif // defined(_WIN32)
388#endif // FEAT_HAVE_MPI
389 std::cout.flush();
390 }
391
392#ifdef FEAT_COMPILER_MICROSOFT
393 if(strcmp(argv[iarg], "---debug-break") == 0)
394 {
395#ifdef FEAT_HAVE_MPI
396 // in an MPI case, the ranks to debug have to be specified
397 for(++iarg; iarg < argc; ++iarg)
398 {
399 char* endptr = nullptr;
400 int irank = int(std::strtol(argv[iarg], &endptr, 0));
401 if((endptr != argv[iarg]) && (*endptr == '\0'))
402 {
403 if(irank == my_rank)
404 {
405 __debugbreak();
406 break;
407 }
408 }
409 else // argv[iarg] could not be parsed as a number
410 {
411 --iarg;
412 break;
413 }
414 }
415#else // no FEAT_HAVE_MPI
416 __debugbreak();
417#endif // FEAT_HAVE_MPI
418 continue;
419 }
420#endif // FEAT_COMPILER_MICROSOFT
421 }
422
423 _initialized = true;
424 // finally initialize Syncguard
425 SyncGuard::sync_on = true;
426}
427
428void Runtime::abort(bool dump_call_stack)
429{
430 if(dump_call_stack)
431 {
432#if defined(__linux) || defined(__unix__)
433#if defined(FEAT_HAVE_DEATH_HANDLER) and not defined(FEAT_HAVE_MPI)
434 Debug::DeathHandler death_handler;
435#else
436 // https://www.gnu.org/software/libc/manual/html_node/Backtraces.html
437 void* buffer[1024];
438 auto bt_size = backtrace(buffer, 1024);
439 char** bt_symb = backtrace_symbols(buffer, bt_size);
440 if((bt_size > 0) && (bt_symb != nullptr))
441 {
442 fprintf(stderr, "\nCall-Stack Back-Trace:\n");
443 fprintf(stderr, "----------------------\n");
444 for(decltype(bt_size) i(0); i < bt_size; ++i)
445 fprintf(stderr, "%s\n", bt_symb[i]);
446 fflush(stderr);
447 }
448#endif
449#elif defined(_WIN32)
451#endif
452 }
453
454#ifdef FEAT_HAVE_MPI
455 ::MPI_Abort(MPI_COMM_WORLD, 1);
456#endif
457 std::abort();
458}
459
461{
462 if (!_initialized)
463 {
464 std::cerr << "ERROR: Runtime::finalize called before Runtime::initialize!\n";
465 std::cerr.flush();
467 }
468 if (_finalized)
469 {
470 std::cerr << "ERROR: Runtime::finalize called twice!\n";
471 std::cerr.flush();
473 }
474
476
477#ifdef FEAT_HAVE_CUDSS
478 cudssDestroy(feat_cudss_handle);
479#endif
480
481#ifdef FEAT_HAVE_CUDA
482 Util::cuda_finalize();
483#endif
484
485 // finalize Dist operations
487 // finalize Likwid markerAPI
489
490 // reset device, which is/can be nesessary to have sanitizer and profiler work properly
491 // this should not be called, if there are other cuda contexts live while FEAT is finalized,
492 // for example if MPI is initilized by another library which shares the same process, or a feat app
493 // is called by another app without reinitializing the cuda device
494#if defined(FEAT_HAVE_CUDA) && defined(FEAT_FINALIZE_RESETS_DEVICE)
495 Util::cuda_reset_device();
496#endif
497 _finalized = true;
498
499 // return successful exit code
500 return EXIT_SUCCESS;
501}
502
504{
505#ifdef FEAT_HAVE_CUDSS
506 return feat_cudss_handle;
507#else
508 return nullptr;
509#endif
510}
FEAT Kernel base header.
int rank() const
Returns the rank of this process in this communicator.
Definition: dist.hpp:1494
static Comm world()
Returns a copy of the world communicator.
Definition: dist.cpp:429
static void initialize()
Setup memory pools.
Definition: memory_pool.hpp:62
static void finalize()
Shutdown memory pool and clean up allocated memory pools.
Definition: memory_pool.hpp:67
static int finalize()
FEAT finalization.
Definition: runtime.cpp:460
static bool _finalized
signals, if finalize was called
Definition: runtime.hpp:31
static void * get_cudss_handle()
Returns the unique cuDSS third-party library handle.
Definition: runtime.cpp:503
static bool _initialized
signals, if initialize was called
Definition: runtime.hpp:28
static void initialize(int &argc, char **&argv)
FEAT initialization.
Definition: runtime.cpp:51
static void abort(bool dump_call_stack=true)
FEAT abortion.
Definition: runtime.cpp:428
#define FEAT_MARKER_INIT
Init the marker api.
#define FEAT_MARKER_CLOSE
Finalize marker api, writes data to file, only call once.
bool initialize(int &argc, char **&argv)
Initializes the distributed communication system.
Definition: dist.cpp:105
void finalize()
Finalizes the distributed communication system.
Definition: dist.cpp:148
void install_seh_filter()
Installs custom Windows Structured-Exception-Handler filter.
Definition: os_windows.cpp:208
void dump_call_stack_to_stderr()
Dumps the call-stack to stderr.
Definition: os_windows.cpp:152
void disable_error_prompts()
Disables Windows error dialog boxes.
Definition: os_windows.cpp:214
unsigned long get_current_process_id()
Returns the Windows process ID for the current process.
Definition: os_windows.cpp:222
FEAT namespace.
Definition: adjactor.hpp:12
static constexpr int version_major
FEAT major version number.
static constexpr int version_patch
FEAT patch version number (month)
static constexpr int version_minor
FEAT minor version number (year)