Millepede-II  V04-00-00_preview
 All Classes Files Functions Variables Enumerator Pages
mpbits.f90
Go to the documentation of this file.
1 
12 
14 MODULE mpbits
15  USE mpdef
16  IMPLICIT NONE
17 
18  INTEGER(KIND=large) :: ndimb !< dimension for bit (field) array
19  INTEGER :: n !< matrix size
20  INTEGER :: ibfw !< bit field width
21  INTEGER :: mxcnt !< max value for bit field counters
22  INTEGER :: nencdm !< max value for column counter
23  INTEGER :: nencdb !< number of bits for encoding column counter
24  INTEGER :: nthrd !< number of threads
25  INTEGER, DIMENSION(:), ALLOCATABLE :: bitFieldCounters !< fit field counters for global parameters pairs
26 
27 END MODULE mpbits
28 
35 SUBROUTINE inbits(im,jm,inc) ! include element (I,J)
36  USE mpbits
37 
38  INTEGER, INTENT(IN) :: im
39  INTEGER, INTENT(IN) :: jm
40  INTEGER, INTENT(IN) :: inc
41 
42  INTEGER(KIND=large) :: l
43  INTEGER(KIND=large) :: ll
44  INTEGER :: i
45  INTEGER :: j
46  INTEGER :: noffj
47  INTEGER :: m
48  INTEGER :: mm
49  INTEGER :: icount
50  INTEGER :: ib
51  INTEGER :: jcount
52  INTEGER*8 :: noffi
53  LOGICAL :: btest
54 
55  IF(im == jm) return ! diagonal
56  j=min(im,jm)
57  i=max(im,jm)
58  IF(j <= 0) return ! out low
59  IF(i > n) return ! out high
60  noffi=int8(i-1)*int8(i-2)*int8(ibfw)/2 ! for J=1
61  noffj=(j-1)*ibfw
62  l=noffi/32+i+noffj/32 ! row offset + column offset
63  ! add I instead of 1 to keep bit maps of different rows in different words (openMP !)
64  m=mod(noffj,32)
65  IF (ibfw <= 1) THEN
66  bitfieldcounters(l)=ibset(bitfieldcounters(l),m)
67  ELSE
68  ! get counter from bit field
69  ll=l
70  mm=m
71  icount=0
72  DO ib=0,ibfw-1
73  IF (btest(bitfieldcounters(ll),mm)) icount=ibset(icount,ib)
74  mm=mm+1
75  IF (mm >= 32) THEN
76  ll=ll+1
77  mm=mm-32
78  END IF
79  END DO
80  ! increment
81  jcount=icount
82  icount=min(icount+inc,mxcnt)
83  ! store counter into bit field
84  IF (icount /= jcount) THEN
85  ll=l
86  mm=m
87  DO ib=0,ibfw-1
88  IF (btest(icount,ib)) THEN
89  bitfieldcounters(ll)=ibset(bitfieldcounters(ll),mm)
90  ELSE
91  bitfieldcounters(ll)=ibclr(bitfieldcounters(ll),mm)
92  END IF
93  mm=mm+1
94  IF (mm >= 32) THEN
95  ll=ll+1
96  mm=mm-32
97  END IF
98  END DO
99  END IF
100  END IF
101  return
102 
103 END SUBROUTINE inbits
104 
112 SUBROUTINE clbits(in,idimb,iencdb,jbfw)
113  USE mpbits
114  USE mpdalc
115 
116  INTEGER, INTENT(IN) :: in
117  INTEGER(KIND=large), INTENT(OUT) :: idimb
118  INTEGER, INTENT(OUT) :: iencdb
119  INTEGER, INTENT(IN) :: jbfw
120 
121  INTEGER*8 :: noffd
122  INTEGER :: i
123  INTEGER :: mb
124  INTEGER :: nbcol
125  !$ INTEGER :: OMP_GET_MAX_THREADS
126 
127  n=in
128  ibfw=jbfw
129  mxcnt=2**ibfw-1
130  noffd=int8(n)*int8(n-1)*int8(ibfw)/2
131  ndimb=noffd/32+n
132  idimb=ndimb
133  mb=int(4.0e-6*float(ndimb))
134  WRITE(*,*) ' '
135  WRITE(*,*) 'CLBITS: symmetric matrix of dimension',n
136  WRITE(*,*) 'CLBITS: off-diagonal elements',noffd
137  IF (mb > 0) THEN
138  WRITE(*,*) 'CLBITS: dimension of bit-array',ndimb , '(',mb,'MB)'
139  ELSE
140  WRITE(*,*) 'CLBITS: dimension of bit-array',ndimb , '(< 1 MB)'
141  END IF
142  CALL mpalloc(bitfieldcounters,ndimb,'INBITS: bit storage')
143  bitfieldcounters=0
144  ! encoding for compression
145  nbcol=16 ! 16 bits for column number, 16 bits for column counter
146  DO i=16,30
147  IF (btest(n,i)) nbcol=i+1 ! more bits for column number
148  END DO
149  nencdb=32-nbcol
150  iencdb=nencdb
151  nencdm=ishft(1,nencdb)-1
152  nthrd=1
153  !$ NTHRD=OMP_GET_MAX_THREADS()
154  return
155 END SUBROUTINE clbits
156 
167 SUBROUTINE ndbits(ndims,ncmprs,nsparr,mnpair,ihst,jcmprs)
168  USE mpbits
169 
170  INTEGER(KIND=large), DIMENSION(4), INTENT(OUT) :: ndims
171  INTEGER, DIMENSION(:), INTENT(OUT) :: ncmprs
172  INTEGER(KIND=large), DIMENSION(:,:), INTENT(OUT) :: nsparr
173  INTEGER, INTENT(IN) :: mnpair
174  INTEGER, INTENT(IN) :: ihst
175  INTEGER, INTENT(IN) :: jcmprs
176 
177  INTEGER :: nwcp(0:1)
178  INTEGER :: irgn(2)
179  INTEGER :: inr(2)
180  INTEGER :: ichunk
181  INTEGER :: i
182  INTEGER :: j
183  INTEGER :: jb
184  INTEGER :: m
185  INTEGER :: last
186  INTEGER :: lrgn
187  INTEGER :: next
188  INTEGER :: icp
189  INTEGER :: kbfw
190  INTEGER :: mm
191  INTEGER :: jp
192  INTEGER :: icmprs
193  INTEGER :: nj
194  INTEGER :: ib
195  INTEGER :: ir
196  INTEGER :: icount
197  INTEGER :: iproc
198  INTEGER :: jbfw
199  INTEGER :: k
200  INTEGER :: mb
201  INTEGER :: n1
202  INTEGER(KIND=large) :: ll
203  INTEGER(KIND=large) :: lb
204  INTEGER(KIND=large) :: nin
205  INTEGER(KIND=large) :: ntot
206  INTEGER*8 :: noffi
207  REAL :: cpr
208  REAL :: fracu
209  REAL :: fracz
210  LOGICAL :: btest
211  !$ INTEGER :: OMP_GET_THREAD_NUM
212  ndims(1)=ndimb
213  ndims(2)=0
214  ndims(3)=0
215  ndims(4)=0
216  ntot=0
217  icmprs=jcmprs
218  ! reduce bit field counters to bits
219  kbfw=1
220  ll=0
221  lb=0
222  ichunk=min((n+nthrd-1)/nthrd/32+1,256)
223  IF (ibfw > 1.OR.icmprs /= 0) THEN
224  IF (ibfw > 1.AND.icmprs > 0) kbfw=2 ! need to tag single precision entries
225  jbfw=kbfw ! temp. bit field width
226  IF (nthrd > 1) jbfw=ibfw ! don't mix rows in bitFieldCounters
227  ! parallelize row loop
228  ! private copy of NDIMS,NTOT for each thread, combined at end, init with 0.
229  !$OMP PARALLEL DO &
230  !$OMP PRIVATE(I,LL,MM,LB,MB,INR,IRGN,LAST,LRGN, &
231  !$OMP J,ICOUNT,NEXT,IB,ICP,NWCP,JB,JP,IR) &
232  !$OMP REDUCTION(+:NDIMS,NTOT) &
233  !$OMP SCHEDULE(DYNAMIC,ICHUNK)
234  DO i=1,n
235  noffi=int8(i-1)*int8(i-2)*int8(ibfw)/2
236  ll=noffi/32+i
237  mm=0
238  noffi=int8(i-1)*int8(i-2)*int8(jbfw)/2
239  lb=noffi/32+i
240  mb=0
241  inr(1)=0
242  inr(2)=0
243  irgn(1)=0
244  irgn(2)=0
245  last=0
246  lrgn=0
247  iproc=0
248  !$ IPROC=OMP_GET_THREAD_NUM() ! thread number
249 
250  DO j=1,i-1
251 
252  icount=0
253  next=0
254  DO ib=0,ibfw-1
255  IF (btest(bitfieldcounters(ll),mm)) icount=ibset(icount,ib)
256  mm=mm+1
257  IF (mm >= 32) THEN
258  ll=ll+1
259  mm=mm-32
260  END IF
261  END DO
262  DO jb=0,kbfw-1
263  bitfieldcounters(lb)=ibclr(bitfieldcounters(lb),mb+jb)
264  END DO
265 
266  IF (icount > 0) THEN
267  ntot=ntot+1
268  IF (iproc == 0.AND.ihst > 0) CALL hmpent(ihst,float(icount))
269  END IF
270  ! keep pair ?
271  IF (icount >= mnpair) THEN
272  next=1 ! double
273  IF (icount <= icmprs.AND.icmprs > 0) next=2 ! single
274  inr(next)=inr(next)+1
275  bitfieldcounters(lb)=ibset(bitfieldcounters(lb),mb+next-1)
276  IF (next /= last.OR.lrgn >= nencdm) THEN
277  irgn(next)=irgn(next)+1
278  lrgn=0
279  END IF
280  lrgn=lrgn+1
281  END IF
282  mb=mb+kbfw
283  IF (mb >= 32) THEN
284  lb=lb+1
285  mb=mb-32
286  END IF
287  last=next
288  END DO
289 
290  DO jp=1,kbfw
291  icp=0
292  nwcp(0)=inr(jp) ! list of column indices (default)
293  IF (inr(jp) > 0) THEN
294  nwcp(1)=irgn(jp)+(irgn(jp)+7)/8 ! list of regions of consecutive columns
295  ! compress row ?
296  IF (nwcp(1) < nwcp(0).AND.icmprs /= 0) THEN
297  icp=1
298  ncmprs(i+n*(jp-1))=irgn(jp)
299  END IF
300  ndims(2) =ndims(2) +nwcp(icp)
301  ndims(jp+2)=ndims(jp+2)+nwcp(0)
302  END IF
303  ir=i+(n+1)*(jp-1)
304  nsparr(1,ir+1)=nwcp(icp)
305  nsparr(2,ir+1)=nwcp(0)
306  END DO
307 
308  END DO
309 
310  !$OMP END PARALLEL DO
311  ! sum up, fill row offsets
312  lb=1
313  n1=0
314  ll=n+1
315  DO jp=1,kbfw
316  DO i=1,n
317  n1=n1+1
318  nsparr(1,n1)=lb
319  nsparr(2,n1)=ll
320  lb=lb+nsparr(1,n1+1)
321  ll=ll+nsparr(2,n1+1)
322  END DO
323  n1=n1+1
324  nsparr(1,n1)=lb
325  nsparr(2,n1)=ll
326  ll=1
327  END DO
328 
329  IF (jbfw /= kbfw) THEN ! move bit fields
330  DO i=1,n
331  noffi=int8(i-1)*int8(i-2)*int8(jbfw)/2
332  ll=noffi/32+i
333  noffi=int8(i-1)*int8(i-2)*int8(kbfw)/2
334  lb=noffi/32+i
335  nj=((i-1)*kbfw)/32
336  DO k=0,nj
337  bitfieldcounters(lb+k)=bitfieldcounters(ll+k)
338  END DO
339  END DO
340  END IF
341 
342  ibfw=kbfw
343  noffi=int8(n)*int8(n-1)*int8(ibfw)/2
344  ndimb=noffi/32+n
345  ndims(1)=ndimb
346 
347  ELSE
348 
349  nin=0
350  nsparr(1,1)=1
351  nsparr(2,1)=n+1
352  n1=1
353  DO i=1,n
354  noffi=int8(i-1)*int8(i-2)/2
355  ll=noffi/32+i
356  nj=((i-1)*kbfw)/32
357  DO k=0,nj
358  DO m=0,31
359  IF(btest(bitfieldcounters(ll+k),m)) nin=nin+1
360  END DO
361  END DO
362  n1=n1+1
363  nsparr(1,n1)=nsparr(1,1)+nin
364  nsparr(2,n1)=nsparr(2,1)+nin
365  END DO
366  ndims(2)=nin
367  ndims(3)=nin
368  ntot=nin
369 
370  END IF
371 
372  nin=ndims(3)+ndims(4)
373  fracz=200.0*float(ntot)/float(n)/float(n-1)
374  fracu=200.0*float(nin)/float(n)/float(n-1)
375  WRITE(*,*) ' '
376  WRITE(*,*) 'NDBITS: number of diagonal elements',n
377  WRITE(*,*) 'NDBITS: number of used off-diagonal elements',nin
378  WRITE(*,1000) 'fraction of non-zero off-diagonal elements', fracz
379  WRITE(*,1000) 'fraction of used off-diagonal elements', fracu
380  IF (icmprs /= 0) THEN
381  cpr=100.0*float(ndims(2)+2*ndims(3)+ndims(4))/float(3*nin)
382  WRITE(*,1000) 'compression ratio for off-diagonal elements', cpr
383  END IF
384 1000 format(' NDBITS: ',a,f6.2,' %')
385  return
386 END SUBROUTINE ndbits
387 
395 SUBROUTINE ckbits(ndims,mnpair,jcmprs)
396  USE mpbits
397 
398  INTEGER(KIND=large), DIMENSION(4), INTENT(OUT) :: ndims
399  INTEGER, INTENT(IN) :: mnpair
400  INTEGER, INTENT(IN) :: jcmprs
401 
402  INTEGER :: nwcp(0:1)
403  INTEGER :: irgn(2)
404  INTEGER :: inr(2)
405  INTEGER(KIND=large) :: ll
406  INTEGER*8 :: noffi
407  INTEGER :: i
408  INTEGER :: j
409  INTEGER :: last
410  INTEGER :: lrgn
411  INTEGER :: next
412  INTEGER :: icp
413  INTEGER :: ib
414  INTEGER :: icount
415  INTEGER :: icmprs
416  INTEGER :: kbfw
417  INTEGER :: jp
418  INTEGER :: mm
419  LOGICAL :: btest
420 
421  DO i=1,4
422  ndims(i)=0
423  END DO
424  icmprs=jcmprs
425  kbfw=1
426  IF (ibfw > 1.AND.icmprs > 0) kbfw=2
427  ll=0
428 
429  DO i=1,n
430  noffi=int8(i-1)*int8(i-2)*int8(ibfw)/2
431  ll=noffi/32+i
432  mm=0
433  inr(1)=0
434  inr(2)=0
435  irgn(1)=0
436  irgn(2)=0
437  last=0
438  lrgn=0
439  DO j=1,i-1
440  icount=0
441  next=0
442  DO ib=0,ibfw-1
443  IF (btest(bitfieldcounters(ll),mm)) icount=ibset(icount,ib)
444  mm=mm+1
445  IF (mm >= 32) THEN
446  ll=ll+1
447  mm=mm-32
448  END IF
449  END DO
450 
451  IF (icount > 0) ndims(1)=ndims(1)+1
452  ! keep pair ?
453  IF (icount >= mnpair) THEN
454  next=1 ! double
455  IF (icount <= icmprs.AND.icmprs > 0) next=2 ! single
456  inr(next)=inr(next)+1
457  IF (next /= last.OR.lrgn >= nencdm) THEN
458  irgn(next)=irgn(next)+1
459  lrgn=0
460  END IF
461  lrgn=lrgn+1
462  END IF
463  last=next
464  END DO
465 
466  IF (icmprs /= 0) THEN
467  DO jp=1,kbfw
468  IF (inr(jp) > 0) THEN
469  icp=0
470  nwcp(0)=inr(jp) ! list of column indices (default)
471  nwcp(1)=irgn(jp)+(irgn(jp)+7)/8 ! list of regions of consecutive columns
472  ! compress row ?
473  IF (nwcp(1) < nwcp(0)) icp=1
474  ndims(2) =ndims(2) +nwcp(icp)
475  ndims(jp+2)=ndims(jp+2)+nwcp(0)
476  END IF
477  END DO
478  ELSE
479  ndims(2)=ndims(2)+inr(1)
480  ndims(3)=ndims(3)+inr(1)
481  END IF
482 
483  END DO
484 
485  return
486 END SUBROUTINE ckbits
487 
494 SUBROUTINE spbits(nsparr,nsparc,ncmprs) ! collect elements
495  USE mpbits
496  USE mpdalc
497 
498  INTEGER(KIND=large), DIMENSION(:,:), INTENT(IN) :: nsparr
499  INTEGER, DIMENSION(:), INTENT(OUT) :: nsparc
500  INTEGER, DIMENSION(:), INTENT(IN) :: ncmprs
501 
502  INTEGER(KIND=large) :: kl
503  INTEGER(KIND=large) :: l
504  INTEGER(KIND=large) :: ll
505  INTEGER(KIND=large) :: l1
506  INTEGER(KIND=large) :: k8
507  INTEGER(KIND=large) :: n1
508  INTEGER*8 :: noffi
509  INTEGER :: i
510  INTEGER :: j
511  INTEGER :: j1
512  INTEGER :: jb
513  INTEGER :: jn
514  INTEGER :: m
515  INTEGER :: ichunk
516  INTEGER :: next
517  INTEGER :: last
518  INTEGER :: lrgn
519  INTEGER :: nrgn
520  INTEGER :: nrgn8
521  LOGICAL :: btest
522 
523  ichunk=min((n+nthrd-1)/nthrd/32+1,256)
524 
525  DO jb=0,ibfw-1
526  ! parallelize row loop
527  !$OMP PARALLEL DO &
528  !$OMP PRIVATE(I,N1,NOFFI,L,M,KL,L1,NRGN,NRGN8,K8, &
529  !$OMP LAST,LRGN,LL,J1,JN,J,NEXT) &
530  !$OMP SCHEDULE(DYNAMIC,ICHUNK)
531  DO i=1,n
532  n1=i+jb*(n+1)
533  noffi=int8(i-1)*int8(i-2)*int8(ibfw)/2
534  l=noffi/32+i
535  m=jb
536  kl=nsparr(1,n1)-1 ! pointer to row in NSPARC
537  l1=nsparr(2,n1) ! pointer to row in sparse matrix
538  nrgn=ncmprs(i+n*jb)! compression (number of consecutive regions)
539  nrgn8=(nrgn+7)/8 ! number of groups (1 offset per group)
540  k8=kl
541  kl=kl+nrgn8 ! reserve space of offsets
542  last=0
543  lrgn=0
544  ll=l1-1
545  j1=0
546  jn=0
547 
548  DO j=1,i-1 ! loop for off-diagonal elements
549  next=0
550  IF(bitfieldcounters(l) /= 0) THEN
551  IF(btest(bitfieldcounters(l),m)) THEN
552  ll=ll+1
553  IF (nrgn <= 0) THEN
554  kl=kl+1
555  nsparc(kl)=j ! column index
556  ELSE
557  next=1
558  IF (last == 0.OR.jn >= nencdm) THEN
559  IF (mod(lrgn,8) == 0) THEN
560  k8=k8+1
561  nsparc(k8)=int(ll-l1)
562  END IF
563  lrgn=lrgn+1
564  kl=kl+1
565  j1=ishft(j,nencdb)
566  jn=0
567  END IF
568  jn=jn+1
569  nsparc(kl)=ior(j1,jn)
570  END IF
571  END IF
572  END IF
573  last=next
574  m=m+ibfw
575  IF (m >= 32) THEN
576  m=m-32
577  l=l+1
578  END IF
579 
580  END DO
581  END DO
582  !$OMP END PARALLEL DO
583 
584  END DO
585 
586  n1=(n+1)*ibfw
587  WRITE(*,*) ' '
588  WRITE(*,*) 'SPBITS: sparse structure constructed ',nsparr(1,n1), ' words'
589  WRITE(*,*) 'SPBITS: dimension parameter of matrix',nsparr(2,1)-1
590  IF (ibfw <= 1) THEN
591  WRITE(*,*) 'SPBITS: index of last used location',nsparr(2,n1)-1
592  ELSE
593  WRITE(*,*) 'SPBITS: index of last used double',nsparr(2,n1/2)-1
594  WRITE(*,*) 'SPBITS: index of last used single',nsparr(2,n1)-1
595  END IF
596  CALL mpdealloc(bitfieldcounters)
597  return
598 END SUBROUTINE spbits
599 
600