1 /* 2 3 This file defines part of the initialization of PETSc 4 5 This file uses regular malloc and free because it cannot known 6 what malloc is being used until it has already processed the input. 7 */ 8 9 #include <petscsys.h> /*I "petscsys.h" I*/ 10 #include <petsc/private/petscimpl.h> 11 #include <petscvalgrind.h> 12 #include <petscviewer.h> 13 #if defined(PETSC_USE_LOG) 14 PETSC_INTERN PetscErrorCode PetscLogInitialize(void); 15 #endif 16 17 #if defined(PETSC_HAVE_SYS_SYSINFO_H) 18 #include <sys/sysinfo.h> 19 #endif 20 #if defined(PETSC_HAVE_UNISTD_H) 21 #include <unistd.h> 22 #endif 23 #if defined(PETSC_HAVE_CUDA) 24 #include <cuda_runtime.h> 25 #include <petsccublas.h> 26 #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) 27 #include "mpi-ext.h" /* Needed for OpenMPI CUDA-aware check */ 28 #endif 29 #endif 30 31 #if defined(PETSC_HAVE_VIENNACL) 32 PETSC_EXTERN PetscErrorCode PetscViennaCLInit(); 33 #endif 34 35 /* ------------------------Nasty global variables -------------------------------*/ 36 /* 37 Indicates if PETSc started up MPI, or it was 38 already started before PETSc was initialized. 39 */ 40 PetscBool PetscBeganMPI = PETSC_FALSE; 41 PetscBool PetscInitializeCalled = PETSC_FALSE; 42 PetscBool PetscFinalizeCalled = PETSC_FALSE; 43 PetscBool PetscCUDAInitialized = PETSC_FALSE; 44 45 PetscMPIInt PetscGlobalRank = -1; 46 PetscMPIInt PetscGlobalSize = -1; 47 48 PetscBool use_gpu_aware_mpi = PETSC_TRUE; 49 50 #if defined(PETSC_HAVE_COMPLEX) 51 #if defined(PETSC_COMPLEX_INSTANTIATE) 52 template <> class std::complex<double>; /* instantiate complex template class */ 53 #endif 54 #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX) 55 MPI_Datatype MPIU_C_DOUBLE_COMPLEX; 56 MPI_Datatype MPIU_C_COMPLEX; 57 #endif 58 59 /*MC 60 PETSC_i - the imaginary number i 61 62 Synopsis: 63 #include <petscsys.h> 64 PetscComplex PETSC_i; 65 66 Level: beginner 67 68 Note: 69 Complex numbers are automatically available if PETSc located a working complex implementation 70 71 .seealso: PetscRealPart(), PetscImaginaryPart(), PetscRealPartComplex(), PetscImaginaryPartComplex() 72 M*/ 73 PetscComplex PETSC_i; 74 #endif 75 #if defined(PETSC_USE_REAL___FLOAT128) 76 MPI_Datatype MPIU___FLOAT128 = 0; 77 #if defined(PETSC_HAVE_COMPLEX) 78 MPI_Datatype MPIU___COMPLEX128 = 0; 79 #endif 80 #elif defined(PETSC_USE_REAL___FP16) 81 MPI_Datatype MPIU___FP16 = 0; 82 #endif 83 MPI_Datatype MPIU_2SCALAR = 0; 84 #if defined(PETSC_USE_64BIT_INDICES) 85 MPI_Datatype MPIU_2INT = 0; 86 #endif 87 MPI_Datatype MPIU_BOOL; 88 MPI_Datatype MPIU_ENUM; 89 MPI_Datatype MPIU_FORTRANADDR; 90 MPI_Datatype MPIU_SIZE_T; 91 92 /* 93 Function that is called to display all error messages 94 */ 95 PetscErrorCode (*PetscErrorPrintf)(const char [],...) = PetscErrorPrintfDefault; 96 PetscErrorCode (*PetscHelpPrintf)(MPI_Comm,const char [],...) = PetscHelpPrintfDefault; 97 PetscErrorCode (*PetscVFPrintf)(FILE*,const char[],va_list) = PetscVFPrintfDefault; 98 /* 99 This is needed to turn on/off GPU synchronization 100 */ 101 PetscBool PetscViennaCLSynchronize = PETSC_FALSE; 102 PetscBool PetscCUDASynchronize = PETSC_FALSE; 103 104 /* ------------------------------------------------------------------------------*/ 105 /* 106 Optional file where all PETSc output from various prints is saved 107 */ 108 PETSC_INTERN FILE *petsc_history; 109 FILE *petsc_history = NULL; 110 111 PetscErrorCode PetscOpenHistoryFile(const char filename[],FILE **fd) 112 { 113 PetscErrorCode ierr; 114 PetscMPIInt rank,size; 115 char pfile[PETSC_MAX_PATH_LEN],pname[PETSC_MAX_PATH_LEN],fname[PETSC_MAX_PATH_LEN],date[64]; 116 char version[256]; 117 118 PetscFunctionBegin; 119 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); 120 if (!rank) { 121 char arch[10]; 122 int err; 123 124 ierr = PetscGetArchType(arch,10);CHKERRQ(ierr); 125 ierr = PetscGetDate(date,64);CHKERRQ(ierr); 126 ierr = PetscGetVersion(version,256);CHKERRQ(ierr); 127 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); 128 if (filename) { 129 ierr = PetscFixFilename(filename,fname);CHKERRQ(ierr); 130 } else { 131 ierr = PetscGetHomeDirectory(pfile,240);CHKERRQ(ierr); 132 ierr = PetscStrcat(pfile,"/.petschistory");CHKERRQ(ierr); 133 ierr = PetscFixFilename(pfile,fname);CHKERRQ(ierr); 134 } 135 136 *fd = fopen(fname,"a"); 137 if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file: %s",fname); 138 139 ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"----------------------------------------\n");CHKERRQ(ierr); 140 ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"%s %s\n",version,date);CHKERRQ(ierr); 141 ierr = PetscGetProgramName(pname,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 142 ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"%s on a %s, %d proc. with options:\n",pname,arch,size);CHKERRQ(ierr); 143 ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"----------------------------------------\n");CHKERRQ(ierr); 144 145 err = fflush(*fd); 146 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 147 } 148 PetscFunctionReturn(0); 149 } 150 151 PETSC_INTERN PetscErrorCode PetscCloseHistoryFile(FILE **fd) 152 { 153 PetscErrorCode ierr; 154 PetscMPIInt rank; 155 char date[64]; 156 int err; 157 158 PetscFunctionBegin; 159 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); 160 if (!rank) { 161 ierr = PetscGetDate(date,64);CHKERRQ(ierr); 162 ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"----------------------------------------\n");CHKERRQ(ierr); 163 ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"Finished at %s\n",date);CHKERRQ(ierr); 164 ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"----------------------------------------\n");CHKERRQ(ierr); 165 err = fflush(*fd); 166 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 167 err = fclose(*fd); 168 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file"); 169 } 170 PetscFunctionReturn(0); 171 } 172 173 /* ------------------------------------------------------------------------------*/ 174 175 /* 176 This is ugly and probably belongs somewhere else, but I want to 177 be able to put a true MPI abort error handler with command line args. 178 179 This is so MPI errors in the debugger will leave all the stack 180 frames. The default MP_Abort() cleans up and exits thus providing no useful information 181 in the debugger hence we call abort() instead of MPI_Abort(). 182 */ 183 184 void Petsc_MPI_AbortOnError(MPI_Comm *comm,PetscMPIInt *flag,...) 185 { 186 PetscFunctionBegin; 187 (*PetscErrorPrintf)("MPI error %d\n",*flag); 188 abort(); 189 } 190 191 void Petsc_MPI_DebuggerOnError(MPI_Comm *comm,PetscMPIInt *flag,...) 192 { 193 PetscErrorCode ierr; 194 195 PetscFunctionBegin; 196 (*PetscErrorPrintf)("MPI error %d\n",*flag); 197 ierr = PetscAttachDebugger(); 198 if (ierr) PETSCABORT(*comm,*flag); /* hopeless so get out */ 199 } 200 201 #if defined(PETSC_HAVE_CUDA) 202 /*@C 203 PetscCUDAInitialize - Initializes the CUDA device and cuBLAS on the device 204 205 Logically collective 206 207 Input Parameter: 208 comm - the MPI communicator that will utilize the CUDA devices 209 210 Options Database: 211 + -cuda_initialize <yes,no> - Default no. Do the initialization in PetscInitialize(). If -cuda_initialize no is used then the default initialization is done automatically 212 when the first CUDA call is made unless you call PetscCUDAInitialize() before any CUDA operations are performed 213 . -cuda_view - view information about the CUDA devices 214 . -cuda_synchronize - wait at the end of asynchronize CUDA calls so that their time gets credited to the current event; default with -log_view 215 . -cuda_set_device <gpu> - integer number of the device 216 - -use_gpu_aware_mpi - Assume the MPI is GPU-aware when communicating data on GPU 217 218 Level: beginner 219 220 Notes: 221 Initializing cuBLAS takes about 1/2 second there it is done by default in PetscInitialize() before logging begins 222 223 @*/ 224 PetscErrorCode PetscCUDAInitialize(MPI_Comm comm) 225 { 226 PetscErrorCode ierr; 227 PetscInt deviceOpt = 0; 228 PetscBool cuda_view_flag = PETSC_FALSE,flg; 229 struct cudaDeviceProp prop; 230 int devCount,device,devicecnt; 231 cudaError_t err = cudaSuccess; 232 PetscMPIInt rank,size; 233 234 PetscFunctionBegin; 235 /* 236 If collecting logging information, by default, wait for GPU to complete its operations 237 before returning to the CPU in order to get accurate timings of each event 238 */ 239 ierr = PetscOptionsHasName(NULL,NULL,"-log_summary",&PetscCUDASynchronize);CHKERRQ(ierr); 240 if (!PetscCUDASynchronize) { 241 ierr = PetscOptionsHasName(NULL,NULL,"-log_view",&PetscCUDASynchronize);CHKERRQ(ierr); 242 } 243 244 ierr = PetscOptionsBegin(comm,NULL,"CUDA options","Sys");CHKERRQ(ierr); 245 ierr = PetscOptionsInt("-cuda_set_device","Set all MPI ranks to use the specified CUDA device",NULL,deviceOpt,&deviceOpt,&flg);CHKERRQ(ierr); 246 device = (int)deviceOpt; 247 ierr = PetscOptionsBool("-cuda_synchronize","Wait for the GPU to complete operations before returning to the CPU",NULL,PetscCUDASynchronize,&PetscCUDASynchronize,NULL);CHKERRQ(ierr); 248 ierr = PetscOptionsDeprecated("-cuda_show_devices","-cuda_view","3.12",NULL);CHKERRQ(ierr); 249 ierr = PetscOptionsName("-cuda_view","Display CUDA device information and assignments",NULL,&cuda_view_flag);CHKERRQ(ierr); 250 ierr = PetscOptionsEnd();CHKERRQ(ierr); 251 if (!PetscCUDAInitialized) { 252 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 253 254 if (size>1 && !flg) { 255 /* check to see if we force multiple ranks to hit the same GPU */ 256 /* we're not using the same GPU on multiple MPI threads. So try to allocated different GPUs to different processes */ 257 258 /* First get the device count */ 259 err = cudaGetDeviceCount(&devCount); 260 if (err != cudaSuccess) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"error in cudaGetDeviceCount %s",cudaGetErrorString(err)); 261 262 /* next determine the rank and then set the device via a mod */ 263 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 264 device = rank % devCount; 265 } 266 err = cudaSetDevice(device); 267 if (err != cudaSuccess) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"error in cudaSetDevice %s",cudaGetErrorString(err)); 268 269 /* set the device flags so that it can map host memory */ 270 err = cudaSetDeviceFlags(cudaDeviceMapHost); 271 if (err != cudaSuccess) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"error in cudaSetDeviceFlags %s",cudaGetErrorString(err)); 272 273 ierr = PetscCUBLASInitializeHandle();CHKERRQ(ierr); 274 ierr = PetscCUSOLVERDnInitializeHandle();CHKERRQ(ierr); 275 PetscCUDAInitialized = PETSC_TRUE; 276 } 277 if (cuda_view_flag) { 278 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 279 err = cudaGetDeviceCount(&devCount); 280 if (err != cudaSuccess) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"error in cudaGetDeviceCount %s",cudaGetErrorString(err)); 281 for (devicecnt = 0; devicecnt < devCount; ++devicecnt) { 282 err = cudaGetDeviceProperties(&prop,devicecnt); 283 if (err != cudaSuccess) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"error in cudaGetDeviceProperties %s",cudaGetErrorString(err)); 284 ierr = PetscPrintf(comm, "CUDA device %d: %s\n", devicecnt, prop.name);CHKERRQ(ierr); 285 } 286 ierr = PetscSynchronizedPrintf(comm,"[%d] Using CUDA device %d.\n",rank,device);CHKERRQ(ierr); 287 ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr); 288 } 289 PetscFunctionReturn(0); 290 } 291 #endif 292 293 /*@C 294 PetscEnd - Calls PetscFinalize() and then ends the program. This is useful if one 295 wishes a clean exit somewhere deep in the program. 296 297 Collective on PETSC_COMM_WORLD 298 299 Options Database Keys are the same as for PetscFinalize() 300 301 Level: advanced 302 303 Note: 304 See PetscInitialize() for more general runtime options. 305 306 .seealso: PetscInitialize(), PetscOptionsView(), PetscMallocDump(), PetscMPIDump(), PetscFinalize() 307 @*/ 308 PetscErrorCode PetscEnd(void) 309 { 310 PetscFunctionBegin; 311 PetscFinalize(); 312 exit(0); 313 return 0; 314 } 315 316 PetscBool PetscOptionsPublish = PETSC_FALSE; 317 PETSC_INTERN PetscErrorCode PetscSetUseHBWMalloc_Private(void); 318 PETSC_INTERN PetscBool petscsetmallocvisited; 319 static char emacsmachinename[256]; 320 321 PetscErrorCode (*PetscExternalVersionFunction)(MPI_Comm) = NULL; 322 PetscErrorCode (*PetscExternalHelpFunction)(MPI_Comm) = NULL; 323 324 /*@C 325 PetscSetHelpVersionFunctions - Sets functions that print help and version information 326 before the PETSc help and version information is printed. Must call BEFORE PetscInitialize(). 327 This routine enables a "higher-level" package that uses PETSc to print its messages first. 328 329 Input Parameter: 330 + help - the help function (may be NULL) 331 - version - the version function (may be NULL) 332 333 Level: developer 334 335 @*/ 336 PetscErrorCode PetscSetHelpVersionFunctions(PetscErrorCode (*help)(MPI_Comm),PetscErrorCode (*version)(MPI_Comm)) 337 { 338 PetscFunctionBegin; 339 PetscExternalHelpFunction = help; 340 PetscExternalVersionFunction = version; 341 PetscFunctionReturn(0); 342 } 343 344 #if defined(PETSC_USE_LOG) 345 PETSC_INTERN PetscBool PetscObjectsLog; 346 #endif 347 348 void PetscMPI_Comm_eh(MPI_Comm *comm, PetscMPIInt *err, ...) 349 { 350 if (PetscUnlikely(*err)) { 351 PetscMPIInt len; 352 char errstring[MPI_MAX_ERROR_STRING]; 353 354 MPI_Error_string(*err,errstring,&len); 355 PetscError(MPI_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,PETSC_MPI_ERROR_CODE,PETSC_ERROR_INITIAL,"Internal error in MPI: %s",errstring); 356 } 357 return; 358 } 359 360 PETSC_INTERN PetscErrorCode PetscOptionsCheckInitial_Private(void) 361 { 362 char string[64]; 363 MPI_Comm comm = PETSC_COMM_WORLD; 364 PetscBool flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,flg3 = PETSC_FALSE,flag; 365 PetscErrorCode ierr; 366 PetscReal si; 367 PetscInt intensity; 368 int i; 369 PetscMPIInt rank; 370 char version[256],helpoptions[256]; 371 #if defined(PETSC_USE_LOG) 372 char mname[PETSC_MAX_PATH_LEN]; 373 PetscViewerFormat format; 374 PetscBool flg4 = PETSC_FALSE; 375 #endif 376 #if defined(PETSC_HAVE_CUDA) 377 PetscBool initCUDA = PETSC_FALSE,mpi_gpu_awareness; 378 cudaError_t cerr; 379 int devCount = 0; 380 #endif 381 382 PetscFunctionBegin; 383 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 384 385 #if !defined(PETSC_HAVE_THREADSAFETY) 386 if (!(PETSC_RUNNING_ON_VALGRIND)) { 387 /* 388 Setup the memory management; support for tracing malloc() usage 389 */ 390 PetscBool mdebug = PETSC_FALSE, eachcall = PETSC_FALSE, initializenan = PETSC_FALSE, mlog = PETSC_FALSE; 391 392 if (PetscDefined(USE_DEBUG)) { 393 mdebug = PETSC_TRUE; 394 initializenan = PETSC_TRUE; 395 ierr = PetscOptionsHasName(NULL,NULL,"-malloc_test",&flg1);CHKERRQ(ierr); 396 } else { 397 /* don't warn about unused option */ 398 ierr = PetscOptionsHasName(NULL,NULL,"-malloc_test",&flg1);CHKERRQ(ierr); 399 flg1 = PETSC_FALSE; 400 } 401 ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_debug",&flg2,&flg3);CHKERRQ(ierr); 402 if (flg1 || flg2) { 403 mdebug = PETSC_TRUE; 404 eachcall = PETSC_TRUE; 405 initializenan = PETSC_TRUE; 406 } else if (flg3 && !flg2) { 407 mdebug = PETSC_FALSE; 408 eachcall = PETSC_FALSE; 409 initializenan = PETSC_FALSE; 410 } 411 412 ierr = PetscOptionsHasName(NULL,NULL,"-malloc_view",&mlog);CHKERRQ(ierr); 413 if (mlog) { 414 mdebug = PETSC_TRUE; 415 } 416 /* the next line is deprecated */ 417 ierr = PetscOptionsGetBool(NULL,NULL,"-malloc",&mdebug,NULL);CHKERRQ(ierr); 418 ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_dump",&mdebug,NULL);CHKERRQ(ierr); 419 ierr = PetscOptionsGetBool(NULL,NULL,"-log_view_memory",&mdebug,NULL);CHKERRQ(ierr); 420 if (mdebug) { 421 ierr = PetscMallocSetDebug(eachcall,initializenan);CHKERRQ(ierr); 422 } 423 if (mlog) { 424 PetscReal logthreshold = 0; 425 ierr = PetscOptionsGetReal(NULL,NULL,"-malloc_view_threshold",&logthreshold,NULL);CHKERRQ(ierr); 426 ierr = PetscMallocViewSet(logthreshold);CHKERRQ(ierr); 427 } 428 #if defined(PETSC_USE_LOG) 429 ierr = PetscOptionsGetBool(NULL,NULL,"-log_view_memory",&PetscLogMemory,NULL);CHKERRQ(ierr); 430 #endif 431 } 432 433 ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_coalesce",&flg1,&flg2);CHKERRQ(ierr); 434 if (flg2) {ierr = PetscMallocSetCoalesce(flg1);CHKERRQ(ierr);} 435 flg1 = PETSC_FALSE; 436 ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_hbw",&flg1,NULL);CHKERRQ(ierr); 437 /* ignore this option if malloc is already set */ 438 if (flg1 && !petscsetmallocvisited) {ierr = PetscSetUseHBWMalloc_Private();CHKERRQ(ierr);} 439 440 flg1 = PETSC_FALSE; 441 ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_info",&flg1,NULL);CHKERRQ(ierr); 442 if (!flg1) { 443 flg1 = PETSC_FALSE; 444 ierr = PetscOptionsGetBool(NULL,NULL,"-memory_view",&flg1,NULL);CHKERRQ(ierr); 445 } 446 if (flg1) { 447 ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr); 448 } 449 #endif 450 451 #if defined(PETSC_USE_LOG) 452 ierr = PetscOptionsHasName(NULL,NULL,"-objects_dump",&PetscObjectsLog);CHKERRQ(ierr); 453 #endif 454 455 /* 456 Set the display variable for graphics 457 */ 458 ierr = PetscSetDisplay();CHKERRQ(ierr); 459 460 /* 461 Print the PETSc version information 462 */ 463 ierr = PetscOptionsHasName(NULL,NULL,"-v",&flg1);CHKERRQ(ierr); 464 ierr = PetscOptionsHasName(NULL,NULL,"-version",&flg2);CHKERRQ(ierr); 465 ierr = PetscOptionsHasHelp(NULL,&flg3);CHKERRQ(ierr); 466 if (flg1 || flg2 || flg3) { 467 468 /* 469 Print "higher-level" package version message 470 */ 471 if (PetscExternalVersionFunction) { 472 ierr = (*PetscExternalVersionFunction)(comm);CHKERRQ(ierr); 473 } 474 475 ierr = PetscGetVersion(version,256);CHKERRQ(ierr); 476 ierr = (*PetscHelpPrintf)(comm,"%s\n",version);CHKERRQ(ierr); 477 ierr = (*PetscHelpPrintf)(comm,"%s",PETSC_AUTHOR_INFO);CHKERRQ(ierr); 478 ierr = (*PetscHelpPrintf)(comm,"See docs/changes/index.html for recent updates.\n");CHKERRQ(ierr); 479 ierr = (*PetscHelpPrintf)(comm,"See docs/faq.html for problems.\n");CHKERRQ(ierr); 480 ierr = (*PetscHelpPrintf)(comm,"See docs/manualpages/index.html for help. \n");CHKERRQ(ierr); 481 ierr = (*PetscHelpPrintf)(comm,"Libraries linked from %s\n",PETSC_LIB_DIR);CHKERRQ(ierr); 482 ierr = (*PetscHelpPrintf)(comm,"----------------------------------------\n");CHKERRQ(ierr); 483 } 484 485 /* 486 Print "higher-level" package help message 487 */ 488 if (flg3) { 489 if (PetscExternalHelpFunction) { 490 ierr = (*PetscExternalHelpFunction)(comm);CHKERRQ(ierr); 491 } 492 } 493 494 ierr = PetscOptionsGetString(NULL,NULL,"-help",helpoptions,sizeof(helpoptions),&flg1);CHKERRQ(ierr); 495 if (flg1) { 496 ierr = PetscStrcmp(helpoptions,"intro",&flg2);CHKERRQ(ierr); 497 if (flg2) { 498 ierr = PetscOptionsDestroyDefault();CHKERRQ(ierr); 499 ierr = PetscFreeMPIResources();CHKERRQ(ierr); 500 ierr = MPI_Finalize();CHKERRQ(ierr); 501 exit(0); 502 } 503 } 504 505 /* 506 Setup the error handling 507 */ 508 flg1 = PETSC_FALSE; 509 ierr = PetscOptionsGetBool(NULL,NULL,"-on_error_abort",&flg1,NULL);CHKERRQ(ierr); 510 if (flg1) { 511 ierr = MPI_Comm_set_errhandler(comm,MPI_ERRORS_ARE_FATAL);CHKERRQ(ierr); 512 ierr = PetscPushErrorHandler(PetscAbortErrorHandler,NULL);CHKERRQ(ierr); 513 } 514 flg1 = PETSC_FALSE; 515 ierr = PetscOptionsGetBool(NULL,NULL,"-on_error_mpiabort",&flg1,NULL);CHKERRQ(ierr); 516 if (flg1) { ierr = PetscPushErrorHandler(PetscMPIAbortErrorHandler,NULL);CHKERRQ(ierr);} 517 flg1 = PETSC_FALSE; 518 ierr = PetscOptionsGetBool(NULL,NULL,"-mpi_return_on_error",&flg1,NULL);CHKERRQ(ierr); 519 if (flg1) { 520 ierr = MPI_Comm_set_errhandler(comm,MPI_ERRORS_RETURN);CHKERRQ(ierr); 521 } 522 /* experimental */ 523 flg1 = PETSC_FALSE; 524 ierr = PetscOptionsGetBool(NULL,NULL,"-mpi_return_error_string",&flg1,NULL);CHKERRQ(ierr); 525 if (flg1) { 526 MPI_Errhandler eh; 527 528 ierr = MPI_Comm_create_errhandler(PetscMPI_Comm_eh,&eh);CHKERRQ(ierr); 529 ierr = MPI_Comm_set_errhandler(comm,eh);CHKERRQ(ierr); 530 ierr = MPI_Errhandler_free(&eh);CHKERRQ(ierr); 531 } 532 flg1 = PETSC_FALSE; 533 ierr = PetscOptionsGetBool(NULL,NULL,"-no_signal_handler",&flg1,NULL);CHKERRQ(ierr); 534 if (!flg1) {ierr = PetscPushSignalHandler(PetscSignalHandlerDefault,(void*)0);CHKERRQ(ierr);} 535 flg1 = PETSC_FALSE; 536 ierr = PetscOptionsGetBool(NULL,NULL,"-fp_trap",&flg1,&flag);CHKERRQ(ierr); 537 if (flag) {ierr = PetscSetFPTrap((PetscFPTrap)flg1);CHKERRQ(ierr);} 538 ierr = PetscOptionsGetInt(NULL,NULL,"-check_pointer_intensity",&intensity,&flag);CHKERRQ(ierr); 539 if (flag) {ierr = PetscCheckPointerSetIntensity(intensity);CHKERRQ(ierr);} 540 541 /* 542 Setup debugger information 543 */ 544 ierr = PetscSetDefaultDebugger();CHKERRQ(ierr); 545 ierr = PetscOptionsGetString(NULL,NULL,"-on_error_attach_debugger",string,64,&flg1);CHKERRQ(ierr); 546 if (flg1) { 547 MPI_Errhandler err_handler; 548 549 ierr = PetscSetDebuggerFromString(string);CHKERRQ(ierr); 550 ierr = MPI_Comm_create_errhandler(Petsc_MPI_DebuggerOnError,&err_handler);CHKERRQ(ierr); 551 ierr = MPI_Comm_set_errhandler(comm,err_handler);CHKERRQ(ierr); 552 ierr = PetscPushErrorHandler(PetscAttachDebuggerErrorHandler,NULL);CHKERRQ(ierr); 553 } 554 ierr = PetscOptionsGetString(NULL,NULL,"-debug_terminal",string,64,&flg1);CHKERRQ(ierr); 555 if (flg1) { ierr = PetscSetDebugTerminal(string);CHKERRQ(ierr); } 556 ierr = PetscOptionsGetString(NULL,NULL,"-start_in_debugger",string,64,&flg1);CHKERRQ(ierr); 557 ierr = PetscOptionsGetString(NULL,NULL,"-stop_for_debugger",string,64,&flg2);CHKERRQ(ierr); 558 if (flg1 || flg2) { 559 PetscMPIInt size; 560 PetscInt lsize,*nodes; 561 MPI_Errhandler err_handler; 562 /* 563 we have to make sure that all processors have opened 564 connections to all other processors, otherwise once the 565 debugger has stated it is likely to receive a SIGUSR1 566 and kill the program. 567 */ 568 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 569 if (size > 2) { 570 PetscMPIInt dummy = 0; 571 MPI_Status status; 572 for (i=0; i<size; i++) { 573 if (rank != i) { 574 ierr = MPI_Send(&dummy,1,MPI_INT,i,109,comm);CHKERRQ(ierr); 575 } 576 } 577 for (i=0; i<size; i++) { 578 if (rank != i) { 579 ierr = MPI_Recv(&dummy,1,MPI_INT,i,109,comm,&status);CHKERRQ(ierr); 580 } 581 } 582 } 583 /* check if this processor node should be in debugger */ 584 ierr = PetscMalloc1(size,&nodes);CHKERRQ(ierr); 585 lsize = size; 586 ierr = PetscOptionsGetIntArray(NULL,NULL,"-debugger_nodes",nodes,&lsize,&flag);CHKERRQ(ierr); 587 if (flag) { 588 for (i=0; i<lsize; i++) { 589 if (nodes[i] == rank) { flag = PETSC_FALSE; break; } 590 } 591 } 592 if (!flag) { 593 ierr = PetscSetDebuggerFromString(string);CHKERRQ(ierr); 594 ierr = PetscPushErrorHandler(PetscAbortErrorHandler,NULL);CHKERRQ(ierr); 595 if (flg1) { 596 ierr = PetscAttachDebugger();CHKERRQ(ierr); 597 } else { 598 ierr = PetscStopForDebugger();CHKERRQ(ierr); 599 } 600 ierr = MPI_Comm_create_errhandler(Petsc_MPI_AbortOnError,&err_handler);CHKERRQ(ierr); 601 ierr = MPI_Comm_set_errhandler(comm,err_handler);CHKERRQ(ierr); 602 } 603 ierr = PetscFree(nodes);CHKERRQ(ierr); 604 } 605 606 ierr = PetscOptionsGetString(NULL,NULL,"-on_error_emacs",emacsmachinename,128,&flg1);CHKERRQ(ierr); 607 if (flg1 && !rank) {ierr = PetscPushErrorHandler(PetscEmacsClientErrorHandler,emacsmachinename);CHKERRQ(ierr);} 608 609 /* 610 Setup profiling and logging 611 */ 612 #if defined(PETSC_USE_INFO) 613 { 614 ierr = PetscInfoSetFromOptions(NULL);CHKERRQ(ierr); 615 } 616 #endif 617 #if defined(PETSC_USE_LOG) 618 mname[0] = 0; 619 ierr = PetscOptionsGetString(NULL,NULL,"-history",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr); 620 if (flg1) { 621 if (mname[0]) { 622 ierr = PetscOpenHistoryFile(mname,&petsc_history);CHKERRQ(ierr); 623 } else { 624 ierr = PetscOpenHistoryFile(NULL,&petsc_history);CHKERRQ(ierr); 625 } 626 } 627 628 ierr = PetscOptionsGetBool(NULL,NULL,"-log_sync",&PetscLogSyncOn,NULL);CHKERRQ(ierr); 629 630 #if defined(PETSC_HAVE_MPE) 631 flg1 = PETSC_FALSE; 632 ierr = PetscOptionsHasName(NULL,NULL,"-log_mpe",&flg1);CHKERRQ(ierr); 633 if (flg1) {ierr = PetscLogMPEBegin();CHKERRQ(ierr);} 634 #endif 635 flg1 = PETSC_FALSE; 636 flg3 = PETSC_FALSE; 637 ierr = PetscOptionsGetBool(NULL,NULL,"-log_all",&flg1,NULL);CHKERRQ(ierr); 638 ierr = PetscOptionsHasName(NULL,NULL,"-log_summary",&flg3);CHKERRQ(ierr); 639 if (flg1) { ierr = PetscLogAllBegin();CHKERRQ(ierr); } 640 else if (flg3) { ierr = PetscLogDefaultBegin();CHKERRQ(ierr);} 641 642 ierr = PetscOptionsGetString(NULL,NULL,"-log_trace",mname,250,&flg1);CHKERRQ(ierr); 643 if (flg1) { 644 char name[PETSC_MAX_PATH_LEN],fname[PETSC_MAX_PATH_LEN]; 645 FILE *file; 646 if (mname[0]) { 647 PetscSNPrintf(name,PETSC_MAX_PATH_LEN,"%s.%d",mname,rank); 648 ierr = PetscFixFilename(name,fname);CHKERRQ(ierr); 649 file = fopen(fname,"w"); 650 if (!file) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open trace file: %s",fname); 651 } else file = PETSC_STDOUT; 652 ierr = PetscLogTraceBegin(file);CHKERRQ(ierr); 653 } 654 655 ierr = PetscOptionsGetViewer(comm,NULL,NULL,"-log_view",NULL,&format,&flg4);CHKERRQ(ierr); 656 if (flg4) { 657 if (format == PETSC_VIEWER_ASCII_XML) { 658 ierr = PetscLogNestedBegin();CHKERRQ(ierr); 659 } else { 660 ierr = PetscLogDefaultBegin();CHKERRQ(ierr); 661 } 662 } 663 if (flg4 && format == PETSC_VIEWER_ASCII_XML) { 664 PetscReal threshold = PetscRealConstant(0.01); 665 ierr = PetscOptionsGetReal(NULL,NULL,"-log_threshold",&threshold,&flg1);CHKERRQ(ierr); 666 if (flg1) {ierr = PetscLogSetThreshold((PetscLogDouble)threshold,NULL);CHKERRQ(ierr);} 667 } 668 #endif 669 670 ierr = PetscOptionsGetBool(NULL,NULL,"-saws_options",&PetscOptionsPublish,NULL);CHKERRQ(ierr); 671 672 #if defined(PETSC_HAVE_CUDA) 673 ierr = PetscOptionsBegin(comm,NULL,"CUDA initialize","Sys");CHKERRQ(ierr); 674 ierr = PetscOptionsBool("-cuda_initialize","Initialize the CUDA devices and cuBLAS during PetscInitialize()",NULL,initCUDA,&initCUDA,NULL);CHKERRQ(ierr); 675 ierr = PetscOptionsBool("-use_gpu_aware_mpi","Use GPU-aware MPI",NULL,use_gpu_aware_mpi,&use_gpu_aware_mpi,NULL);CHKERRQ(ierr); 676 ierr = PetscOptionsEnd();CHKERRQ(ierr); 677 if (initCUDA) {ierr = PetscCUDAInitialize(PETSC_COMM_WORLD);CHKERRQ(ierr);} 678 cerr = cudaGetDeviceCount(&devCount);{if (cerr != cudaErrorNoDevice) CHKERRCUDA(cerr);} /* Catch other errors */ 679 if (cerr == cudaErrorNoDevice) devCount = 0; /* CUDA does not say what devCount is under this error */ 680 if (devCount > 0 && use_gpu_aware_mpi) { /* Only do the MPI GPU awareness check when there are GPU(s) */ 681 #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) && defined(MPIX_CUDA_AWARE_SUPPORT) && MPIX_CUDA_AWARE_SUPPORT 682 /* Trust OpenMPI's compile time cuda query interface */ 683 mpi_gpu_awareness = PETSC_TRUE; 684 #else 685 /* For other MPI implementations without cuda query API, we do a GPU MPI call to see if it segfaults. 686 Note that Spectrum MPI sets OMPI_MAJOR_VERSION and is CUDA-aware, but does not have MPIX_CUDA_AWARE_SUPPORT. 687 */ 688 mpi_gpu_awareness = PetscCheckMpiGpuAwareness(); 689 #endif 690 if (!mpi_gpu_awareness) { 691 (*PetscErrorPrintf)("PETSc is configured with GPU support, but your MPI is not GPU-aware. For better performance, please use a GPU-aware MPI.\n"); 692 (*PetscErrorPrintf)("For IBM Spectrum MPI on OLCF Summit, you may need jsrun --smpiargs=-gpu.\n"); 693 (*PetscErrorPrintf)("For OpenMPI, you need to configure it --with-cuda (https://www.open-mpi.org/faq/?category=buildcuda)\n"); 694 (*PetscErrorPrintf)("For MVAPICH2-GDR, you need to set MV2_USE_CUDA=1 (http://mvapich.cse.ohio-state.edu/userguide/gdr/)\n"); 695 (*PetscErrorPrintf)("For Cray-MPICH, you need to set MPICH_RDMA_ENABLED_CUDA=1 (https://www.olcf.ornl.gov/tutorials/gpudirect-mpich-enabled-cuda/)\n"); 696 (*PetscErrorPrintf)("If you do not care, use option -use_gpu_aware_mpi 0, then PETSc will copy data from GPU to CPU for communication.\n"); 697 PETSCABORT(PETSC_COMM_WORLD,PETSC_ERR_LIB); 698 } 699 } 700 #endif 701 702 /* 703 Print basic help message 704 */ 705 ierr = PetscOptionsHasHelp(NULL,&flg1);CHKERRQ(ierr); 706 if (flg1) { 707 ierr = (*PetscHelpPrintf)(comm,"Options for all PETSc programs:\n");CHKERRQ(ierr); 708 ierr = (*PetscHelpPrintf)(comm," -help: prints help method for each option\n");CHKERRQ(ierr); 709 ierr = (*PetscHelpPrintf)(comm," -on_error_abort: cause an abort when an error is detected. Useful \n ");CHKERRQ(ierr); 710 ierr = (*PetscHelpPrintf)(comm," only when run in the debugger\n");CHKERRQ(ierr); 711 ierr = (*PetscHelpPrintf)(comm," -on_error_attach_debugger [gdb,dbx,xxgdb,ups,noxterm]\n");CHKERRQ(ierr); 712 ierr = (*PetscHelpPrintf)(comm," start the debugger in new xterm\n");CHKERRQ(ierr); 713 ierr = (*PetscHelpPrintf)(comm," unless noxterm is given\n");CHKERRQ(ierr); 714 ierr = (*PetscHelpPrintf)(comm," -start_in_debugger [gdb,dbx,xxgdb,ups,noxterm]\n");CHKERRQ(ierr); 715 ierr = (*PetscHelpPrintf)(comm," start all processes in the debugger\n");CHKERRQ(ierr); 716 ierr = (*PetscHelpPrintf)(comm," -on_error_emacs <machinename>\n");CHKERRQ(ierr); 717 ierr = (*PetscHelpPrintf)(comm," emacs jumps to error file\n");CHKERRQ(ierr); 718 ierr = (*PetscHelpPrintf)(comm," -debugger_nodes [n1,n2,..] Nodes to start in debugger\n");CHKERRQ(ierr); 719 ierr = (*PetscHelpPrintf)(comm," -debugger_pause [m] : delay (in seconds) to attach debugger\n");CHKERRQ(ierr); 720 ierr = (*PetscHelpPrintf)(comm," -stop_for_debugger : prints message on how to attach debugger manually\n");CHKERRQ(ierr); 721 ierr = (*PetscHelpPrintf)(comm," waits the delay for you to attach\n");CHKERRQ(ierr); 722 ierr = (*PetscHelpPrintf)(comm," -display display: Location where X window graphics and debuggers are displayed\n");CHKERRQ(ierr); 723 ierr = (*PetscHelpPrintf)(comm," -no_signal_handler: do not trap error signals\n");CHKERRQ(ierr); 724 ierr = (*PetscHelpPrintf)(comm," -mpi_return_on_error: MPI returns error code, rather than abort on internal error\n");CHKERRQ(ierr); 725 ierr = (*PetscHelpPrintf)(comm," -fp_trap: stop on floating point exceptions\n");CHKERRQ(ierr); 726 ierr = (*PetscHelpPrintf)(comm," note on IBM RS6000 this slows run greatly\n");CHKERRQ(ierr); 727 ierr = (*PetscHelpPrintf)(comm," -malloc_dump <optional filename>: dump list of unfreed memory at conclusion\n");CHKERRQ(ierr); 728 ierr = (*PetscHelpPrintf)(comm," -malloc: use PETSc error checking malloc (deprecated, use -malloc_debug)\n");CHKERRQ(ierr); 729 ierr = (*PetscHelpPrintf)(comm," -malloc no: don't use PETSc error checking malloc (deprecated, use -malloc_debug no)\n");CHKERRQ(ierr); 730 ierr = (*PetscHelpPrintf)(comm," -malloc_info: prints total memory usage\n");CHKERRQ(ierr); 731 ierr = (*PetscHelpPrintf)(comm," -malloc_view <optional filename>: keeps log of all memory allocations, displays in PetscFinalize()\n");CHKERRQ(ierr); 732 ierr = (*PetscHelpPrintf)(comm," -malloc_debug <true or false>: enables or disables extended checking for memory corruption\n");CHKERRQ(ierr); 733 ierr = (*PetscHelpPrintf)(comm," -options_view: dump list of options inputted\n");CHKERRQ(ierr); 734 ierr = (*PetscHelpPrintf)(comm," -options_left: dump list of unused options\n");CHKERRQ(ierr); 735 ierr = (*PetscHelpPrintf)(comm," -options_left no: don't dump list of unused options\n");CHKERRQ(ierr); 736 ierr = (*PetscHelpPrintf)(comm," -tmp tmpdir: alternative /tmp directory\n");CHKERRQ(ierr); 737 ierr = (*PetscHelpPrintf)(comm," -shared_tmp: tmp directory is shared by all processors\n");CHKERRQ(ierr); 738 ierr = (*PetscHelpPrintf)(comm," -not_shared_tmp: each processor has separate tmp directory\n");CHKERRQ(ierr); 739 ierr = (*PetscHelpPrintf)(comm," -memory_view: print memory usage at end of run\n");CHKERRQ(ierr); 740 #if defined(PETSC_USE_LOG) 741 ierr = (*PetscHelpPrintf)(comm," -get_total_flops: total flops over all processors\n");CHKERRQ(ierr); 742 ierr = (*PetscHelpPrintf)(comm," -log_view [:filename:[format]]: logging objects and events\n");CHKERRQ(ierr); 743 ierr = (*PetscHelpPrintf)(comm," -log_trace [filename]: prints trace of all PETSc calls\n");CHKERRQ(ierr); 744 ierr = (*PetscHelpPrintf)(comm," -log_exclude <list,of,classnames>: exclude given classes from logging\n");CHKERRQ(ierr); 745 #if defined(PETSC_HAVE_MPE) 746 ierr = (*PetscHelpPrintf)(comm," -log_mpe: Also create logfile viewable through Jumpshot\n");CHKERRQ(ierr); 747 #endif 748 #endif 749 #if defined(PETSC_USE_INFO) 750 ierr = (*PetscHelpPrintf)(comm," -info [filename][:[~]<list,of,classnames>[:[~]self]]: print verbose information\n");CHKERRQ(ierr); 751 #endif 752 ierr = (*PetscHelpPrintf)(comm," -v: prints PETSc version number and release date\n");CHKERRQ(ierr); 753 ierr = (*PetscHelpPrintf)(comm," -options_file <file>: reads options from file\n");CHKERRQ(ierr); 754 ierr = (*PetscHelpPrintf)(comm," -petsc_sleep n: sleeps n seconds before running program\n");CHKERRQ(ierr); 755 } 756 757 #if defined(PETSC_HAVE_POPEN) 758 { 759 char machine[128]; 760 ierr = PetscOptionsGetString(NULL,NULL,"-popen_machine",machine,128,&flg1);CHKERRQ(ierr); 761 if (flg1) { 762 ierr = PetscPOpenSetMachine(machine);CHKERRQ(ierr); 763 } 764 } 765 #endif 766 767 ierr = PetscOptionsGetReal(NULL,NULL,"-petsc_sleep",&si,&flg1);CHKERRQ(ierr); 768 if (flg1) { 769 ierr = PetscSleep(si);CHKERRQ(ierr); 770 } 771 772 #if defined(PETSC_HAVE_VIENNACL) 773 ierr = PetscOptionsHasName(NULL,NULL,"-log_summary",&flg3);CHKERRQ(ierr); 774 if (!flg3) { 775 ierr = PetscOptionsHasName(NULL,NULL,"-log_view",&flg3);CHKERRQ(ierr); 776 } 777 ierr = PetscOptionsGetBool(NULL,NULL,"-viennacl_synchronize",&flg3,NULL);CHKERRQ(ierr); 778 PetscViennaCLSynchronize = flg3; 779 ierr = PetscViennaCLInit();CHKERRQ(ierr); 780 #endif 781 782 /* 783 Creates the logging data structures; this is enabled even if logging is not turned on 784 This is the last thing we do before returning to the user code to prevent having the 785 logging numbers contaminated by any startup time associated with MPI and the GPUs 786 */ 787 #if defined(PETSC_USE_LOG) 788 ierr = PetscLogInitialize();CHKERRQ(ierr); 789 #endif 790 791 PetscFunctionReturn(0); 792 } 793