SURFEX v8.1
General documentation of Surfex
ecsort_mix.F90
Go to the documentation of this file.
1 #ifdef RS6K
2 @process nocheck
3 #endif
4 MODULE ecsort_mix
5 USE parkind1 , ONLY : jpim ,jpib ,jprb ,jprm ,jprd
6 USE yomhook , ONLY : lhook, dr_hook
8 USE strhandler_mod , ONLY : toupper
9 #ifdef SFX_MPI
10 USE mpl_module , ONLY : mpl_myrank, mpl_nproc
11 #endif
12 
13 !$
14 !.. Author: Sami Saarinen, ECMWF, 10/02/98
15 ! Fixes : Sami Saarinen, ECMWF, 08/11/99 : Sub-arrays go now correctly (look for addrdiff)
16 ! Genuine real(4) sort "re-habilitated"
17 ! sizeof_int, _real4 & _real8 HARDCODED !
18 ! Sami Saarinen, ECMWF, 11/10/00 : REAL*4 version included (REAL_M)
19 ! Sami Saarinen, ECMWF, 28/11/03 : Calls to DR_HOOK added manually (on top of CY28)
20 ! Sami Saarinen, ECMWF, 18/02/05 : 64-bit integer sorting introduced (for CY30)
21 ! Sami Saarinen, ECMWF, 22/02/05 : Using genuine 64-bit rsort64() => one-pass through data
22 ! Sami Saarinen, ECMWF, 06/07/05 : "current_method" made OpenMP-thread aware (for max. # of threads = NTHRDS)
23 ! Sami Saarinen, ECMWF, 07/07/05 : Quick-sort method finally arrived (and applicable to multikeys, too)
24 ! Quick-sort the default for scalar machines ("non-VPP"), VPPs is radix-sort
25 ! Sami Saarinen, ECMWF, 03/07/07 : Quick-sort method uses stable approach (was not guaranteed so before)
26 ! Sami Saarinen, ECMWF, 15/10/07 : Subroutines put into a common file ../include/ecsort_shared.h and
27 ! preprocessed from there
28 ! Sami Saarinen, ECMWF, 15/10/07 : NTHRDS increased from 32 to 64
29 ! Sami Saarinen, ECMWF, 16/10/07 : The default sorting method can be overriden via export EC_SORTING_METHOD=[<number>|<string>]
30 ! Sami Saarinen, ECMWF, 30/10/07 : Support for CountingSort added as part of QuickSort speedup
31 ! Sami Saarinen, ECMWF, 31/10/07 : CALL SORTING_METHOD() now prints the prevailing method from EC_SORTING_METHOD
32 ! Sami Saarinen, ECMWF, 01/11/07 : CountingSort implemented as independent method
33 ! Sami Saarinen, ECMWF, 06/11/07 : index_adj added as an optional argument to init_index ; new routine adjust_index()
34 ! Sami Saarinen, ECMWF, 07/11/07 : threshold length "nomp" (see below). Override with EC_SORTING_NOMP.
35 ! Sami Saarinen, ECMWF, 12/11/07 : Gnome-sort -- the easiest sort on Earth (and very slow for large arrays)
36 ! Sami Saarinen, ECMWF, 15/11/07 : OpenMP-sorting still under development. Do NOT override the EC_SORTING_NOMP yet.
37 ! Sami Saarinen, ECMWF, 05/12/07 : When export EC_SORTING_INFO=0, then no info messages are printed from CALL sorting_method()
38 ! Sami Saarinen, ECMWF, 20/12/07 : export EC_SORTING_INFO=0, rather than =1 is now the default --> less hassling output
39 
40 
41 IMPLICIT NONE
42 SAVE
43 PRIVATE
44 
45 INTEGER(KIND=JPIM), PARAMETER :: nthrds = 64 ! ***Note: A hardcoded max number of threads !!!
46 
47 INTEGER(KIND=JPIM), PARAMETER :: sizeof_int4 = 4
48 INTEGER(KIND=JPIM), PARAMETER :: sizeof_int8 = 8
49 INTEGER(KIND=JPIM), PARAMETER :: sizeof_real4 = 4
50 INTEGER(KIND=JPIM), PARAMETER :: sizeof_real8 = 8
51 
52 INTEGER(KIND=JPIM), PARAMETER :: min_method = 1
53 INTEGER(KIND=JPIM), PARAMETER :: max_method = 5
54 
55 INTEGER(KIND=JPIM), PARAMETER :: radixsort_method = 1
56 INTEGER(KIND=JPIM), PARAMETER :: heapsort_method = 2
57 INTEGER(KIND=JPIM), PARAMETER :: quicksort_method = 3
58 INTEGER(KIND=JPIM), PARAMETER :: countingsort_method = 4
59 INTEGER(KIND=JPIM), PARAMETER :: gnomesort_method = 5
60 
61 CHARACTER(LEN=12), PARAMETER :: method_name(min_method:max_method) = &
62  & (/&
63  & 'RADIXSORT ' &
64  & ,'HEAPSORT ' &
65  & ,'QUICKSORT ' &
66  & ,'COUNTINGSORT' &
67  & ,'GNOMESORT ' &
68  & /)
69 
70 !-- Select such method for default_method, which also works for multikey sorts
71 ! Vector machines should choose radixsort_method, others quicksort_method (oh, sorry, countingsort_method!)
72 !
73 ! Note: Occasionally radixsort_method may be faster on non-vector machines, too
74 #if defined(VPP) || defined(NECSX)
75 INTEGER(KIND=JPIM) :: default_method = radixsort_method
76 INTEGER(KIND=JPIM) :: current_method(nthrds) = radixsort_method
77 #else
78 INTEGER(KIND=JPIM) :: default_method = countingsort_method
79 INTEGER(KIND=JPIM) :: current_method(nthrds) = countingsort_method
80 #endif
81 
82 !-- A threshold length after which OpenMP in sorting, merging, copying may kick in.
83 ! Override with EC_SORTING_NOMP. Detected while initializing/calling SORTING_METHOD
84 ! Non-positive values (<= 0) indicate that OpenMP will NOT be attempted at all
85 INTEGER(KIND=JPIM) :: nomp = -1
86 
87 !-- EC_SORTING_INFO = MPL-proc id [1..$NPES] to print the info message when CALL sorting_method()
88 ! : 0 (no print; the default)
89 ! : 1 (print on MPL-task one)
90 ! : > 1 and <= $NPES (some other MPL-task than 1 prints)
91 INTEGER(KIND=JPIM) :: nsinfo = 0
92 
93 INTERFACE keysort
94 MODULE PROCEDURE &
95  &int4_keysort_1d, int4_keysort_2d, &
96  &int8_keysort_1d, int8_keysort_2d, &
97  &real8_keysort_1d, real8_keysort_2d, &
98  &real4_keysort_1d, real4_keysort_2d
99 END INTERFACE
100 
101 INTERFACE sorting_method
102 MODULE PROCEDURE int_sorting_method, str_sorting_method
103 END INTERFACE
104 
105 PUBLIC :: keysort
106 PUBLIC :: init_index, get_rank, adjust_index
107 PUBLIC :: sorting_method
108 
109 CONTAINS
110 
111 !----------------------------
112 !-- Public subroutines --
113 !----------------------------
114 
115 SUBROUTINE int_sorting_method(INEW, IOLD)
116 INTEGER(KIND=JPIM), OPTIONAL, INTENT(IN) :: INEW
117 INTEGER(KIND=JPIM), OPTIONAL, INTENT(OUT) :: IOLD
118 INTEGER(KIND=JPIM) :: ITMP, IMYPROC, INPES
119 INTEGER(KIND=JPIM) :: ITID
120 CHARACTER(LEN=20) CLENV
121 LOGICAL, SAVE :: LLFIRST = .true.
122 LOGICAL LLOMP, LLHOOK_OK
123 REAL(KIND=JPRB) :: ZHOOK_HANDLE
124 !-- This maybe called from the very first call of DR_HOOK_UTIL ...
125 llhook_ok = lhook .AND. (PRESENT(inew) .OR. PRESENT(iold))
126 IF (llhook_ok) CALL dr_hook('ECSORT_MIX:INT_SORTING_METHOD',0,zhook_handle)
127 itid = oml_my_thread()
128 llomp = oml_in_parallel()
129 IF (PRESENT(iold)) iold = current_method(itid)
130 itmp = -1
131 IF (PRESENT(inew)) THEN
132  itmp = inew
133 ELSE IF (.NOT.llomp) THEN ! Override the default method (only if outside the OpenMP)
134  itmp = -1 ! no change
135  IF (llfirst) THEN ! Do once per execution only
136 #ifdef SFX_MPI
137  inpes = mpl_nproc()
138 #else
139  inpes = 1
140 #endif
141  CALL get_environment_variable('EC_SORTING_INFO',clenv) ! ../support/env.c
142  IF (clenv /= ' ') THEN
143  itmp = nsinfo
144  READ(clenv,'(i20)',end=89,err=89) itmp
145  GOTO 88
146 89 CONTINUE
147  itmp = nsinfo ! no change
148 88 CONTINUE
149  IF (itmp <= 0) THEN
150  nsinfo = 0
151  ELSE IF (itmp >= 1 .AND. itmp <= inpes) THEN
152  nsinfo = itmp
153  ENDIF
154  ENDIF
155 #ifdef SFX_MPI
156  imyproc = mpl_myrank()
157 #else
158  imyproc = 0
159 #endif
160  CALL get_environment_variable('EC_SORTING_METHOD',clenv) ! ../support/env.c
161  IF (clenv /= ' ') THEN
162  IF (imyproc == nsinfo) WRITE(0,'(a)')'<EC_SORTING_METHOD='//trim(clenv)
163  CALL toupper(clenv)
164  SELECT CASE (clenv)
165  CASE ('RADIX', 'RADIXSORT')
166  itmp = radixsort_method
167  CASE ('HEAP', 'HEAPSORT')
168  itmp = heapsort_method
169  CASE ('QUICK', 'QUICKSORT', 'QSORT')
170  itmp = quicksort_method
171  CASE ('COUNT', 'COUNTINGSORT', 'COUNTSORT')
172  itmp = countingsort_method
173  CASE ('GNOME', 'GNOMESORT')
174  itmp = gnomesort_method
175  CASE ('DEFAULT', 'DEF')
176  itmp = -1 ! no change
177  CASE DEFAULT
178  READ(clenv,'(i20)',end=99,err=99) itmp
179  GOTO 98
180 99 CONTINUE
181  itmp = -1 ! no change
182 98 CONTINUE
183  END SELECT
184  ENDIF
185 
186  IF (itmp < min_method .OR. itmp > max_method) itmp = default_method
187  default_method = itmp
188  current_method(:) = itmp
189  IF (imyproc == nsinfo) &
190  & WRITE(0,'(a,i1,a)')'>EC_SORTING_METHOD=',default_method,&
191  & ' # '//method_name(default_method)
192 
193  CALL get_environment_variable('EC_SORTING_NOMP',clenv)
194  IF (clenv /= ' ') THEN
195  IF (imyproc == nsinfo) WRITE(0,'(a)')'<EC_SORTING_NOMP='//trim(clenv)
196  READ(clenv,'(i20)',end=199,err=199) itmp
197  GOTO 198
198 199 CONTINUE
199  itmp = nomp ! no change
200 198 CONTINUE
201  nomp = itmp
202  ENDIF
203 
204  IF (imyproc == nsinfo) THEN
205  WRITE(clenv,'(i20)') nomp
206  WRITE(0,'(a)')'>EC_SORTING_NOMP='//trim(adjustl(clenv))
207  ENDIF
208 
209  itmp = default_method
210  llfirst = .false.
211  ENDIF
212 ENDIF
213 
214 IF (itmp < min_method .OR. itmp > max_method) itmp = default_method
215 IF (llomp) THEN ! Only this thread sees the change
216  current_method(itid) = itmp
217 ELSE ! All threads see the change
218  current_method(:) = itmp
219 ENDIF
220 IF (llhook_ok) CALL dr_hook('ECSORT_MIX:INT_SORTING_METHOD',1,zhook_handle)
221 END SUBROUTINE int_sorting_method
222 
223 
224 SUBROUTINE str_sorting_method(CDNEW, IOLD)
225 CHARACTER(LEN=*), INTENT(IN) :: CDNEW
226 INTEGER(KIND=JPIM), OPTIONAL, INTENT(OUT) :: IOLD
227 CHARACTER(LEN=LEN(CDNEW)) CLNEW
228 REAL(KIND=JPRB) :: ZHOOK_HANDLE
229 IF (lhook) CALL dr_hook('ECSORT_MIX:STR_SORTING_METHOD',0,zhook_handle)
230 clnew = cdnew
231 CALL toupper(clnew)
232 SELECT CASE (clnew)
233 CASE ('RADIX', 'RADIXSORT')
234  CALL sorting_method(radixsort_method, iold)
235 CASE ('HEAP', 'HEAPSORT')
236  CALL sorting_method(heapsort_method, iold)
237 CASE ('QUICK', 'QUICKSORT', 'QSORT')
238  CALL sorting_method(quicksort_method, iold)
239 CASE ('COUNT', 'COUNTINGSORT', 'COUNTSORT')
241 CASE ('GNOME', 'GNOMESORT')
242  CALL sorting_method(gnomesort_method, iold)
243 CASE ('DEFAULT', 'DEF')
244  CALL sorting_method(default_method, iold)
245 CASE DEFAULT
246  CALL sorting_method(default_method, iold)
247 END SELECT
248 IF (lhook) CALL dr_hook('ECSORT_MIX:STR_SORTING_METHOD',1,zhook_handle)
249 END SUBROUTINE str_sorting_method
250 
251 
252 SUBROUTINE init_index(INDEX, INDEX_ADJ)
253 INTEGER(KIND=JPIM), INTENT(OUT):: INDEX(:)
254 INTEGER(KIND=JPIM), INTENT(IN), OPTIONAL :: INDEX_ADJ
255 INTEGER(KIND=JPIM) :: I, N
256 REAL(KIND=JPRB) :: ZHOOK_HANDLE
257 IF (lhook) CALL dr_hook('ECSORT_MIX:INIT_INDEX',0,zhook_handle)
258 n = SIZE(index)
259 IF (PRESENT(index_adj)) THEN
260  DO i=1,n
261  index(i) = i + index_adj
262  ENDDO
263 ELSE
264  DO i=1,n
265  index(i) = i
266  ENDDO
267 ENDIF
268 IF (lhook) CALL dr_hook('ECSORT_MIX:INIT_INDEX',1,zhook_handle)
269 END SUBROUTINE init_index
270 
271 
272 SUBROUTINE adjust_index(INDEX, INDEX_ADJ)
273 INTEGER(KIND=JPIM), INTENT(INOUT):: INDEX(:)
274 INTEGER(KIND=JPIM), INTENT(IN) :: INDEX_ADJ
275 INTEGER(KIND=JPIM) :: I, N
276 REAL(KIND=JPRB) :: ZHOOK_HANDLE
277 IF (lhook) CALL dr_hook('ECSORT_MIX:ADJUST_INDEX',0,zhook_handle)
278 IF (index_adj /= 0) THEN
279  n = SIZE(index)
280  DO i=1,n
281  index(i) = index(i) + index_adj
282  ENDDO
283 ENDIF
284 IF (lhook) CALL dr_hook('ECSORT_MIX:ADJUST_INDEX',1,zhook_handle)
285 END SUBROUTINE adjust_index
286 
287 
288 SUBROUTINE get_rank(INDEX, RANK, INDEX_ADJ)
289 INTEGER(KIND=JPIM), INTENT(IN) :: INDEX(:)
290 INTEGER(KIND=JPIM), INTENT(OUT):: RANK(:)
291 INTEGER(KIND=JPIM), INTENT(IN), OPTIONAL :: INDEX_ADJ
292 INTEGER(KIND=JPIM) :: I, N
293 REAL(KIND=JPRB) :: ZHOOK_HANDLE
294 IF (lhook) CALL dr_hook('ECSORT_MIX:GET_RANK',0,zhook_handle)
295 n = min(SIZE(index),SIZE(rank))
296 IF (PRESENT(index_adj)) THEN
297  DO i=1,n
298  rank(index(i)+index_adj) = i
299  ENDDO
300 ELSE
301  DO i=1,n
302  rank(index(i)) = i
303  ENDDO
304 ENDIF
305 IF (lhook) CALL dr_hook('ECSORT_MIX:GET_RANK',1,zhook_handle)
306 END SUBROUTINE get_rank
307 
308 
309 #undef INT_VERSION
310 #undef REAL_VERSION
311 
312 !-- Create version for INTEGER(KIND=JPIM)
313 #define INT_VERSION 4
314 #define REAL_VERSION 0
315 #include "ecsort_shared.h"
316 #undef INT_VERSION
317 #undef REAL_VERSION
318 
319 !-- Create version for INTEGER(KIND=JPIB)
320 #define INT_VERSION 8
321 #define REAL_VERSION 0
322 #include "ecsort_shared.h"
323 #undef INT_VERSION
324 #undef REAL_VERSION
325 
326 !-- Create version for REAL(KIND=JPRM)
327 #define INT_VERSION 0
328 #define REAL_VERSION 4
329 #include "ecsort_shared.h"
330 #undef INT_VERSION
331 #undef REAL_VERSION
332 
333 !-- Create version for REAL(KIND=JPRB)
334 #define INT_VERSION 0
335 #define REAL_VERSION 8
336 #include "ecsort_shared.h"
337 #undef INT_VERSION
338 #undef REAL_VERSION
339 
340 END MODULE ecsort_mix
integer(kind=jpim), parameter quicksort_method
Definition: ecsort_mix.F90:57
static const char * trim(const char *name, int *n)
Definition: drhook.c:2383
subroutine str_sorting_method(CDNEW, IOLD)
Definition: ecsort_mix.F90:225
integer, parameter jpim
Definition: parkind1.F90:13
integer, parameter jprd
Definition: parkind1.F90:39
integer(kind=jpim), parameter gnomesort_method
Definition: ecsort_mix.F90:59
integer(kind=jpim), parameter nthrds
Definition: ecsort_mix.F90:45
integer(kind=jpim), parameter sizeof_int4
Definition: ecsort_mix.F90:47
subroutine, public init_index(INDEX, INDEX_ADJ)
Definition: ecsort_mix.F90:253
integer(kind=jpim), parameter min_method
Definition: ecsort_mix.F90:52
integer(kind=jpim), parameter sizeof_int8
Definition: ecsort_mix.F90:48
character(len=12), dimension(min_method:max_method), parameter method_name
Definition: ecsort_mix.F90:61
subroutine, public adjust_index(INDEX, INDEX_ADJ)
Definition: ecsort_mix.F90:273
logical function, public oml_in_parallel()
Definition: oml_mod.F90:125
integer(kind=jpim), parameter heapsort_method
Definition: ecsort_mix.F90:56
integer(kind=jpim), parameter sizeof_real8
Definition: ecsort_mix.F90:50
integer, parameter jprb
Definition: parkind1.F90:32
integer(kind=jpim), parameter max_method
Definition: ecsort_mix.F90:53
integer(kind=jpim), parameter sizeof_real4
Definition: ecsort_mix.F90:49
subroutine, public get_rank(INDEX, RANK, INDEX_ADJ)
Definition: ecsort_mix.F90:289
integer, parameter jprm
Definition: parkind1.F90:30
integer(kind=jpim) function, public oml_my_thread()
Definition: oml_mod.F90:249
logical lhook
Definition: yomhook.F90:15
integer(kind=jpim), parameter radixsort_method
Definition: ecsort_mix.F90:55
integer(kind=jpim) nsinfo
Definition: ecsort_mix.F90:91
subroutine, public toupper(CDS)
integer(kind=jpim) function, public oml_max_threads()
Definition: oml_mod.F90:256
integer(kind=jpim), dimension(nthrds) current_method
Definition: ecsort_mix.F90:76
quick &counting sorts only inumt inumt nomp
integer, parameter jpib
Definition: parkind1.F90:14
integer(kind=jpim) default_method
Definition: ecsort_mix.F90:75
subroutine int_sorting_method(INEW, IOLD)
Definition: ecsort_mix.F90:116
integer(kind=jpim), parameter countingsort_method
Definition: ecsort_mix.F90:58