void mpi_attr_delete_f(MPI_Fint *comm, MPI_Fint *keyval, MPI_Fint *ierr) { MPI_Comm c_comm; c_comm = MPI_Comm_f2c(*comm); *ierr = OMPI_INT_2_FINT(MPI_Attr_delete(c_comm, OMPI_FINT_2_INT(*keyval))); }
void ompi_attr_delete_f(MPI_Fint *comm, MPI_Fint *keyval, MPI_Fint *ierr) { int c_ierr; MPI_Comm c_comm; c_comm = MPI_Comm_f2c(*comm); c_ierr = MPI_Attr_delete(c_comm, OMPI_FINT_2_INT(*keyval)); if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); }
int test_communicators( void ) { MPI_Comm dup_comm_world, d2; ptrdiff_t world_rank; int world_size, key_1; int err; MPI_Aint value; int rank; MPI_Comm_rank( MPI_COMM_WORLD, &rank ); world_rank=rank; MPI_Comm_size( MPI_COMM_WORLD, &world_size ); if (world_rank == 0) { printf( "*** Attribute copy/delete return codes ***\n" ); } MPI_Comm_dup( MPI_COMM_WORLD, &dup_comm_world ); MPI_Barrier( dup_comm_world ); MPI_Errhandler_set( dup_comm_world, MPI_ERRORS_RETURN ); value = - 11; if ((err=MPI_Keyval_create( copybomb_fn, deletebomb_fn, &key_1, &value ))) abort_msg( "Keyval_create", err ); err = MPI_Attr_put( dup_comm_world, key_1, (void *)world_rank ); if (err) { printf( "Error with first put\n" ); } err = MPI_Attr_put( dup_comm_world, key_1, (void *)(2*world_rank) ); if (err == MPI_SUCCESS) { printf( "delete function return code was MPI_SUCCESS in put\n" ); } /* Because the attribute delete function should fail, the attribute should *not be removed* */ err = MPI_Attr_delete( dup_comm_world, key_1 ); if (err == MPI_SUCCESS) { printf( "delete function return code was MPI_SUCCESS in delete\n" ); } err = MPI_Comm_dup( dup_comm_world, &d2 ); if (err == MPI_SUCCESS) { printf( "copy function return code was MPI_SUCCESS in dup\n" ); } if (err && d2 != MPI_COMM_NULL) { printf( "dup did not return MPI_COMM_NULL on error\n" ); } delete_flag = 1; MPI_Comm_free( &dup_comm_world ); return 0; }
PetscErrorCode PetscViewer_SAWS_Destroy(MPI_Comm comm) { PetscErrorCode ierr; PetscMPIInt flag; PetscViewer viewer; PetscFunctionBegin; if (Petsc_Viewer_SAWs_keyval == MPI_KEYVAL_INVALID) PetscFunctionReturn(0); ierr = MPI_Attr_get(comm,Petsc_Viewer_SAWs_keyval,(void**)&viewer,&flag);CHKERRQ(ierr); if (flag) { ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); ierr = MPI_Attr_delete(comm,Petsc_Viewer_SAWs_keyval);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* This is invoked on the outer comm as a result of either PetscCommDestroy() (via MPI_Attr_delete) or when the user calls MPI_Comm_free(). This is the only entry point for breaking the links between inner and outer comms. This is called by MPI, not by users. This is called when MPI_Comm_free() is called on the communicator. Note: this is declared extern "C" because it is passed to MPI_Keyval_create() */ PETSC_EXTERN PetscMPIInt MPIAPI Petsc_DelComm_Outer(MPI_Comm comm,PetscMPIInt keyval,void *attr_val,void *extra_state) { PetscErrorCode ierr; PetscMPIInt flg; union {MPI_Comm comm; void *ptr;} icomm,ocomm; PetscFunctionBegin; if (keyval != Petsc_InnerComm_keyval) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Unexpected keyval"); icomm.ptr = attr_val; ierr = MPI_Attr_get(icomm.comm,Petsc_OuterComm_keyval,&ocomm,&flg);CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm does not have expected reference to outer comm"); if (ocomm.comm != comm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm has reference to non-matching outer comm"); ierr = MPI_Attr_delete(icomm.comm,Petsc_OuterComm_keyval);CHKERRQ(ierr); /* Calls Petsc_DelComm_Inner */ ierr = PetscInfo1(0,"User MPI_Comm %ld is being freed after removing reference from inner PETSc comm to this outer comm\n",(long)comm);if (ierr) PetscFunctionReturn((PetscMPIInt)ierr); PetscFunctionReturn(MPI_SUCCESS); }
/*@ PetscSequentialPhaseEnd - Ends a sequential section of code. Collective on MPI_Comm Input Parameters: + comm - Communicator to sequentialize. - ng - Number in processor group. This many processes are allowed to execute at the same time (usually 1) Level: intermediate Notes: See PetscSequentialPhaseBegin() for more details. .seealso: PetscSequentialPhaseBegin() Concepts: sequential stage @*/ PetscErrorCode PetscSequentialPhaseEnd(MPI_Comm comm,int ng) { PetscErrorCode ierr; PetscMPIInt size,flag; MPI_Comm local_comm,*addr_local_comm; PetscFunctionBegin; ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); if (size == 1) PetscFunctionReturn(0); ierr = MPI_Attr_get(comm,Petsc_Seq_keyval,(void **)&addr_local_comm,&flag);CHKERRQ(ierr); if (!flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Wrong MPI communicator; must pass in one used with PetscSequentialPhaseBegin()"); local_comm = *addr_local_comm; ierr = PetscSequentialPhaseEnd_Private(local_comm,ng);CHKERRQ(ierr); ierr = PetscFree(addr_local_comm);CHKERRQ(ierr); ierr = MPI_Comm_free(&local_comm);CHKERRQ(ierr); ierr = MPI_Attr_delete(comm,Petsc_Seq_keyval);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* This does not actually free anything, it simply marks when a reference count to an internal or external MPI_Comm reaches zero and the the external MPI_Comm drops its reference to the internal or external MPI_Comm This is called by MPI, not by users. This is called when MPI_Comm_free() is called on the communicator. Note: this is declared extern "C" because it is passed to MPI_Keyval_create() */ PETSC_EXTERN PetscMPIInt MPIAPI Petsc_DelComm(MPI_Comm comm,PetscMPIInt keyval,void *attr_val,void *extra_state) { PetscErrorCode ierr; PetscMPIInt flg; MPI_Comm icomm; void *ptr; PetscFunctionBegin; ierr = MPI_Attr_get(comm,Petsc_InnerComm_keyval,&ptr,&flg);CHKERRQ(ierr); if (flg) { /* Use PetscMemcpy() because casting from pointer to integer of different size is not allowed with some compilers */ ierr = PetscMemcpy(&icomm,&ptr,sizeof(MPI_Comm));CHKERRQ(ierr); ierr = MPI_Attr_get(icomm,Petsc_OuterComm_keyval,&ptr,&flg);CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm does not have expected reference to outer comm"); ierr = MPI_Attr_delete(icomm,Petsc_OuterComm_keyval);CHKERRQ(ierr); ierr = PetscInfo1(0,"User MPI_Comm m %ld is being freed, removing reference from inner PETSc comm to this outer comm\n",(long)comm);if (ierr) PetscFunctionReturn((PetscMPIInt)ierr); } else { ierr = PetscInfo1(0,"Removing reference to PETSc communicator imbedded in a user MPI_Comm m %ld\n",(long)comm);if (ierr) PetscFunctionReturn((PetscMPIInt)ierr); } PetscFunctionReturn(MPI_SUCCESS); }
/*@C PetscCommDestroy - Frees communicator. Use in conjunction with PetscCommDuplicate(). Collective on MPI_Comm Input Parameter: . comm - the communicator to free Level: developer Concepts: communicator^destroy .seealso: PetscCommDuplicate() @*/ PetscErrorCode PetscCommDestroy(MPI_Comm *comm) { PetscErrorCode ierr; PetscCommCounter *counter; PetscMPIInt flg; MPI_Comm icomm = *comm,ocomm; union {MPI_Comm comm; void *ptr;} ucomm; PetscFunctionBegin; if (*comm == MPI_COMM_NULL) PetscFunctionReturn(0); ierr = PetscSpinlockLock(&PetscCommSpinLock);CHKERRQ(ierr); ierr = MPI_Attr_get(icomm,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr); if (!flg) { /* not a PETSc comm, check if it has an inner comm */ ierr = MPI_Attr_get(icomm,Petsc_InnerComm_keyval,&ucomm,&flg);CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"MPI_Comm does not have tag/name counter nor does it have inner MPI_Comm"); icomm = ucomm.comm; ierr = MPI_Attr_get(icomm,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm does not have expected tag/name counter, problem with corrupted memory"); } counter->refcount--; if (!counter->refcount) { /* if MPI_Comm has outer comm then remove reference to inner MPI_Comm from outer MPI_Comm */ ierr = MPI_Attr_get(icomm,Petsc_OuterComm_keyval,&ucomm,&flg);CHKERRQ(ierr); if (flg) { ocomm = ucomm.comm; ierr = MPI_Attr_get(ocomm,Petsc_InnerComm_keyval,&ucomm,&flg);CHKERRQ(ierr); if (flg) { ierr = MPI_Attr_delete(ocomm,Petsc_InnerComm_keyval);CHKERRQ(ierr); } else SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Outer MPI_Comm %ld does not have expected reference to inner comm %d, problem with corrupted memory",(long int)ocomm,(long int)icomm); } ierr = PetscInfo1(0,"Deleting PETSc MPI_Comm %ld\n",(long)icomm);CHKERRQ(ierr); ierr = MPI_Comm_free(&icomm);CHKERRQ(ierr); } *comm = MPI_COMM_NULL; ierr = PetscSpinlockUnlock(&PetscCommSpinLock);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer) { PetscErrorCode ierr; PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data; PetscViewerLink *vlink; PetscBool flg; PetscFunctionBegin; if (vascii->sviewer) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"ASCII PetscViewer destroyed before restoring singleton or subcomm PetscViewer"); ierr = PetscViewerFileClose_ASCII(viewer);CHKERRQ(ierr); ierr = PetscFree(vascii);CHKERRQ(ierr); /* remove the viewer from the list in the MPI Communicator */ if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) { ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelViewer,&Petsc_Viewer_keyval,(void*)0);CHKERRQ(ierr); } ierr = MPI_Attr_get(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_keyval,(void**)&vlink,(PetscMPIInt*)&flg);CHKERRQ(ierr); if (flg) { if (vlink && vlink->viewer == viewer) { if (vlink->next) { ierr = MPI_Attr_put(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_keyval,vlink->next);CHKERRQ(ierr); } else { ierr = MPI_Attr_delete(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_keyval);CHKERRQ(ierr); } ierr = PetscFree(vlink);CHKERRQ(ierr); } else { while (vlink && vlink->next) { if (vlink->next->viewer == viewer) { PetscViewerLink *nv = vlink->next; vlink->next = vlink->next->next; ierr = PetscFree(nv);CHKERRQ(ierr); } vlink = vlink->next; } } } PetscFunctionReturn(0); }
int test_communicators(void) { MPI_Comm dup_comm_world, d2; int world_rank, world_size, key_1; int err, errs = 0; MPI_Aint value; MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); MPI_Comm_size(MPI_COMM_WORLD, &world_size); #ifdef DEBUG if (world_rank == 0) { printf("*** Attribute copy/delete return codes ***\n"); } #endif MPI_Comm_dup(MPI_COMM_WORLD, &dup_comm_world); MPI_Barrier(dup_comm_world); MPI_Errhandler_set(dup_comm_world, MPI_ERRORS_RETURN); value = -11; if ((err = MPI_Keyval_create(copybomb_fn, deletebomb_fn, &key_1, &value))) abort_msg("Keyval_create", err); err = MPI_Attr_put(dup_comm_world, key_1, (void *) (MPI_Aint) world_rank); if (err) { errs++; printf("Error with first put\n"); } err = MPI_Attr_put(dup_comm_world, key_1, (void *) (MPI_Aint) (2 * world_rank)); if (err == MPI_SUCCESS) { errs++; printf("delete function return code was MPI_SUCCESS in put\n"); } /* Because the attribute delete function should fail, the attribute * should *not be removed* */ err = MPI_Attr_delete(dup_comm_world, key_1); if (err == MPI_SUCCESS) { errs++; printf("delete function return code was MPI_SUCCESS in delete\n"); } err = MPI_Comm_dup(dup_comm_world, &d2); if (err == MPI_SUCCESS) { errs++; printf("copy function return code was MPI_SUCCESS in dup\n"); } #ifndef USE_STRICT_MPI /* Another interpretation is to leave d2 unchanged on error */ if (err && d2 != MPI_COMM_NULL) { errs++; printf("dup did not return MPI_COMM_NULL on error\n"); } #endif delete_flag = 1; MPI_Comm_free(&dup_comm_world); MPI_Keyval_free(&key_1); return errs; }
/*@C PetscFinalize - Checks for options to be called at the conclusion of the program. MPI_Finalize() is called only if the user had not called MPI_Init() before calling PetscInitialize(). Collective on PETSC_COMM_WORLD Options Database Keys: + -options_table - Calls PetscOptionsView() . -options_left - Prints unused options that remain in the database . -objects_dump [all] - Prints list of objects allocated by the user that have not been freed, the option all cause all outstanding objects to be listed . -mpidump - Calls PetscMPIDump() . -malloc_dump - Calls PetscMallocDump() . -malloc_info - Prints total memory usage - -malloc_log - Prints summary of memory usage Level: beginner Note: See PetscInitialize() for more general runtime options. .seealso: PetscInitialize(), PetscOptionsView(), PetscMallocDump(), PetscMPIDump(), PetscEnd() @*/ PetscErrorCode PetscFinalize(void) { PetscErrorCode ierr; PetscMPIInt rank; PetscInt nopt; PetscBool flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,flg3 = PETSC_FALSE; #if defined(PETSC_HAVE_AMS) PetscBool flg = PETSC_FALSE; #endif #if defined(PETSC_USE_LOG) char mname[PETSC_MAX_PATH_LEN]; #endif PetscFunctionBegin; if (!PetscInitializeCalled) { printf("PetscInitialize() must be called before PetscFinalize()\n"); PetscFunctionReturn(PETSC_ERR_ARG_WRONGSTATE); } ierr = PetscInfo(NULL,"PetscFinalize() called\n");CHKERRQ(ierr); #if defined(PETSC_SERIALIZE_FUNCTIONS) ierr = PetscFPTDestroy();CHKERRQ(ierr); #endif #if defined(PETSC_HAVE_AMS) ierr = PetscOptionsGetBool(NULL,"-options_gui",&flg,NULL);CHKERRQ(ierr); if (flg) { ierr = PetscOptionsAMSDestroy();CHKERRQ(ierr); } #endif #if defined(PETSC_HAVE_SERVER) flg1 = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,"-server",&flg1,NULL);CHKERRQ(ierr); if (flg1) { /* this is a crude hack, but better than nothing */ ierr = PetscPOpen(PETSC_COMM_WORLD,NULL,"pkill -9 petscwebserver","r",NULL);CHKERRQ(ierr); } #endif ierr = PetscHMPIFinalize();CHKERRQ(ierr); ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); ierr = PetscOptionsGetBool(NULL,"-malloc_info",&flg2,NULL);CHKERRQ(ierr); if (!flg2) { flg2 = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,"-memory_info",&flg2,NULL);CHKERRQ(ierr); } if (flg2) { ierr = PetscMemoryShowUsage(PETSC_VIEWER_STDOUT_WORLD,"Summary of Memory Usage in PETSc\n");CHKERRQ(ierr); } #if defined(PETSC_USE_LOG) flg1 = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,"-get_total_flops",&flg1,NULL);CHKERRQ(ierr); if (flg1) { PetscLogDouble flops = 0; ierr = MPI_Reduce(&petsc_TotalFlops,&flops,1,MPI_DOUBLE,MPI_SUM,0,PETSC_COMM_WORLD);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Total flops over all processors %g\n",flops);CHKERRQ(ierr); } #endif #if defined(PETSC_USE_LOG) #if defined(PETSC_HAVE_MPE) mname[0] = 0; ierr = PetscOptionsGetString(NULL,"-log_mpe",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr); if (flg1) { if (mname[0]) {ierr = PetscLogMPEDump(mname);CHKERRQ(ierr);} else {ierr = PetscLogMPEDump(0);CHKERRQ(ierr);} } #endif mname[0] = 0; ierr = PetscOptionsGetString(NULL,"-log_summary",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr); if (flg1) { PetscViewer viewer; if (mname[0]) { ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,mname,&viewer);CHKERRQ(ierr); ierr = PetscLogView(viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } else { viewer = PETSC_VIEWER_STDOUT_WORLD; ierr = PetscLogView(viewer);CHKERRQ(ierr); } } mname[0] = 0; ierr = PetscOptionsGetString(NULL,"-log_summary_python",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr); if (flg1) { PetscViewer viewer; if (mname[0]) { ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,mname,&viewer);CHKERRQ(ierr); ierr = PetscLogViewPython(viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } else { viewer = PETSC_VIEWER_STDOUT_WORLD; ierr = PetscLogViewPython(viewer);CHKERRQ(ierr); } } ierr = PetscOptionsGetString(NULL,"-log_detailed",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr); if (flg1) { if (mname[0]) {ierr = PetscLogPrintDetailed(PETSC_COMM_WORLD,mname);CHKERRQ(ierr);} else {ierr = PetscLogPrintDetailed(PETSC_COMM_WORLD,0);CHKERRQ(ierr);} } mname[0] = 0; ierr = PetscOptionsGetString(NULL,"-log_all",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr); ierr = PetscOptionsGetString(NULL,"-log",mname,PETSC_MAX_PATH_LEN,&flg2);CHKERRQ(ierr); if (flg1 || flg2) { if (mname[0]) PetscLogDump(mname); else PetscLogDump(0); } #endif /* Free all objects registered with PetscObjectRegisterDestroy() such as PETSC_VIEWER_XXX_(). */ ierr = PetscObjectRegisterDestroyAll();CHKERRQ(ierr); ierr = PetscStackDestroy();CHKERRQ(ierr); flg1 = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,"-no_signal_handler",&flg1,NULL);CHKERRQ(ierr); if (!flg1) { ierr = PetscPopSignalHandler();CHKERRQ(ierr);} flg1 = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,"-mpidump",&flg1,NULL);CHKERRQ(ierr); if (flg1) { ierr = PetscMPIDump(stdout);CHKERRQ(ierr); } flg1 = PETSC_FALSE; flg2 = PETSC_FALSE; /* preemptive call to avoid listing this option in options table as unused */ ierr = PetscOptionsHasName(NULL,"-malloc_dump",&flg1);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-objects_dump",&flg1);CHKERRQ(ierr); ierr = PetscOptionsGetBool(NULL,"-options_table",&flg2,NULL);CHKERRQ(ierr); if (flg2) { PetscViewer viewer; ierr = PetscViewerASCIIGetStdout(PETSC_COMM_WORLD,&viewer);CHKERRQ(ierr); ierr = PetscOptionsView(viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } /* to prevent PETSc -options_left from warning */ ierr = PetscOptionsHasName(NULL,"-nox",&flg1);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-nox_warning",&flg1);CHKERRQ(ierr); if (!PetscHMPIWorker) { /* worker processes skip this because they do not usually process options */ flg3 = PETSC_FALSE; /* default value is required */ ierr = PetscOptionsGetBool(NULL,"-options_left",&flg3,&flg1);CHKERRQ(ierr); ierr = PetscOptionsAllUsed(&nopt);CHKERRQ(ierr); if (flg3) { if (!flg2) { /* have not yet printed the options */ PetscViewer viewer; ierr = PetscViewerASCIIGetStdout(PETSC_COMM_WORLD,&viewer);CHKERRQ(ierr); ierr = PetscOptionsView(viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } if (!nopt) { ierr = PetscPrintf(PETSC_COMM_WORLD,"There are no unused options.\n");CHKERRQ(ierr); } else if (nopt == 1) { ierr = PetscPrintf(PETSC_COMM_WORLD,"There is one unused database option. It is:\n");CHKERRQ(ierr); } else { ierr = PetscPrintf(PETSC_COMM_WORLD,"There are %D unused database options. They are:\n",nopt);CHKERRQ(ierr); } } #if defined(PETSC_USE_DEBUG) if (nopt && !flg3 && !flg1) { ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! There are options you set that were not used!\n");CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! could be spelling mistake, etc!\n");CHKERRQ(ierr); ierr = PetscOptionsLeft();CHKERRQ(ierr); } else if (nopt && flg3) { #else if (nopt && flg3) { #endif ierr = PetscOptionsLeft();CHKERRQ(ierr); } } { PetscThreadComm tcomm_world; ierr = PetscGetThreadCommWorld(&tcomm_world);CHKERRQ(ierr); /* Free global thread communicator */ ierr = PetscThreadCommDestroy(&tcomm_world);CHKERRQ(ierr); } /* List all objects the user may have forgot to free */ ierr = PetscOptionsHasName(NULL,"-objects_dump",&flg1);CHKERRQ(ierr); if (flg1) { MPI_Comm local_comm; char string[64]; ierr = PetscOptionsGetString(NULL,"-objects_dump",string,64,NULL);CHKERRQ(ierr); ierr = MPI_Comm_dup(MPI_COMM_WORLD,&local_comm);CHKERRQ(ierr); ierr = PetscSequentialPhaseBegin_Private(local_comm,1);CHKERRQ(ierr); ierr = PetscObjectsDump(stdout,(string[0] == 'a') ? PETSC_TRUE : PETSC_FALSE);CHKERRQ(ierr); ierr = PetscSequentialPhaseEnd_Private(local_comm,1);CHKERRQ(ierr); ierr = MPI_Comm_free(&local_comm);CHKERRQ(ierr); } PetscObjectsCounts = 0; PetscObjectsMaxCounts = 0; ierr = PetscFree(PetscObjects);CHKERRQ(ierr); #if defined(PETSC_USE_LOG) ierr = PetscLogDestroy();CHKERRQ(ierr); #endif /* Destroy any packages that registered a finalize */ ierr = PetscRegisterFinalizeAll();CHKERRQ(ierr); /* Destroy all the function registration lists created */ ierr = PetscFinalize_DynamicLibraries();CHKERRQ(ierr); /* Print PetscFunctionLists that have not been properly freed ierr = PetscFunctionListPrintAll();CHKERRQ(ierr); */ if (petsc_history) { ierr = PetscCloseHistoryFile(&petsc_history);CHKERRQ(ierr); petsc_history = 0; } ierr = PetscInfoAllow(PETSC_FALSE,NULL);CHKERRQ(ierr); { char fname[PETSC_MAX_PATH_LEN]; FILE *fd; int err; fname[0] = 0; ierr = PetscOptionsGetString(NULL,"-malloc_dump",fname,250,&flg1);CHKERRQ(ierr); flg2 = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,"-malloc_test",&flg2,NULL);CHKERRQ(ierr); #if defined(PETSC_USE_DEBUG) if (PETSC_RUNNING_ON_VALGRIND) flg2 = PETSC_FALSE; #else flg2 = PETSC_FALSE; /* Skip reporting for optimized builds regardless of -malloc_test */ #endif if (flg1 && fname[0]) { char sname[PETSC_MAX_PATH_LEN]; sprintf(sname,"%s_%d",fname,rank); fd = fopen(sname,"w"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",sname); ierr = PetscMallocDump(fd);CHKERRQ(ierr); err = fclose(fd); if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file"); } else if (flg1 || flg2) { MPI_Comm local_comm; ierr = MPI_Comm_dup(MPI_COMM_WORLD,&local_comm);CHKERRQ(ierr); ierr = PetscSequentialPhaseBegin_Private(local_comm,1);CHKERRQ(ierr); ierr = PetscMallocDump(stdout);CHKERRQ(ierr); ierr = PetscSequentialPhaseEnd_Private(local_comm,1);CHKERRQ(ierr); ierr = MPI_Comm_free(&local_comm);CHKERRQ(ierr); } } { char fname[PETSC_MAX_PATH_LEN]; FILE *fd = NULL; fname[0] = 0; ierr = PetscOptionsGetString(NULL,"-malloc_log",fname,250,&flg1);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-malloc_log_threshold",&flg2);CHKERRQ(ierr); if (flg1 && fname[0]) { int err; if (!rank) { fd = fopen(fname,"w"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",fname); } ierr = PetscMallocDumpLog(fd);CHKERRQ(ierr); if (fd) { err = fclose(fd); if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file"); } } else if (flg1 || flg2) { ierr = PetscMallocDumpLog(stdout);CHKERRQ(ierr); } } /* Can be destroyed only after all the options are used */ ierr = PetscOptionsDestroy();CHKERRQ(ierr); PetscGlobalArgc = 0; PetscGlobalArgs = 0; #if defined(PETSC_USE_REAL___FLOAT128) ierr = MPI_Type_free(&MPIU___FLOAT128);CHKERRQ(ierr); #if defined(PETSC_HAVE_COMPLEX) ierr = MPI_Type_free(&MPIU___COMPLEX128);CHKERRQ(ierr); #endif ierr = MPI_Op_free(&MPIU_MAX);CHKERRQ(ierr); ierr = MPI_Op_free(&MPIU_MIN);CHKERRQ(ierr); #endif #if defined(PETSC_HAVE_COMPLEX) #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX) ierr = MPI_Type_free(&MPIU_C_DOUBLE_COMPLEX);CHKERRQ(ierr); ierr = MPI_Type_free(&MPIU_C_COMPLEX);CHKERRQ(ierr); #endif #endif #if (defined(PETSC_HAVE_COMPLEX) && !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)) || defined(PETSC_USE_REAL___FLOAT128) ierr = MPI_Op_free(&MPIU_SUM);CHKERRQ(ierr); #endif ierr = MPI_Type_free(&MPIU_2SCALAR);CHKERRQ(ierr); #if defined(PETSC_USE_64BIT_INDICES) || !defined(MPI_2INT) ierr = MPI_Type_free(&MPIU_2INT);CHKERRQ(ierr); #endif ierr = MPI_Op_free(&PetscMaxSum_Op);CHKERRQ(ierr); ierr = MPI_Op_free(&PetscADMax_Op);CHKERRQ(ierr); ierr = MPI_Op_free(&PetscADMin_Op);CHKERRQ(ierr); /* Destroy any known inner MPI_Comm's and attributes pointing to them Note this will not destroy any new communicators the user has created. If all PETSc objects were not destroyed those left over objects will have hanging references to the MPI_Comms that were freed; but that is ok because those PETSc objects will never be used again */ { PetscCommCounter *counter; PetscMPIInt flg; MPI_Comm icomm; union {MPI_Comm comm; void *ptr;} ucomm; ierr = MPI_Attr_get(PETSC_COMM_SELF,Petsc_InnerComm_keyval,&ucomm,&flg);CHKERRQ(ierr); if (flg) { icomm = ucomm.comm; ierr = MPI_Attr_get(icomm,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm does not have expected tag/name counter, problem with corrupted memory"); ierr = MPI_Attr_delete(PETSC_COMM_SELF,Petsc_InnerComm_keyval);CHKERRQ(ierr); ierr = MPI_Attr_delete(icomm,Petsc_Counter_keyval);CHKERRQ(ierr); ierr = MPI_Comm_free(&icomm);CHKERRQ(ierr); } ierr = MPI_Attr_get(PETSC_COMM_WORLD,Petsc_InnerComm_keyval,&ucomm,&flg);CHKERRQ(ierr); if (flg) { icomm = ucomm.comm; ierr = MPI_Attr_get(icomm,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm does not have expected tag/name counter, problem with corrupted memory"); ierr = MPI_Attr_delete(PETSC_COMM_WORLD,Petsc_InnerComm_keyval);CHKERRQ(ierr); ierr = MPI_Attr_delete(icomm,Petsc_Counter_keyval);CHKERRQ(ierr); ierr = MPI_Comm_free(&icomm);CHKERRQ(ierr); } } ierr = MPI_Keyval_free(&Petsc_Counter_keyval);CHKERRQ(ierr); ierr = MPI_Keyval_free(&Petsc_InnerComm_keyval);CHKERRQ(ierr); ierr = MPI_Keyval_free(&Petsc_OuterComm_keyval);CHKERRQ(ierr); #if defined(PETSC_HAVE_CUDA) { PetscInt p; for (p = 0; p < PetscGlobalSize; ++p) { if (p == PetscGlobalRank) cublasShutdown(); ierr = MPI_Barrier(PETSC_COMM_WORLD);CHKERRQ(ierr); } } #endif if (PetscBeganMPI) { #if defined(PETSC_HAVE_MPI_FINALIZED) PetscMPIInt flag; ierr = MPI_Finalized(&flag);CHKERRQ(ierr); if (flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"MPI_Finalize() has already been called, even though MPI_Init() was called by PetscInitialize()"); #endif ierr = MPI_Finalize();CHKERRQ(ierr); } /* Note: In certain cases PETSC_COMM_WORLD is never MPI_Comm_free()ed because the communicator has some outstanding requests on it. Specifically if the flag PETSC_HAVE_BROKEN_REQUEST_FREE is set (for IBM MPI implementation). See src/vec/utils/vpscat.c. Due to this the memory allocated in PetscCommDuplicate() is never freed as it should be. Thus one may obtain messages of the form [ 1] 8 bytes PetscCommDuplicate() line 645 in src/sys/mpiu.c indicating the memory was not freed. */ ierr = PetscMallocClear();CHKERRQ(ierr); PetscInitializeCalled = PETSC_FALSE; PetscFinalizeCalled = PETSC_TRUE; PetscFunctionReturn(ierr); } #if defined(PETSC_MISSING_LAPACK_lsame_) PETSC_EXTERN int lsame_(char *a,char *b) { if (*a == *b) return 1; if (*a + 32 == *b) return 1; if (*a - 32 == *b) return 1; return 0; } #endif #if defined(PETSC_MISSING_LAPACK_lsame) PETSC_EXTERN int lsame(char *a,char *b) { if (*a == *b) return 1; if (*a + 32 == *b) return 1; if (*a - 32 == *b) return 1; return 0; }
void declareBindings (void) { /* === Point-to-point === */ void* buf; int count; MPI_Datatype datatype; int dest; int tag; MPI_Comm comm; MPI_Send (buf, count, datatype, dest, tag, comm); // L12 int source; MPI_Status status; MPI_Recv (buf, count, datatype, source, tag, comm, &status); // L15 MPI_Get_count (&status, datatype, &count); MPI_Bsend (buf, count, datatype, dest, tag, comm); MPI_Ssend (buf, count, datatype, dest, tag, comm); MPI_Rsend (buf, count, datatype, dest, tag, comm); void* buffer; int size; MPI_Buffer_attach (buffer, size); // L22 MPI_Buffer_detach (buffer, &size); MPI_Request request; MPI_Isend (buf, count, datatype, dest, tag, comm, &request); // L25 MPI_Ibsend (buf, count, datatype, dest, tag, comm, &request); MPI_Issend (buf, count, datatype, dest, tag, comm, &request); MPI_Irsend (buf, count, datatype, dest, tag, comm, &request); MPI_Irecv (buf, count, datatype, source, tag, comm, &request); MPI_Wait (&request, &status); int flag; MPI_Test (&request, &flag, &status); // L32 MPI_Request_free (&request); MPI_Request* array_of_requests; int index; MPI_Waitany (count, array_of_requests, &index, &status); // L36 MPI_Testany (count, array_of_requests, &index, &flag, &status); MPI_Status* array_of_statuses; MPI_Waitall (count, array_of_requests, array_of_statuses); // L39 MPI_Testall (count, array_of_requests, &flag, array_of_statuses); int incount; int outcount; int* array_of_indices; MPI_Waitsome (incount, array_of_requests, &outcount, array_of_indices, array_of_statuses); // L44--45 MPI_Testsome (incount, array_of_requests, &outcount, array_of_indices, array_of_statuses); // L46--47 MPI_Iprobe (source, tag, comm, &flag, &status); // L48 MPI_Probe (source, tag, comm, &status); MPI_Cancel (&request); MPI_Test_cancelled (&status, &flag); MPI_Send_init (buf, count, datatype, dest, tag, comm, &request); MPI_Bsend_init (buf, count, datatype, dest, tag, comm, &request); MPI_Ssend_init (buf, count, datatype, dest, tag, comm, &request); MPI_Rsend_init (buf, count, datatype, dest, tag, comm, &request); MPI_Recv_init (buf, count, datatype, source, tag, comm, &request); MPI_Start (&request); MPI_Startall (count, array_of_requests); void* sendbuf; int sendcount; MPI_Datatype sendtype; int sendtag; void* recvbuf; int recvcount; MPI_Datatype recvtype; MPI_Datatype recvtag; MPI_Sendrecv (sendbuf, sendcount, sendtype, dest, sendtag, recvbuf, recvcount, recvtype, source, recvtag, comm, &status); // L67--69 MPI_Sendrecv_replace (buf, count, datatype, dest, sendtag, source, recvtag, comm, &status); // L70--71 MPI_Datatype oldtype; MPI_Datatype newtype; MPI_Type_contiguous (count, oldtype, &newtype); // L74 int blocklength; { int stride; MPI_Type_vector (count, blocklength, stride, oldtype, &newtype); // L78 } { MPI_Aint stride; MPI_Type_hvector (count, blocklength, stride, oldtype, &newtype); // L82 } int* array_of_blocklengths; { int* array_of_displacements; MPI_Type_indexed (count, array_of_blocklengths, array_of_displacements, oldtype, &newtype); // L87--88 } { MPI_Aint* array_of_displacements; MPI_Type_hindexed (count, array_of_blocklengths, array_of_displacements, oldtype, &newtype); // L92--93 MPI_Datatype* array_of_types; MPI_Type_struct (count, array_of_blocklengths, array_of_displacements, array_of_types, &newtype); // L95--96 } void* location; MPI_Aint address; MPI_Address (location, &address); // L100 MPI_Aint extent; MPI_Type_extent (datatype, &extent); // L102 MPI_Type_size (datatype, &size); MPI_Aint displacement; MPI_Type_lb (datatype, &displacement); // L105 MPI_Type_ub (datatype, &displacement); MPI_Type_commit (&datatype); MPI_Type_free (&datatype); MPI_Get_elements (&status, datatype, &count); void* inbuf; void* outbuf; int outsize; int position; MPI_Pack (inbuf, incount, datatype, outbuf, outsize, &position, comm); // L114 int insize; MPI_Unpack (inbuf, insize, &position, outbuf, outcount, datatype, comm); // L116--117 MPI_Pack_size (incount, datatype, comm, &size); /* === Collectives === */ MPI_Barrier (comm); // L121 int root; MPI_Bcast (buffer, count, datatype, root, comm); // L123 MPI_Gather (sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm); // L124--125 int* recvcounts; int* displs; MPI_Gatherv (sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, root, comm); // L128--130 MPI_Scatter (sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm); // L131--132 int* sendcounts; MPI_Scatterv (sendbuf, sendcounts, displs, sendtype, recvbuf, recvcount, recvtype, root, comm); // L134--135 MPI_Allgather (sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm); // L136--137 MPI_Allgatherv (sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, comm); // L138--140 MPI_Alltoall (sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm); // L141--142 int* sdispls; int* rdispls; MPI_Alltoallv (sendbuf, sendcounts, sdispls, sendtype, recvbuf, recvcounts, rdispls, recvtype, comm); // L145--147 MPI_Op op; MPI_Reduce (sendbuf, recvbuf, count, datatype, op, root, comm); // L149 #if 0 MPI_User_function function; int commute; MPI_Op_create (function, commute, &op); // L153 #endif MPI_Op_free (&op); // L155 MPI_Allreduce (sendbuf, recvbuf, count, datatype, op, comm); MPI_Reduce_scatter (sendbuf, recvbuf, recvcounts, datatype, op, comm); MPI_Scan (sendbuf, recvbuf, count, datatype, op, comm); /* === Groups, contexts, and communicators === */ MPI_Group group; MPI_Group_size (group, &size); // L162 int rank; MPI_Group_rank (group, &rank); // L164 MPI_Group group1; int n; int* ranks1; MPI_Group group2; int* ranks2; MPI_Group_translate_ranks (group1, n, ranks1, group2, ranks2); // L170 int result; MPI_Group_compare (group1, group2, &result); // L172 MPI_Group newgroup; MPI_Group_union (group1, group2, &newgroup); // L174 MPI_Group_intersection (group1, group2, &newgroup); MPI_Group_difference (group1, group2, &newgroup); int* ranks; MPI_Group_incl (group, n, ranks, &newgroup); // L178 MPI_Group_excl (group, n, ranks, &newgroup); extern int ranges[][3]; MPI_Group_range_incl (group, n, ranges, &newgroup); // L181 MPI_Group_range_excl (group, n, ranges, &newgroup); MPI_Group_free (&group); MPI_Comm_size (comm, &size); MPI_Comm_rank (comm, &rank); MPI_Comm comm1; MPI_Comm comm2; MPI_Comm_compare (comm1, comm2, &result); MPI_Comm newcomm; MPI_Comm_dup (comm, &newcomm); MPI_Comm_create (comm, group, &newcomm); int color; int key; MPI_Comm_split (comm, color, key, &newcomm); // L194 MPI_Comm_free (&comm); MPI_Comm_test_inter (comm, &flag); MPI_Comm_remote_size (comm, &size); MPI_Comm_remote_group (comm, &group); MPI_Comm local_comm; int local_leader; MPI_Comm peer_comm; int remote_leader; MPI_Comm newintercomm; MPI_Intercomm_create (local_comm, local_leader, peer_comm, remote_leader, tag, &newintercomm); // L204--205 MPI_Comm intercomm; MPI_Comm newintracomm; int high; MPI_Intercomm_merge (intercomm, high, &newintracomm); // L209 int keyval; #if 0 MPI_Copy_function copy_fn; MPI_Delete_function delete_fn; void* extra_state; MPI_Keyval_create (copy_fn, delete_fn, &keyval, extra_state); // L215 #endif MPI_Keyval_free (&keyval); // L217 void* attribute_val; MPI_Attr_put (comm, keyval, attribute_val); // L219 MPI_Attr_get (comm, keyval, attribute_val, &flag); MPI_Attr_delete (comm, keyval); /* === Environmental inquiry === */ char* name; int resultlen; MPI_Get_processor_name (name, &resultlen); // L226 MPI_Errhandler errhandler; #if 0 MPI_Handler_function function; MPI_Errhandler_create (function, &errhandler); // L230 #endif MPI_Errhandler_set (comm, errhandler); // L232 MPI_Errhandler_get (comm, &errhandler); MPI_Errhandler_free (&errhandler); int errorcode; char* string; MPI_Error_string (errorcode, string, &resultlen); // L237 int errorclass; MPI_Error_class (errorcode, &errorclass); // L239 MPI_Wtime (); MPI_Wtick (); int argc; char** argv; MPI_Init (&argc, &argv); // L244 MPI_Finalize (); MPI_Initialized (&flag); MPI_Abort (comm, errorcode); }
int main(int argc, char *argv[]) { int key[3]; int val[3] = { 1, 2, 3 }; int flag; int *out; MPI_Init(&argc, &argv); MPI_Keyval_create(MPI_NULL_COPY_FN, MPI_NULL_DELETE_FN, &key[0], (void *)0); MPI_Keyval_create(MPI_NULL_COPY_FN, delete_attr, &key[1], (void *)0); /* TODO: nonempty COPY_FN MPI_Comm_create_keyval(MPI_NULL_COPY_FN, delete_attr, &key[2], (void *)0); */ MPI_Attr_get(MPI_COMM_WORLD, key[0], NULL, &flag); if (flag) { return 1; } MPI_Attr_get(MPI_COMM_WORLD, key[1], NULL, &flag); if (flag) { return 1; } MPI_Attr_put(MPI_COMM_WORLD, key[0], &val[0]); MPI_Attr_put(MPI_COMM_WORLD, key[1], &val[1]); MPI_Attr_get(MPI_COMM_SELF, key[1], NULL, &flag); if (flag) { return 1; } MPI_Attr_put(MPI_COMM_SELF, key[1], &val[2]); MPI_Attr_get(MPI_COMM_SELF, key[1], &out, &flag); if (!flag || *out != 3) { return 1; } MPI_Attr_get(MPI_COMM_WORLD, key[1], &out, &flag); if (!flag || *out != 2) { return 1; } MPI_Attr_get(MPI_COMM_WORLD, key[0], &out, &flag); if (!flag || *out != 1) { return 1; } MPI_Attr_put(MPI_COMM_WORLD, key[1], &val[0]); MPI_Attr_get(MPI_COMM_WORLD, key[1], &out, &flag); if (!flag || *out != 1) { return 1; } MPI_Attr_get(MPI_COMM_SELF, key[1], &out, &flag); if (!flag || *out != 3) { return 1; } MPI_Attr_delete(MPI_COMM_WORLD, key[0]); MPI_Attr_delete(MPI_COMM_WORLD, key[1]); MPI_Attr_delete(MPI_COMM_SELF, key[1]); MPI_Keyval_free(&key[0]); MPI_Keyval_free(&key[1]); if (key[0] != MPI_KEYVAL_INVALID || key[1] != MPI_KEYVAL_INVALID) { return 2; } return 0; }
int main(int argc, char *argv[]) { int errs = 0; int key[3], attrval[3]; int i; MPI_Comm comm; MTest_Init(&argc, &argv); { comm = MPI_COMM_WORLD; /* Create key values */ for (i = 0; i < 3; i++) { MPI_Keyval_create(MPI_NULL_COPY_FN, MPI_NULL_DELETE_FN, &key[i], (void *) 0); attrval[i] = 1024 * i; } /* Insert attribute in several orders. Test after put with get, * then delete, then confirm delete with get. */ MPI_Attr_put(comm, key[2], &attrval[2]); MPI_Attr_put(comm, key[1], &attrval[1]); MPI_Attr_put(comm, key[0], &attrval[0]); errs += checkAttrs(comm, 3, key, attrval); MPI_Attr_delete(comm, key[0]); MPI_Attr_delete(comm, key[1]); MPI_Attr_delete(comm, key[2]); errs += checkNoAttrs(comm, 3, key); MPI_Attr_put(comm, key[1], &attrval[1]); MPI_Attr_put(comm, key[2], &attrval[2]); MPI_Attr_put(comm, key[0], &attrval[0]); errs += checkAttrs(comm, 3, key, attrval); MPI_Attr_delete(comm, key[2]); MPI_Attr_delete(comm, key[1]); MPI_Attr_delete(comm, key[0]); errs += checkNoAttrs(comm, 3, key); MPI_Attr_put(comm, key[0], &attrval[0]); MPI_Attr_put(comm, key[1], &attrval[1]); MPI_Attr_put(comm, key[2], &attrval[2]); errs += checkAttrs(comm, 3, key, attrval); MPI_Attr_delete(comm, key[1]); MPI_Attr_delete(comm, key[2]); MPI_Attr_delete(comm, key[0]); errs += checkNoAttrs(comm, 3, key); for (i = 0; i < 3; i++) { MPI_Keyval_free(&key[i]); } } MTest_Finalize(errs); return MTestReturnValue(errs); }