SURFEX v8.1
General documentation of Surfex
oml_mod.F90
Go to the documentation of this file.
1 MODULE oml_mod
2 
3 !-- the following system specific omp_lib-module is not always available (e.g. pgf90)
4 !! use omp_lib
5 
6 USE parkind1 ,ONLY : jpim, jpib
7 
8 !**SS/18-Feb-2005
9 !--Dr.Hook references removed, because these locks may also be
10 ! called from within drhook.c itself !!
11 !--Also, there could be considerable & unjustified overhead
12 ! when using Dr.Hook in such a low level
13 
14 !**SS/15-Dec-2005
15 !--The size of lock-variables are now OMP_LOCK_KIND as of in OMP_LIB,
16 ! and OMP_LOCK_KIND is aliased to OML_LOCK_KIND
17 ! OMP_LOCK_KIND is usually 4 in 32-bit addressing mode
18 ! 8 in 64-bit addressing mode
19 !--M_OML_LOCK changed to M_EVENT and kept as 32-bit int
20 !--OML_FUNCT changed to OML_TEST_EVENT
21 !--M_LOCK initialized to -1
22 !--M_EVENT initialized to 0
23 !--Added intent(s)
24 !--Support for omp_lib (but not always available)
25 !--Locks can now also be set/unset OUTSIDE the parallel regions
26 !--Added routine OML_TEST_LOCK (attempts to set lock, but if *un*successful, does NOT block)
27 !--Buffer-zone for M_LOCK; now a vector of 2 elements in case problems/inconsistencies with OMP_LOCK_KIND 4/8
28 
29 !**SS/22-Feb-2006
30 !--Locking routines are doing nothing unless OMP_GET_MAX_THREADS() > 1
31 ! This is to avoid unacceptable deadlocks/timeouts with signal handlers when
32 ! the only thread receives signal while inside locked region
33 !--Affected routines: OML_TEST_LOCK() --> always receives .TRUE.
34 ! OML_SET_LOCK() --> sets nothing
35 ! OML_UNSET_LOCK() --> unsets nothing
36 ! OML_INIT_LOCK() --> inits nothing
37 
38 !**SS/11-Sep-2006
39 !--Added OML_DEBUG feature
40 
41 !**REK/18-Jul-2007
42 !--Protected OML_DESTROY_LOCK
43 
44 !**REK/07-Sep-2007
45 !--Add OMP FLUSH feature
46 
47 !**SS/05-Dec-2007
48 !--Added routine OML_NUM_THREADS([optional_new_number_of_threads])
49 ! 1) To adjust [reduce] the number of threads working in concert
50 ! Accepts only # of threads between 1 and the max # of threads (i.e. from export OMP_NUM_THREADS=<value>)
51 ! 2) Returns the previous active number of threads
52 ! 3) Can be called from outside the OpenMP-parallel region only
53 
54 !**SS/14-Dec-2007
55 !--The routine OML_NUM_THREADS() now also accepts character string (= environment variable)
56 ! as the sole argumentoz
57 !--You could now set effective number of threads (<= $OMP_NUM_THREADS) to the value of
58 ! particular environment variable; f.ex.:
59 ! export OML_MSGPASS_OBSDATA_READ=8 and call to OML_NUM_THREADS('OML_MSGPASS_OBSDATA_READ')
60 ! would set the effective no. of threads to (max) 8 when reading obs. wiz msgpass_obsdata
61 
62 !**SS/09-May-2008
63 !-- OML_NUM_THREADS() did not work as expected since I misinterpreted the meaning of
64 ! the OpenMP-function OMP_NUM_THREADS()
65 !-- With two PRIVATE [to this module] variables the bug will get sorted out
66 ! + a new routine OML_INIT() was added (to be called from MPL_INIT or so)
67 
68 !**FV/27-May-2009
69 !-- OML_GET_NUM_THREADS()
70 
71 IMPLICIT NONE
72 
73 SAVE
74 
75 PRIVATE
76 
77 LOGICAL :: oml_debug = .false.
78 
79 INTERFACE oml_num_threads
80 MODULE PROCEDURE &
83 END INTERFACE
84 
91 
92 !-- The following should normally be 4 in 32-bit addressing mode
93 ! 8 in 64-bit addressing mode
94 ! Since system specific omp_lib-module is not always available (e.g. pgf90)
95 ! we hardcode OML_LOCK_KIND to JPIB (usually 8) for now
96 !!INTEGER(KIND=JPIM), PARAMETER :: OML_LOCK_KIND = OMP_LOCK_KIND
97 INTEGER(KIND=JPIM), PARAMETER :: oml_lock_kind = jpib
98 
99 !-- Note: Still JPIM !!
100 INTEGER(KIND=JPIM) :: m_event = 0
101 
102 !-- Note: OML_LOCK_KIND, not JPIM !!
103 INTEGER(KIND=OML_LOCK_KIND) :: m_lock(2) = (/-1, -1/)
104 
105 !-- The two PRIVATE [to this module] variables
106 INTEGER(KIND=JPIM) :: n_oml_max_threads = -1
107 
108 CONTAINS
109 
110 SUBROUTINE oml_init()
111 !$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
112 IF (n_oml_max_threads == -1) THEN
114 !$ N_OML_MAX_THREADS = OMP_GET_MAX_THREADS()
115 ENDIF
116 END SUBROUTINE oml_init
117 
118 FUNCTION oml_omp()
119 LOGICAL :: OML_OMP
120 oml_omp=.false.
121 !$ OML_OMP=.TRUE.
122 END FUNCTION oml_omp
123 
124 FUNCTION oml_in_parallel()
125 LOGICAL :: OML_IN_PARALLEL
126 !$ LOGICAL :: OMP_IN_PARALLEL
127 !$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
128 oml_in_parallel=.false.
129 !$ OML_IN_PARALLEL=((OMP_GET_MAX_THREADS() > 1).AND.OMP_IN_PARALLEL())
130 END FUNCTION oml_in_parallel
131 
132 FUNCTION oml_test_lock(MYLOCK)
133 INTEGER(KIND=OML_LOCK_KIND),INTENT(INOUT),OPTIONAL :: MYLOCK
134 LOGICAL :: OML_TEST_LOCK
135 !$ LOGICAL :: OMP_TEST_LOCK
136 !$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
137 oml_test_lock = .true.
138 !$ IF(OMP_GET_MAX_THREADS() > 1) THEN
139 !$ IF(PRESENT(MYLOCK))THEN
140 !$ OML_TEST_LOCK = OMP_TEST_LOCK(MYLOCK)
141 !$ ELSE
142 !$ OML_TEST_LOCK = OMP_TEST_LOCK(M_LOCK(1))
143 !$ ENDIF
144 !$ ENDIF
145 END FUNCTION oml_test_lock
146 
147 SUBROUTINE oml_unset_lock(MYLOCK)
148 INTEGER(KIND=OML_LOCK_KIND),INTENT(INOUT),OPTIONAL :: MYLOCK
149 !$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
150 !$ IF(OMP_GET_MAX_THREADS() > 1) THEN
151 !$ IF(PRESENT(MYLOCK))THEN
152 !$ CALL OMP_UNSET_LOCK(MYLOCK)
153 !$ ELSE
154 !$ CALL OMP_UNSET_LOCK(M_LOCK(1))
155 !$ ENDIF
156 !$ ENDIF
157 END SUBROUTINE oml_unset_lock
158 
159 SUBROUTINE oml_set_lock(MYLOCK)
160 INTEGER(KIND=OML_LOCK_KIND),INTENT(INOUT),OPTIONAL :: MYLOCK
161 !$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
162 !$ IF(OMP_GET_MAX_THREADS() > 1) THEN
163 !$ IF(PRESENT(MYLOCK))THEN
164 !$ CALL OMP_SET_LOCK(MYLOCK)
165 !$ ELSE
166 !$ CALL OMP_SET_LOCK(M_LOCK(1))
167 !$ ENDIF
168 !$ ENDIF
169 END SUBROUTINE oml_set_lock
170 
171 SUBROUTINE oml_init_lock(MYLOCK)
172 INTEGER(KIND=OML_LOCK_KIND),INTENT(INOUT),OPTIONAL :: MYLOCK
173 !$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
174 !$ IF(OMP_GET_MAX_THREADS() > 1) THEN
175 !$ IF(PRESENT(MYLOCK))THEN
176 !$ CALL OMP_INIT_LOCK(MYLOCK)
177 !$ ELSE
178 !$ CALL OMP_INIT_LOCK(M_LOCK(1))
179 !$ ENDIF
180 !$ ENDIF
181 END SUBROUTINE oml_init_lock
182 
183 SUBROUTINE oml_destroy_lock(MYLOCK)
184 INTEGER(KIND=OML_LOCK_KIND),INTENT(INOUT),OPTIONAL :: MYLOCK
185 !$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
186 !$ IF(OMP_GET_MAX_THREADS() > 1) THEN
187 !$ IF(PRESENT(MYLOCK))THEN
188 !$ CALL OMP_DESTROY_LOCK(MYLOCK)
189 !$ ELSE
190 !$ CALL OMP_DESTROY_LOCK(M_LOCK(1))
191 !$ ENDIF
192 !$ ENDIF
193 END SUBROUTINE oml_destroy_lock
194 
195 FUNCTION oml_test_event(K,MYEVENT)
196 LOGICAL :: OML_TEST_EVENT
197 INTEGER(KIND=JPIM),INTENT(IN) :: K,MYEVENT
198 #ifndef RS6K
199 !$OMP FLUSH
200 #endif
201 IF(k.EQ.myevent) THEN
202  oml_test_event =.true.
203 ELSE
204  oml_test_event=.false.
205 ENDIF
206 END FUNCTION oml_test_event
207 
208 SUBROUTINE oml_wait_event(K,MYEVENT)
209 INTEGER(KIND=JPIM),INTENT(IN) :: K
210 INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: MYEVENT
211 IF(PRESENT(myevent))THEN
212  DO
213  IF(oml_test_event(k,myevent)) EXIT
214  ENDDO
215 ELSE
216  DO
217  IF(oml_test_event(k,m_event)) EXIT
218  ENDDO
219 ENDIF
220 END SUBROUTINE oml_wait_event
221 
222 SUBROUTINE oml_set_event(K,MYEVENT)
223 INTEGER(KIND=JPIM),INTENT(IN) :: K
224 INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: MYEVENT
225 IF(PRESENT(myevent))THEN
226  myevent=k
227 ELSE
228  m_event=k
229 ENDIF
230 END SUBROUTINE oml_set_event
231 
232 SUBROUTINE oml_incr_event(K,MYEVENT)
233 INTEGER(KIND=JPIM) :: K
234 INTEGER(KIND=JPIM),INTENT(INOUT),OPTIONAL :: MYEVENT
235 !$OMP FLUSH
236 IF(PRESENT(myevent))THEN
237 !$OMP ATOMIC
238  myevent=myevent+k
239 ELSE
240 !$OMP ATOMIC
241  m_event=m_event+k
242 ENDIF
243 #ifndef RS6K
244 !$OMP FLUSH
245 #endif
246 END SUBROUTINE oml_incr_event
247 
248 FUNCTION oml_my_thread()
249 INTEGER(KIND=JPIM) :: OML_MY_THREAD
250 !$ INTEGER(KIND=JPIM) OMP_GET_THREAD_NUM
251 oml_my_thread = 1
252 !$ OML_MY_THREAD = OMP_GET_THREAD_NUM() + 1
253 END FUNCTION oml_my_thread
254 
255 FUNCTION oml_max_threads()
256 INTEGER(KIND=JPIM) :: OML_MAX_THREADS
257 !$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
258 oml_max_threads = 1
259 !$ OML_MAX_THREADS = OMP_GET_MAX_THREADS()
260 END FUNCTION oml_max_threads
261 
262 FUNCTION oml_get_num_threads()
263 INTEGER(KIND=JPIM) :: OML_GET_NUM_THREADS
264 !$ INTEGER(KIND=JPIM) OMP_GET_NUM_THREADS
265 oml_get_num_threads = 1
266 !$ OML_GET_NUM_THREADS = OMP_GET_NUM_THREADS()
267 END FUNCTION oml_get_num_threads
268 
269 FUNCTION oml_num_threads_int(KOMP_SET_THREADS)
270 INTEGER(KIND=JPIM) :: OML_NUM_THREADS_INT
271 INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KOMP_SET_THREADS
272 !$ LOGICAL :: OMP_IN_PARALLEL
273 !$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
274 oml_num_threads_int = 1
275 !$ OML_NUM_THREADS_INT = OMP_GET_MAX_THREADS()
276 !$ IF (PRESENT(KOMP_SET_THREADS)) THEN
277 !$ IF (KOMP_SET_THREADS >= 1 .AND. KOMP_SET_THREADS <= N_OML_MAX_THREADS) THEN
278 !- This is the absolute max no. of threads available --> ^^^^^^^^^^^^^^^^^ <--
279 !$ IF (.NOT.OMP_IN_PARALLEL()) THEN ! Change only if called from OUTSIDE the OpenMP-parallel region
280 !$ CALL OMP_SET_NUM_THREADS(KOMP_SET_THREADS)
281 !$ ENDIF
282 !$ ENDIF
283 !$ ENDIF
284 END FUNCTION oml_num_threads_int
285 
286 FUNCTION oml_num_threads_str(CD_ENV)
287 INTEGER(KIND=JPIM) :: OML_NUM_THREADS_STR
288 CHARACTER(LEN=*),INTENT(IN) :: CD_ENV
289 !$ character(len=20) CLvalue
290 !$ INTEGER(KIND=JPIM) :: itmp
291 oml_num_threads_str = 1
292 !$ OML_NUM_THREADS_STR = OML_NUM_THREADS_INT()
293 !$ IF (LEN(CD_ENV) > 0) THEN
294 !$ CALL GET_ENVIRONMENT_VARIABLE(CD_ENV,CLvalue)
295 !$ IF (CLvalue /= ' ') THEN
296 !$ READ(CLvalue,'(i20)',end=99,err=99) itmp
297 !$ OML_NUM_THREADS_STR = OML_NUM_THREADS_INT(itmp)
298 !$ ENDIF
299 !$ 99 continue
300 !$ ENDIF
301 END FUNCTION oml_num_threads_str
302 
303 END MODULE oml_mod
subroutine, public oml_set_lock(MYLOCK)
Definition: oml_mod.F90:160
logical function, public oml_test_event(K, MYEVENT)
Definition: oml_mod.F90:196
integer, parameter jpim
Definition: parkind1.F90:13
subroutine, public oml_init_lock(MYLOCK)
Definition: oml_mod.F90:172
integer(kind=jpim) function, public oml_get_num_threads()
Definition: oml_mod.F90:263
subroutine, public oml_destroy_lock(MYLOCK)
Definition: oml_mod.F90:184
subroutine, public oml_unset_lock(MYLOCK)
Definition: oml_mod.F90:148
logical function, public oml_in_parallel()
Definition: oml_mod.F90:125
logical, public oml_debug
Definition: oml_mod.F90:77
integer(kind=jpim), parameter, public oml_lock_kind
Definition: oml_mod.F90:97
integer(kind=oml_lock_kind), dimension(2) m_lock
Definition: oml_mod.F90:103
subroutine, public oml_wait_event(K, MYEVENT)
Definition: oml_mod.F90:209
logical function, public oml_test_lock(MYLOCK)
Definition: oml_mod.F90:133
integer(kind=jpim) m_event
Definition: oml_mod.F90:100
subroutine, public oml_incr_event(K, MYEVENT)
Definition: oml_mod.F90:233
integer(kind=jpim) function, public oml_my_thread()
Definition: oml_mod.F90:249
subroutine, public oml_set_event(K, MYEVENT)
Definition: oml_mod.F90:223
integer(kind=jpim) n_oml_max_threads
Definition: oml_mod.F90:106
logical function, public oml_omp()
Definition: oml_mod.F90:119
integer(kind=jpim) function oml_num_threads_int(KOMP_SET_THREADS)
Definition: oml_mod.F90:270
integer(kind=jpim) function, public oml_max_threads()
Definition: oml_mod.F90:256
integer(kind=jpim) function oml_num_threads_str(CD_ENV)
Definition: oml_mod.F90:287
integer, parameter jpib
Definition: parkind1.F90:14
subroutine, public oml_init()
Definition: oml_mod.F90:111