1 2 /* 3 This file contains routines for Parallel vector operations that use shared memory 4 */ 5 #include <../src/vec/vec/impls/mpi/pvecimpl.h> /*I "petscvec.h" I*/ 6 7 #if defined(PETSC_USE_SHARED_MEMORY) 8 9 extern PetscErrorCode PetscSharedMalloc(MPI_Comm,PetscInt,PetscInt,void**); 10 11 #undef __FUNCT__ 12 #define __FUNCT__ "VecDuplicate_Shared" 13 PetscErrorCode VecDuplicate_Shared(Vec win,Vec *v) 14 { 15 PetscErrorCode ierr; 16 Vec_MPI *w = (Vec_MPI*)win->data; 17 PetscScalar *array; 18 19 PetscFunctionBegin; 20 /* first processor allocates entire array and sends it's address to the others */ 21 ierr = PetscSharedMalloc(PetscObjectComm((PetscObject)win),win->map->n*sizeof(PetscScalar),win->map->N*sizeof(PetscScalar),(void**)&array);CHKERRQ(ierr); 22 23 ierr = VecCreate(PetscObjectComm((PetscObject)win),v);CHKERRQ(ierr); 24 ierr = VecSetSizes(*v,win->map->n,win->map->N);CHKERRQ(ierr); 25 ierr = VecCreate_MPI_Private(*v,PETSC_FALSE,w->nghost,array);CHKERRQ(ierr); 26 ierr = PetscLayoutReference(win->map,&(*v)->map);CHKERRQ(ierr); 27 28 /* New vector should inherit stashing property of parent */ 29 (*v)->stash.donotstash = win->stash.donotstash; 30 (*v)->stash.ignorenegidx = win->stash.ignorenegidx; 31 32 ierr = PetscObjectListDuplicate(((PetscObject)win)->olist,&((PetscObject)*v)->olist);CHKERRQ(ierr); 33 ierr = PetscFunctionListDuplicate(((PetscObject)win)->qlist,&((PetscObject)*v)->qlist);CHKERRQ(ierr); 34 35 (*v)->ops->duplicate = VecDuplicate_Shared; 36 (*v)->bstash.bs = win->bstash.bs; 37 PetscFunctionReturn(0); 38 } 39 40 41 EXTERN_C_BEGIN 42 #undef __FUNCT__ 43 #define __FUNCT__ "VecCreate_Shared" 44 PetscErrorCode VecCreate_Shared(Vec vv) 45 { 46 PetscErrorCode ierr; 47 PetscScalar *array; 48 49 PetscFunctionBegin; 50 ierr = PetscSplitOwnership(PetscObjectComm((PetscObject)vv),&vv->map->n,&vv->map->N);CHKERRQ(ierr); 51 ierr = PetscSharedMalloc(PetscObjectComm((PetscObject)vv),vv->map->n*sizeof(PetscScalar),vv->map->N*sizeof(PetscScalar),(void**)&array);CHKERRQ(ierr); 52 53 ierr = VecCreate_MPI_Private(vv,PETSC_FALSE,0,array);CHKERRQ(ierr); 54 vv->ops->duplicate = VecDuplicate_Shared; 55 PetscFunctionReturn(0); 56 } 57 EXTERN_C_END 58 59 60 /* ---------------------------------------------------------------------------------------- 61 Code to manage shared memory allocation using standard Unix shared memory 62 */ 63 #include <petscsys.h> 64 #if defined(PETSC_HAVE_PWD_H) 65 #include <pwd.h> 66 #endif 67 #include <ctype.h> 68 #include <sys/stat.h> 69 #if defined(PETSC_HAVE_UNISTD_H) 70 #include <unistd.h> 71 #endif 72 #if defined(PETSC_HAVE_SYS_UTSNAME_H) 73 #include <sys/utsname.h> 74 #endif 75 #include <fcntl.h> 76 #include <time.h> 77 #if defined(PETSC_HAVE_SYS_SYSTEMINFO_H) 78 #include <sys/systeminfo.h> 79 #endif 80 #include <sys/shm.h> 81 #include <sys/mman.h> 82 83 84 static PetscMPIInt Petsc_Shared_keyval = MPI_KEYVAL_INVALID; 85 86 #undef __FUNCT__ 87 #define __FUNCT__ "Petsc_DeleteShared" 88 /* 89 Private routine to delete internal storage when a communicator is freed. 90 This is called by MPI, not by users. 91 92 The binding for the first argument changed from MPI 1.0 to 1.1; in 1.0 93 it was MPI_Comm *comm. 94 */ 95 static PetscErrorCode Petsc_DeleteShared(MPI_Comm comm,PetscInt keyval,void *attr_val,void *extra_state) 96 { 97 PetscErrorCode ierr; 98 99 PetscFunctionBegin; 100 ierr = PetscFree(attr_val);CHKERRQ(ierr); 101 PetscFunctionReturn(MPI_SUCCESS); 102 } 103 104 #undef __FUNCT__ 105 #define __FUNCT__ "PetscSharedMalloc" 106 /* 107 108 This routine is still incomplete and needs work. 109 110 For this to work on the Apple Mac OS X you will likely need to add something line the following to the file /etc/sysctl.conf 111 cat /etc/sysctl.conf 112 kern.sysv.shmmax=67108864 113 kern.sysv.shmmin=1 114 kern.sysv.shmmni=32 115 kern.sysv.shmseg=512 116 kern.sysv.shmall=1024 117 118 This does not currently free the shared memory after the program runs. Use the Unix command ipcs to see the shared memory in use and 119 ipcrm to remove the shared memory in use. 120 121 */ 122 PetscErrorCode PetscSharedMalloc(MPI_Comm comm,PetscInt llen,PetscInt len,void **result) 123 { 124 PetscErrorCode ierr; 125 PetscInt shift; 126 PetscMPIInt rank,flag; 127 int *arena,id,key = 0; 128 char *value; 129 130 PetscFunctionBegin; 131 *result = 0; 132 133 ierr = MPI_Scan(&llen,&shift,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr); 134 shift -= llen; 135 136 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 137 if (!rank) { 138 id = shmget(key,len, 0666 |IPC_CREAT); 139 if (id == -1) { 140 perror("Unable to malloc shared memory"); 141 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to malloc shared memory"); 142 } 143 } else { 144 id = shmget(key,len, 0666); 145 if (id == -1) { 146 perror("Unable to malloc shared memory"); 147 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to malloc shared memory"); 148 } 149 } 150 value = shmat(id,(void*)0,0); 151 if (value == (char*)-1) { 152 perror("Unable to access shared memory allocated"); 153 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to access shared memory allocated"); 154 } 155 *result = (void*) (value + shift); 156 PetscFunctionReturn(0); 157 } 158 159 #else 160 161 EXTERN_C_BEGIN 162 extern PetscErrorCode VecCreate_Seq(Vec); 163 EXTERN_C_END 164 165 EXTERN_C_BEGIN 166 #undef __FUNCT__ 167 #define __FUNCT__ "VecCreate_Shared" 168 PetscErrorCode VecCreate_Shared(Vec vv) 169 { 170 PetscErrorCode ierr; 171 PetscMPIInt size; 172 173 PetscFunctionBegin; 174 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)vv),&size);CHKERRQ(ierr); 175 if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"No supported for shared memory vector objects on this machine"); 176 ierr = VecCreate_Seq(vv);CHKERRQ(ierr); 177 PetscFunctionReturn(0); 178 } 179 EXTERN_C_END 180 181 #endif 182 183 #undef __FUNCT__ 184 #define __FUNCT__ "VecCreateShared" 185 /*@ 186 VecCreateShared - Creates a parallel vector that uses shared memory. 187 188 Input Parameters: 189 . comm - the MPI communicator to use 190 . n - local vector length (or PETSC_DECIDE to have calculated if N is given) 191 . N - global vector length (or PETSC_DECIDE to have calculated if n is given) 192 193 Output Parameter: 194 . vv - the vector 195 196 Collective on MPI_Comm 197 198 Notes: 199 Currently VecCreateShared() is available only on the SGI; otherwise, 200 this routine is the same as VecCreateMPI(). 201 202 Use VecDuplicate() or VecDuplicateVecs() to form additional vectors of the 203 same type as an existing vector. 204 205 Level: advanced 206 207 Concepts: vectors^creating with shared memory 208 209 .seealso: VecCreateSeq(), VecCreate(), VecCreateMPI(), VecDuplicate(), VecDuplicateVecs(), 210 VecCreateGhost(), VecCreateMPIWithArray(), VecCreateGhostWithArray() 211 212 @*/ 213 PetscErrorCode VecCreateShared(MPI_Comm comm,PetscInt n,PetscInt N,Vec *v) 214 { 215 PetscErrorCode ierr; 216 217 PetscFunctionBegin; 218 ierr = VecCreate(comm,v);CHKERRQ(ierr); 219 ierr = VecSetSizes(*v,n,N);CHKERRQ(ierr); 220 ierr = VecSetType(*v,VECSHARED);CHKERRQ(ierr); 221 PetscFunctionReturn(0); 222 } 223 224 225 226 227 228