xref: /petsc/src/vec/vec/impls/shared/shvec.c (revision 9895aa37ac365bac650f6bd8bf977519f7222510)
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