Line data Source code
1 : !!****m* ABINIT/m_FFT_prof
2 : !! NAME
3 : !! m_FFT_prof
4 : !!
5 : !! COPYRIGHT
6 : !! Copyright (C) 2008-2026 ABINIT group (MG)
7 : !! This file is distributed under the terms of the
8 : !! GNU General Public License, see ~abinit/COPYING
9 : !! or http://www.gnu.org/copyleft/gpl.txt .
10 : !!
11 : !! SOURCE
12 :
13 : #if defined HAVE_CONFIG_H
14 : #include "config.h"
15 : #endif
16 :
17 : #include "abi_common.h"
18 :
19 : module m_FFT_prof
20 :
21 : use defs_basis
22 : use m_xomp
23 : use m_errors
24 : use m_abicore
25 : use m_fftw3
26 : use m_fft
27 : use m_distribfft
28 :
29 : use defs_abitypes, only : MPI_type
30 : use m_fstrings, only : sjoin, itoa
31 : use m_numeric_tools, only : arth
32 : use m_time, only : cwtime
33 : use m_io_tools, only : open_file
34 : use m_geometry, only : metric
35 : use m_hide_blas, only : xcopy
36 : use m_cgtools, only : set_istwfk
37 : use m_fftcore, only : get_kg, print_ngfft, fftalg_info, kgindex, getng, sphereboundary
38 : use m_fft_mesh, only : calc_eigr, calc_ceigr
39 : use m_mpinfo, only : nullify_mpi_enreg, destroy_mpi_enreg, copy_mpi_enreg, initmpi_seq
40 : use m_oscillators, only : rho_tw_g
41 :
42 : implicit none
43 :
44 : private
45 :
46 : integer,private,parameter :: TNAME_LEN=100
47 : !!***
48 :
49 : !----------------------------------------------------------------------
50 :
51 : public :: fftprof_ncalls_per_test
52 :
53 : ! Routines for benchmarking
54 : public :: prof_fourdp
55 : public :: prof_fourwf
56 : public :: prof_rhotwg
57 :
58 : !----------------------------------------------------------------------
59 :
60 : !!****t* m_fft_mesh/FFT_test_t
61 : !! NAME
62 : !! FFT_test_t
63 : !!
64 : !! FUNCTION
65 : !! Parameters passed to the FFT routines used in abinit (fourdp|fourwf).
66 : !!
67 : !! SOURCE
68 :
69 : type, public :: FFT_test_t
70 :
71 : integer :: available = 0
72 : integer :: istwf_k = -1
73 : integer :: mgfft = -1
74 : integer :: ndat = -1
75 : integer :: nfft = -1
76 : integer :: nthreads = 1
77 : integer :: npw_k = -1
78 : integer :: npw_kout = -1
79 : integer :: paral_kgb = -1
80 : integer :: gpu_option = 0
81 :
82 : real(dp) :: ecut=zero
83 : integer :: ngfft(18)=-1
84 :
85 : real(dp) :: kpoint(3) = [zero,zero,zero]
86 : real(dp) :: rprimd(3,3),rmet(3,3)
87 : real(dp) :: gprimd(3,3),gmet(3,3)
88 :
89 : integer,allocatable :: kg_k(:,:)
90 : integer,allocatable :: kg_kout(:,:)
91 : integer,allocatable :: indpw_k(:)
92 :
93 : type(MPI_type) :: MPI_enreg
94 :
95 : contains
96 : procedure :: init => fft_test_init
97 : procedure :: free => fft_test_free_0D
98 : procedure :: print => fft_test_print
99 : procedure :: get_name
100 :
101 : ! Timing routines.
102 : procedure :: time_fourdp
103 : procedure :: time_fftbox
104 : procedure :: time_fourwf
105 : procedure :: time_rhotwg
106 : procedure :: time_fftu
107 : end type FFT_test_t
108 :
109 : public :: fft_tests_free
110 :
111 : interface fft_tests_free
112 : module procedure fft_test_free_0D
113 : module procedure fft_test_free_1D
114 : end interface fft_tests_free
115 : !!***
116 :
117 : !----------------------------------------------------------------------
118 :
119 : !!****t* m_fft_mesh/FFT_prof_t
120 : !! NAME
121 : !! FFT_prof_t
122 : !!
123 : !! FUNCTION
124 : !! The results of the tests
125 : !!
126 : !! SOURCE
127 :
128 : type,public :: FFT_prof_t
129 : integer :: ncalls
130 : integer :: ndat
131 : integer :: gpu_option
132 : integer :: nthreads
133 : real(dp) :: cpu_time
134 : real(dp) :: wall_time
135 : real(dp) :: gflops
136 : character(len=TNAME_LEN) :: test_name
137 : complex(dp),allocatable :: results(:)
138 :
139 : contains
140 : procedure :: init => fftprof_init
141 : procedure :: free => fftprof_free_0D
142 : end type FFT_prof_t
143 :
144 : public :: fftprofs_free
145 : public :: fftprofs_print
146 :
147 : interface fftprofs_free
148 : module procedure fftprof_free_0D
149 : module procedure fftprof_free_1D
150 : end interface fftprofs_free
151 : !!***
152 :
153 : !----------------------------------------------------------------------
154 : ! Number of calls of each FFT algo, used to have a betters statistics for timing.
155 : integer,save,private :: NCALLS_FOR_TEST=10
156 :
157 : integer,private,parameter :: CACHE_KBSIZE=0
158 : ! Argument of empty_cache. Set it to zero if the cache should not be emptied.
159 :
160 : CONTAINS !====================================================================
161 : !!***
162 :
163 : !----------------------------------------------------------------------
164 :
165 : !!****f* m_FFT_prof/fft_test_init
166 : !! NAME
167 : !! fft_test_init
168 : !!
169 : !! FUNCTION
170 : !! Creation method for the FFT_test_t structured datatype.
171 : !!
172 : !! INPUTS
173 : !!
174 : !! OUTPUT
175 : !!
176 : !! SOURCE
177 :
178 98 : subroutine fft_test_init(Ftest, fft_setup, kpoint, ecut, boxcutmin, rprimd, nsym, symrel, MPI_enreg_in)
179 :
180 : !Arguments -----------------------------------
181 : !scalars
182 : class(FFT_test_t),intent(inout) :: Ftest
183 : integer,intent(in) :: nsym
184 : real(dp),intent(in) :: ecut,boxcutmin
185 : class(MPI_type),intent(in) :: MPI_enreg_in
186 : !arrays
187 : integer,intent(in) :: fft_setup(6),symrel(3,3,nsym)
188 : real(dp),intent(in) :: kpoint(3),rprimd(3,3)
189 :
190 : !Local variables-------------------------------
191 : !scalars
192 : integer :: fftalg,fftcache,ndat
193 : real(dp) :: ucvol
194 : !arrays
195 98 : logical,allocatable :: mask(:)
196 : real(dp),parameter :: k0(3)=zero
197 : real(dp) :: gmet(3,3),gprimd(3,3),rmet(3,3)
198 98 : real(dp),allocatable :: tnons(:,:)
199 : ! *************************************************************************
200 :
201 98 : call nullify_mpi_enreg(Ftest%MPI_enreg)
202 :
203 98 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
204 :
205 1274 : Ftest%rprimd = rprimd
206 1274 : Ftest%rmet = rmet
207 1274 : Ftest%gprimd = gprimd
208 1274 : Ftest%gmet = gmet
209 98 : Ftest%ecut = ecut
210 :
211 98 : fftalg = fft_setup(1)
212 98 : fftcache = fft_setup(2)
213 98 : ndat = fft_setup(3)
214 98 : Ftest%nthreads = fft_setup(4)
215 98 : Ftest%available = fft_setup(5)
216 98 : Ftest%gpu_option = fft_setup(6)
217 :
218 98 : Ftest%paral_kgb = 0
219 392 : Ftest%kpoint = kpoint
220 98 : Ftest%ndat = ndat
221 :
222 98 : Ftest%istwf_k = set_istwfk(kpoint)
223 :
224 98 : call get_kg(Ftest%kpoint,Ftest%istwf_k,ecut,gmet,Ftest%npw_k,Ftest%kg_k)
225 98 : call get_kg(Ftest%kpoint,Ftest%istwf_k,ecut,gmet,Ftest%npw_kout,Ftest%kg_kout)
226 :
227 98 : call copy_mpi_enreg(MPI_enreg_in,Ftest%MPI_enreg)
228 :
229 98 : Ftest%ngfft(7) = fftalg
230 98 : Ftest%ngfft(8) = fftcache
231 :
232 : ! Fill part of ngfft
233 686 : ABI_CALLOC(tnons,(3,nsym))
234 :
235 : call getng(boxcutmin,0,ecut,gmet,k0,Ftest%MPI_enreg%me_fft,Ftest%mgfft,Ftest%nfft,Ftest%ngfft,Ftest%MPI_enreg%nproc_fft,nsym,&
236 98 : Ftest%MPI_enreg%paral_kgb,symrel,tnons, unit=dev_null, gpu_option=ftest%gpu_option)
237 :
238 98 : ABI_FREE(tnons)
239 :
240 98 : call Ftest%MPI_enreg%distribfft%init('c',Ftest%MPI_enreg%nproc_fft,Ftest%ngfft(2),Ftest%ngfft(3))
241 :
242 : ! Compute the index of each plane wave in the FFT grid.
243 294 : ABI_MALLOC(Ftest%indpw_k,(Ftest%npw_k))
244 :
245 196 : ABI_MALLOC(mask,(Ftest%npw_k))
246 98 : call kgindex(Ftest%indpw_k,Ftest%kg_k,mask,Ftest%MPI_enreg,Ftest%ngfft,Ftest%npw_k)
247 2474319 : ABI_CHECK(ALL(mask),"FFT parallelism not supported in fftprof")
248 98 : ABI_FREE(mask)
249 :
250 98 : end subroutine fft_test_init
251 : !!***
252 :
253 : !----------------------------------------------------------------------
254 :
255 : !!****f* m_FFT_prof/fft_test_free_0D
256 : !! NAME
257 : !! fft_test_free_0D
258 : !!
259 : !! FUNCTION
260 : !! Destruction method for the FFT_test_t structured datatype.
261 : !!
262 : !! INPUTS
263 : !!
264 : !! OUTPUT
265 : !!
266 : !! SOURCE
267 :
268 98 : subroutine fft_test_free_0D(Ftest)
269 :
270 : !Arguments -----------------------------------
271 : class(FFT_test_t),intent(inout) :: Ftest
272 : ! *********************************************************************
273 :
274 98 : ABI_SFREE(Ftest%indpw_k)
275 98 : ABI_SFREE(Ftest%kg_k)
276 98 : ABI_SFREE(Ftest%kg_kout)
277 :
278 98 : call destroy_mpi_enreg(Ftest%MPI_enreg)
279 :
280 98 : end subroutine fft_test_free_0D
281 : !!***
282 :
283 : !----------------------------------------------------------------------
284 :
285 : !!****f* m_FFT_prof/fft_test_free_1D
286 : !! NAME
287 : !! fft_test_free_1D
288 : !!
289 : !! FUNCTION
290 : !! Destruction method for the FFT_test_t structured datatype.
291 : !!
292 : !! INPUTS
293 : !!
294 : !! OUTPUT
295 : !!
296 : !! SOURCE
297 :
298 17 : subroutine fft_test_free_1D(Ftest)
299 :
300 : !Arguments -----------------------------------
301 : class(FFT_test_t),intent(inout) :: Ftest(:)
302 :
303 : !Local variables-------------------------------
304 : integer :: ii
305 : ! *********************************************************************
306 :
307 132 : do ii=LBOUND(Ftest,DIM=1),UBOUND(Ftest,DIM=1)
308 115 : call Ftest(ii)%free()
309 : end do
310 :
311 17 : end subroutine fft_test_free_1D
312 : !!***
313 :
314 : !----------------------------------------------------------------------
315 :
316 : !!****f* m_FFT_prof/fft_test_print
317 : !! NAME
318 : !! fft_test_print
319 : !!
320 : !! FUNCTION
321 : !! Printout of the FFT_test_t structured datatype.
322 : !!
323 : !! INPUTS
324 : !!
325 : !! OUTPUT
326 : !!
327 : !! SOURCE
328 :
329 98 : subroutine fft_test_print(Ftest, header, unit, mode_paral, prtvol)
330 :
331 : !Arguments -----------------------------------
332 : class(FFT_test_t),intent(in) :: Ftest
333 : integer,optional,intent(in) :: unit,prtvol
334 : character(len=4),optional,intent(in) :: mode_paral
335 : character(len=*),optional,intent(in) :: header
336 :
337 : !Local variables-------------------------------
338 : !scalars
339 : integer :: my_unt,my_prtvol
340 : character(len=4) :: my_mode
341 : character(len=500) :: msg
342 : ! *********************************************************************
343 :
344 0 : my_unt =std_out; if (PRESENT(unit )) my_unt =unit
345 98 : my_prtvol=0 ; if (PRESENT(prtvol )) my_prtvol=prtvol
346 98 : my_mode ='COLL' ; if (PRESENT(mode_paral)) my_mode =mode_paral
347 :
348 : !msg=' ==== Info on the FFT test object ==== '
349 98 : if (PRESENT(header)) then
350 0 : msg=' ==== '//TRIM(ADJUSTL(header))//' ==== '
351 0 : call wrtout(my_unt,msg,my_mode)
352 : end if
353 :
354 98 : write(msg,'(a,i3)')"FFT setup for fftalg ",Ftest%ngfft(7)
355 196 : call print_ngfft([my_unt], Ftest%ngfft, header=msg)
356 :
357 98 : end subroutine fft_test_print
358 : !!***
359 :
360 : !----------------------------------------------------------------------
361 :
362 : !!****f* m_FFT_prof/get_name
363 : !! NAME
364 : !! get_name
365 : !!
366 : !! FUNCTION
367 : !! Returns a string with info on the test.
368 : !!
369 : !! INPUTS
370 : !!
371 : !! OUTPUT
372 : !!
373 : !! SOURCE
374 :
375 403 : character(len=TNAME_LEN) function get_name(Ftest)
376 :
377 : !Arguments -----------------------------------
378 : class(FFT_test_t),intent(in) :: Ftest
379 :
380 : !Local variables-------------------------------
381 : character(len=TNAME_LEN) :: library_name,cplex_mode,padding_mode
382 : ! *********************************************************************
383 :
384 403 : if (ftest%gpu_option == 0) then
385 403 : call fftalg_info(Ftest%ngfft(7), library_name, cplex_mode, padding_mode)
386 : !get_name = TRIM(library_name)//"; "//TRIM(cplex_mode)//"; "//TRIM(padding_mode)
387 403 : write(get_name,'(i3)')Ftest%ngfft(7)
388 403 : get_name = TRIM(library_name)//" ("//TRIM(get_name)//")"
389 : else
390 0 : get_name = "GPU_FLAVOR"
391 : end if
392 :
393 403 : end function get_name
394 : !!***
395 :
396 : !----------------------------------------------------------------------
397 :
398 : !!****f* m_FFT_prof/fftprof_init
399 : !! NAME
400 : !! fftprof_init
401 : !!
402 : !! FUNCTION
403 : !! Creation method for the FFT_prof_t structured datatype.
404 : !!
405 : !! INPUTS
406 : !! gflops = Gigaflops
407 : !!
408 : !! OUTPUT
409 : !!
410 : !! SOURCE
411 :
412 403 : subroutine fftprof_init(Ftprof, test_name, nthreads, ncalls, ndat, gpu_option, cpu_time, wall_time, gflops, results)
413 :
414 : !Arguments -----------------------------------
415 : class(FFT_prof_t),intent(out) :: Ftprof
416 : integer,intent(in) :: ncalls,nthreads,ndat, gpu_option
417 : real(dp),intent(in) :: cpu_time,wall_time,gflops
418 : character(len=*),intent(in) :: test_name
419 : !arrays
420 : complex(dp),optional,intent(in) :: results(:)
421 : ! *************************************************************************
422 :
423 403 : Ftprof%ncalls = ncalls
424 403 : Ftprof%nthreads = nthreads
425 403 : Ftprof%ndat = ndat
426 403 : Ftprof%gpu_option = gpu_option
427 403 : Ftprof%cpu_time = cpu_time
428 403 : Ftprof%wall_time = wall_time
429 403 : Ftprof%gflops = gflops
430 403 : Ftprof%test_name = test_name
431 :
432 403 : if (present(results)) then
433 921 : ABI_REMALLOC(Ftprof%results, (size(results)))
434 280722773 : Ftprof%results = results
435 : end if
436 :
437 403 : end subroutine fftprof_init
438 : !!***
439 :
440 : !----------------------------------------------------------------------
441 :
442 : !!****f* m_FFT_prof/fftprof_free_0D
443 : !! NAME
444 : !! fftprof_free_0D
445 : !!
446 : !! FUNCTION
447 : !! Destruction method for the FFT_prof_t structured datatype.
448 : !!
449 : !! SOURCE
450 :
451 501 : subroutine fftprof_free_0D(Ftprof)
452 :
453 : !Arguments -----------------------------------
454 : class(FFT_prof_t),intent(inout) :: Ftprof
455 : ! *********************************************************************
456 :
457 501 : ABI_SFREE(Ftprof%results)
458 :
459 501 : end subroutine fftprof_free_0D
460 : !!***
461 :
462 : !----------------------------------------------------------------------
463 :
464 : !!****f* m_FFT_prof/fftprof_free_1D
465 : !! NAME
466 : !! fftprof_free_1D
467 : !!
468 : !! FUNCTION
469 : !! Destruction method for the FFT_prof_t structured datatype.
470 : !!
471 : !! INPUTS
472 : !!
473 : !! OUTPUT
474 : !!
475 : !! SOURCE
476 :
477 75 : subroutine fftprof_free_1D(Ftprof)
478 :
479 : !Arguments -----------------------------------
480 : class(FFT_prof_t),intent(inout) :: Ftprof(:)
481 :
482 : !Local variables-------------------------------
483 : integer :: ii
484 : ! *********************************************************************
485 :
486 651 : do ii=LBOUND(Ftprof,DIM=1),UBOUND(Ftprof,DIM=1)
487 576 : call fftprof_free_0D(Ftprof(ii))
488 : end do
489 :
490 75 : end subroutine fftprof_free_1D
491 : !!***
492 :
493 : !----------------------------------------------------------------------
494 :
495 : !!****f* m_FFT_prof/fftprofs_print
496 : !! NAME
497 : !! fftprofs_print
498 : !!
499 : !! FUNCTION
500 : !! Printout of the FFT_prof_t structured datatype.
501 : !!
502 : !! INPUTS
503 : !!
504 : !! OUTPUT
505 : !!
506 : !! SOURCE
507 :
508 116 : subroutine fftprofs_print(Fprof, header, unit, mode_paral, prtvol)
509 :
510 : !Arguments -----------------------------------
511 : class(FFT_prof_t),intent(in) :: Fprof(:)
512 : integer,optional,intent(in) :: unit,prtvol
513 : character(len=4),optional,intent(in) :: mode_paral
514 : character(len=*),optional,intent(in) :: header
515 :
516 : !Local variables-------------------------------
517 : !scalars
518 : integer :: my_unt,my_prtvol,ncalls, field1_w,ii,ref_lib !ifft
519 : real(dp) :: mabs_err,mean_err,check_mabs_err,check_mean_err, ref_wtime,para_eff
520 : character(len=4) :: my_mode
521 : character(len=500) :: ofmt,hfmt,nafmt,msg
522 : ! *********************************************************************
523 :
524 58 : my_unt =std_out; if (PRESENT(unit )) my_unt =unit
525 58 : my_prtvol=0 ; if (PRESENT(prtvol )) my_prtvol=prtvol
526 58 : my_mode ='COLL' ; if (PRESENT(mode_paral)) my_mode =mode_paral
527 :
528 58 : msg='==== Info on the FFT_prof_t object ===='
529 58 : if (PRESENT(header)) msg='==== '//TRIM(ADJUSTL(header))//' ===='
530 :
531 3506 : call wrtout(my_unt,ch10//REPEAT("=",LEN_TRIM(msg)))
532 58 : call wrtout(my_unt,msg,my_mode)
533 3506 : call wrtout(my_unt,REPEAT("=",LEN_TRIM(msg)))
534 :
535 58 : field1_w=0 ! Width of the field used to print key names.
536 461 : do ii=1,SIZE(Fprof)
537 461 : field1_w = MAX(field1_w, LEN_TRIM(Fprof(ii)%test_name))
538 : end do
539 :
540 58 : if (field1_w==0) RETURN
541 58 : field1_w = field1_w + 2 ! To account for ". "
542 58 : write(ofmt,*)"(a",field1_w,",2x,2(f7.4,4x),1x,i2,1x,a,i3,a,1x,i0,4x,2(es9.2,3x))"
543 :
544 58 : write(hfmt,*)"(a",field1_w,",2x,a)"
545 58 : write(std_out,hfmt)" Library ","CPU-time WALL-time nthreads ncalls Max_|Err| <|Err|>"
546 : !
547 : ! Find reference library.
548 58 : ref_lib=0
549 58 : do ii=1,SIZE(Fprof)
550 58 : if (Fprof(ii)%ncalls>0) then
551 : ref_lib = ii
552 : EXIT
553 : end if
554 : end do
555 : !ref_lib=3
556 : !
557 : ! Write timing analysis and error wrt reference library if available.
558 58 : check_mabs_err=zero; check_mean_err=zero
559 461 : do ii=1,SIZE(Fprof)
560 403 : ncalls = Fprof(ii)%ncalls
561 461 : if (ncalls > 0) then
562 307 : mabs_err = zero; mean_err=zero
563 307 : if (ref_lib>0) then
564 280722773 : mabs_err = MAXVAL( ABS(Fprof(ii)%results - Fprof(ref_lib)%results) )
565 280722466 : mean_err = SUM( ABS(Fprof(ii)%results - Fprof(ref_lib)%results) ) / SIZE(Fprof(ref_lib)%results)
566 : ! Relative error is not a good estimator because some components are close to zero within machine accuracy.
567 : !mean_err = 100 * MAXVAL( ABS(Fprof(ii)%results - Fprof(1)%results)/ ABS(Fprof(1)%results ))
568 : !ifft = imax_loc( ABS(Fprof(ii)%results - Fprof(1)%results)/ ABS(Fprof(1)%results) )
569 : !write(std_out,*) Fprof(ii)%results(ifft),Fprof(1)%results(ifft)
570 : end if
571 307 : if (Fprof(ii)%nthreads==1) ref_wtime = Fprof(ii)%wall_time
572 307 : para_eff = 100 * ref_wtime / ( Fprof(ii)%wall_time * Fprof(ii)%nthreads)
573 : write(std_out,ofmt)&
574 307 : "- "//Fprof(ii)%test_name,Fprof(ii)%cpu_time/ncalls,Fprof(ii)%wall_time/ncalls,&
575 614 : Fprof(ii)%nthreads,"(",NINT(para_eff),"%)",ncalls,mabs_err,mean_err
576 307 : check_mabs_err = MAX(check_mabs_err, mabs_err)
577 307 : check_mean_err = MAX(check_mean_err, mean_err)
578 : else
579 96 : write(nafmt,*)"(a",field1_w,",2x,a)"
580 96 : write(std_out,nafmt)"- "//Fprof(ii)%test_name," N/A N/A N/A N/A N/A N/A"
581 : end if
582 : end do
583 :
584 58 : if (ref_lib > 0) then
585 : write(std_out,'(/,2(a,es9.2),2a)')&
586 58 : " Consistency check: MAX(Max_|Err|) = ",check_mabs_err,&
587 116 : ", Max(<|Err|>) = ",check_mean_err,", reference_lib: ",TRIM(Fprof(ref_lib)%test_name)
588 : end if
589 58 : write(std_out,*)
590 :
591 58 : end subroutine fftprofs_print
592 : !!***
593 :
594 : !----------------------------------------------------------------------
595 :
596 : !!****f* m_FFT_prof/time_fourdp
597 : !! NAME
598 : !! time_fourdp
599 : !!
600 : !! FUNCTION
601 : !! Profiling of the fourdp routine.
602 : !!
603 : !! INPUTS
604 : !!
605 : !! OUTPUT
606 : !!
607 : !! SOURCE
608 :
609 16 : subroutine time_fourdp(Ftest, isign, cplex, header, Ftprof)
610 :
611 : !Arguments -----------------------------------
612 : class(FFT_test_t),intent(inout) :: Ftest
613 : integer,intent(in) :: cplex,isign
614 : character(len=500),intent(out) :: header
615 : class(FFT_prof_t),intent(out) :: Ftprof
616 :
617 : !Local variables-------------------------------
618 : !scalars
619 : integer,parameter :: nspinor1=1
620 : integer :: icall,i1,i2,i3,n1,n2,n3,ifft
621 : real(dp) :: cpu_time,wall_time,gflops,gsq
622 : !character(len=500) :: msg
623 : character(len=TNAME_LEN) :: test_name
624 : !arrays
625 : integer,parameter :: g0(3)=(/1,2,-1/)
626 : integer :: gg(3)
627 16 : real(dp),allocatable :: fofg(:,:),fofr(:)
628 16 : complex(dp),allocatable :: results(:),ctmp(:)
629 : ! *********************************************************************
630 :
631 16 : test_name = Ftest%get_name()
632 16 : n1=Ftest%ngfft(1); n2=Ftest%ngfft(2); n3=Ftest%ngfft(3)
633 :
634 16 : write(header,'(2(a,i2),a)')" fourdp with cplex ",cplex,", isign ",isign,", ndat 1"
635 :
636 16 : if (Ftest%available == 0) then
637 4 : call Ftprof%init(test_name,0,0,0,0,zero,zero,zero)
638 : RETURN
639 : end if
640 :
641 12 : call xomp_set_num_threads(Ftest%nthreads)
642 :
643 12 : if (Ftest%ngfft(7)/100 == FFT_FFTW3) call fftw3_set_nthreads(Ftest%nthreads)
644 :
645 36 : ABI_MALLOC(fofg,(2,Ftest%nfft))
646 36 : ABI_MALLOC(fofr,(cplex*Ftest%nfft))
647 :
648 : ! Initialize input data.
649 12 : if (isign==1) then
650 : ! initialize fofg
651 13122006 : fofg = zero
652 : ifft=0
653 546 : do i3=1,n3
654 540 : gg(3)=i3-1; if (i3>1+n3/2) gg(3)=i3-n3-1 ! TODO recheck this
655 49146 : do i2=1,n2
656 48600 : gg(2)=i2-1; if (i2>1+n2/2) gg(2)=i2-n2-1
657 4423140 : do i1=1,n1
658 4374000 : gg(1)=i1-1; if (i1>1+n1/2) gg(1)=i1-n1-1
659 83106000 : gsq = two_pi**2 * DOT_PRODUCT(gg,MATMUL(Ftest%gmet,gg))
660 4374000 : ifft=ifft+1
661 4374000 : fofg(1,ifft) = EXP(-gsq)
662 4422600 : fofg(2,ifft) = zero
663 : end do
664 : end do
665 : end do
666 :
667 : else
668 : ! init fofr
669 6 : if (cplex==2) then
670 3 : call calc_eigr(g0,Ftest%nfft,Ftest%ngfft,fofr)
671 3 : else if (cplex==1) then
672 9 : ABI_MALLOC(ctmp,(Ftest%nfft))
673 3 : call calc_ceigr(g0,Ftest%nfft,nspinor1,Ftest%ngfft,ctmp)
674 2187006 : fofr = REAL(ctmp)
675 3 : ABI_FREE(ctmp)
676 : else
677 0 : ABI_ERROR(sjoin("Wrong cplex:", itoa(cplex)))
678 : end if
679 : end if
680 :
681 8748036 : ABI_CALLOC(results, (Ftest%nfft))
682 12 : call cwtime(cpu_time, wall_time, gflops, "start")
683 :
684 72 : do icall=1,NCALLS_FOR_TEST
685 60 : ifft = empty_cache(CACHE_KBSIZE)
686 60 : call fourdp(cplex,fofg,fofr,isign,Ftest%MPI_enreg,Ftest%nfft,1,Ftest%ngfft,0)
687 :
688 : ! Store results at the first call.
689 72 : if (icall==1) then
690 12 : if (isign==1) then
691 6 : if (cplex==1) then
692 2187006 : results = DCMPLX(fofr, zero)
693 3 : else if (cplex==2) then
694 2187006 : results = DCMPLX( fofr(1:2*Ftest%nfft:2), fofr(2:2*Ftest%nfft:2) )
695 : end if
696 6 : else if (isign==-1) then
697 4374012 : results = DCMPLX(fofg(1,:),fofg(2,:))
698 : end if
699 : end if
700 : end do
701 :
702 12 : call cwtime(cpu_time, wall_time, gflops, "stop")
703 : call Ftprof%init(test_name,Ftest%nthreads,NCALLS_FOR_TEST,Ftest%ndat,ftest%gpu_option, &
704 12 : cpu_time,wall_time,gflops,results=results)
705 :
706 12 : ABI_FREE(fofg)
707 12 : ABI_FREE(fofr)
708 12 : ABI_FREE(results)
709 :
710 24 : end subroutine time_fourdp
711 : !!***
712 :
713 : !----------------------------------------------------------------------
714 :
715 : !!****f* m_FFT_prof/time_fftbox
716 : !! NAME
717 : !! time_fftbox
718 : !!
719 : !! FUNCTION
720 : !! Profiling of the fftbox_[io]p routines.
721 : !!
722 : !! INPUTS
723 : !!
724 : !! OUTPUT
725 : !!
726 : !! SOURCE
727 :
728 12 : subroutine time_fftbox(Ftest, isign, inplace, header, Ftprof)
729 :
730 : !Arguments -----------------------------------
731 : class(FFT_test_t),intent(inout) :: Ftest
732 : integer,intent(in) :: isign,inplace
733 : character(len=500),intent(inout) :: header
734 : class(FFT_prof_t),intent(out) :: Ftprof
735 :
736 : !Local variables-------------------------------
737 : !scalars
738 : integer,parameter :: nspinor1 = 1, fftcache0 = 0
739 : integer :: icall,i1,i2,i3,n1,n2,n3,ifft,ndat,nfft,dat,padat
740 : real(dp) :: cpu_time,wall_time,gflops,gsq
741 : !character(len=500) :: msg
742 : character(len=TNAME_LEN) :: test_name
743 : type(fftbox_plan3_t) :: plan
744 : !arrays
745 : integer,parameter :: g0(3) = [1,-2,1]
746 : integer :: gg(3)
747 12 : complex(dp),allocatable :: ffc(:),ggc(:),results(:)
748 : ! *********************************************************************
749 :
750 12 : test_name = Ftest%get_name()
751 :
752 12 : if (Ftest%available == 0) then
753 4 : call Ftprof%init(test_name, 0, 0, 0, 0, zero, zero, zero)
754 : return
755 : end if
756 :
757 8 : call xomp_set_num_threads(Ftest%nthreads)
758 :
759 8 : if (Ftest%ngfft(7)/100 == FFT_FFTW3) call fftw3_set_nthreads(Ftest%nthreads)
760 :
761 8 : n1 = Ftest%ngfft(1); n2 = Ftest%ngfft(2); n3 = Ftest%ngfft(3)
762 8 : nfft = Ftest%nfft; ndat = Ftest%ndat
763 8 : write(header,'(3(a,i2))')" fftbox with isign ",isign,", in-place ",inplace,", ndat ",ndat
764 :
765 5832024 : ABI_CALLOC(ffc, (nfft*ndat))
766 5832016 : ABI_CALLOC(ggc, (nfft*ndat))
767 5832016 : ABI_CALLOC(results, (nfft*ndat))
768 :
769 8 : if (isign==-1) then
770 4 : call calc_ceigr(g0,nfft,nspinor1,Ftest%ngfft,ffc)
771 4 : else if (isign==1) then
772 : ifft=0
773 364 : do i3=1,n3
774 360 : gg(3)=i3-1; if (i3>1+n3/2) gg(3)=i3-n3-1 ! TODO recheck this
775 32764 : do i2=1,n2
776 32400 : gg(2)=i2-1; if (i2>1+n2/2) gg(2)=i2-n2-1
777 2948760 : do i1=1,n1
778 2916000 : gg(1)=i1-1; if (i1>1+n1/2) gg(1)=i1-n1-1
779 55404000 : gsq = two_pi**2 * DOT_PRODUCT(gg,MATMUL(Ftest%gmet,gg))
780 2916000 : ifft=ifft+1
781 2948400 : ffc(ifft) = EXP(-gsq)
782 : end do
783 : end do
784 : end do
785 : else
786 0 : ABI_ERROR("Wrong isign")
787 : end if
788 :
789 : ! Replicate and scale input data
790 8 : do dat=2,ndat
791 0 : padat = (dat-1) * nfft
792 8 : do ifft=1,nfft
793 0 : ffc(ifft+padat) = DBLE(dat) * ffc(ifft)
794 : end do
795 : end do
796 :
797 8 : call cwtime(cpu_time, wall_time, gflops, "start")
798 :
799 : ! No augmentation here.
800 8 : call plan%init(ndat, Ftest%ngfft(1:3), Ftest%ngfft(1:3), Ftest%ngfft(7), fftcache0, ftest%gpu_option)
801 :
802 : if (plan%gpu_option == ABI_GPU_OPENMP) then
803 : #ifdef HAVE_OPENMP_OFFLOAD
804 : !$OMP TARGET ENTER DATA MAP(to:ffc, ggc)
805 : #endif
806 : end if
807 :
808 12 : select case (inplace)
809 : case (0)
810 24 : do icall=1,NCALLS_FOR_TEST
811 20 : ifft = empty_cache(CACHE_KBSIZE)
812 20 : call plan%execute(ffc, ggc, isign, ndat, iscale=0)
813 : ! Store results at the first call.
814 24 : if (icall == 1) then
815 : #ifdef HAVE_OPENMP_OFFLOAD
816 : !$omp target update from(ggc)
817 : #endif
818 2916008 : results = ggc
819 : end if
820 : end do
821 : case (1)
822 24 : do icall=1,NCALLS_FOR_TEST
823 20 : ifft = empty_cache(CACHE_KBSIZE)
824 20 : call plan%execute(ffc, isign, ndat, iscale=0)
825 : ! Store results at the first call.
826 24 : if (icall == 1) then
827 : #ifdef HAVE_OPENMP_OFFLOAD
828 : !$omp target update from(ffc)
829 : #endif
830 2916008 : results = ffc
831 : end if
832 : end do
833 : case default
834 8 : ABI_ERROR(sjoin("Wrong value for inplace:", itoa(inplace)))
835 : end select
836 :
837 8 : call cwtime(cpu_time, wall_time, gflops, "stop")
838 : call Ftprof%init(test_name,Ftest%nthreads,NCALLS_FOR_TEST,Ftest%ndat,ftest%gpu_option, &
839 8 : cpu_time,wall_time,gflops,results=results)
840 :
841 8 : call plan%free()
842 :
843 : if (plan%gpu_option == ABI_GPU_OPENMP) then
844 : #ifdef HAVE_OPENMP_OFFLOAD
845 : !$OMP TARGET EXIT DATA MAP(delete:ffc, ggc)
846 : #endif
847 : end if
848 8 : ABI_FREE(ffc)
849 8 : ABI_FREE(ggc)
850 8 : ABI_FREE(results)
851 :
852 100 : end subroutine time_fftbox
853 : !!***
854 :
855 : !----------------------------------------------------------------------
856 :
857 : !!****f* m_FFT_prof/time_fourwf
858 : !! NAME
859 : !! time_fourwf
860 : !!
861 : !! FUNCTION
862 : !! Profiling of the fourwf routine.
863 : !!
864 : !! INPUTS
865 : !!
866 : !! OUTPUT
867 : !!
868 : !! SOURCE
869 :
870 363 : subroutine time_fourwf(Ftest, cplex, option_fourwf, header, Ftprof)
871 :
872 : !Arguments -----------------------------------
873 : class(FFT_test_t),intent(inout) :: Ftest
874 : integer,intent(in) :: cplex,option_fourwf
875 : character(len=500),intent(out) :: header
876 : class(FFT_prof_t),intent(out) :: Ftprof
877 :
878 : !Local variables-------------------------------
879 : !scalars
880 : integer,parameter :: tim0=0
881 : integer :: n1,n2,n3,n4,n5,n6,npw_out,icall,i1,i2,i3,idx,ipw,ndat,cnt,dat,padat
882 : integer :: fftalg,fftalga,fftalgc
883 : real(dp),parameter :: weight_i=one,weight_r=one
884 : real(dp) :: cpu_time,wall_time,gflops,gsq,g0dotr
885 : logical :: isbuggy,not_supported
886 : !character(len=500) :: msg
887 : character(len=TNAME_LEN) :: test_name
888 : !arrays
889 : integer,parameter :: g0(3)=[1,-1,2] !g0(3)=[1,0,0]
890 : integer :: gg(3)
891 363 : integer,allocatable :: gbound_in(:,:),gbound_out(:,:)
892 363 : real(dp),allocatable :: denpot(:,:,:),fofg_in(:,:), fofr_4(:,:,:,:),fofg_out(:,:)
893 363 : complex(dp),allocatable :: results(:)
894 : ! *********************************************************************
895 :
896 363 : test_name = Ftest%get_name()
897 :
898 363 : fftalg = Ftest%ngfft(7); fftalga = fftalg/100; fftalgc = MOD(fftalg,10)
899 :
900 : isbuggy = &
901 : (option_fourwf==3 .and. fftalga==FFT_SG2002 .and. fftalgc /= 0 .and. &
902 2008 : any(Ftest%istwf_k == [3,4,5,6,7,8,9])) ! see sg_fourwf
903 : !isbuggy = .False.
904 :
905 : !FIXME problems with the unitary tests reference files!
906 : not_supported = ( &
907 363 : (fftalgc == 2 .and. option_fourwf==0 .and. Ftest%istwf_k > 2))
908 : !not_supported = .FALSE.
909 :
910 363 : npw_out= Ftest%npw_kout
911 363 : ndat = Ftest%ndat
912 363 : n1=Ftest%ngfft(1); n2=Ftest%ngfft(2); n3=Ftest%ngfft(3)
913 363 : n4=Ftest%ngfft(4); n5=Ftest%ngfft(5); n6=Ftest%ngfft(6)
914 :
915 363 : write(header,'(4(a,i2))')" fourwf with option ",option_fourwf,", cplex ",cplex,", ndat ",ndat,", istwf_k ",Ftest%istwf_k
916 :
917 363 : if (isbuggy .or. not_supported .or. Ftest%available==0) then
918 81 : call Ftprof%init(test_name,0,0,0,0,zero,zero,zero)
919 81 : RETURN
920 : end if
921 :
922 282 : call xomp_set_num_threads(Ftest%nthreads)
923 :
924 282 : if (Ftest%ngfft(7)/100 == FFT_FFTW3) call fftw3_set_nthreads(Ftest%nthreads)
925 :
926 : ! FFTW3 does not need gbound_in but oh well
927 1128 : ABI_MALLOC(gbound_in, (2*Ftest%mgfft+8,2))
928 282 : call sphereboundary(gbound_in,Ftest%istwf_k,Ftest%kg_k,Ftest%mgfft,Ftest%npw_k)
929 :
930 1128 : ABI_MALLOC(gbound_out, (2*Ftest%mgfft+8,2))
931 282 : call sphereboundary(gbound_out,Ftest%istwf_k,Ftest%kg_kout,Ftest%mgfft,Ftest%npw_kout)
932 :
933 118451490 : ABI_CALLOC(denpot, (cplex*n4,n5,n6))
934 38832138 : ABI_CALLOC(fofg_in, (2,Ftest%npw_k*ndat))
935 38832138 : ABI_CALLOC(fofg_out, (2,npw_out*ndat))
936 811367790 : ABI_CALLOC(fofr_4, (2,n4,n5,n6*ndat))
937 264648846 : ABI_CALLOC(results, (Ftest%nfft*ndat))
938 :
939 : select case (option_fourwf)
940 : case (0, 1, 2)
941 : !! for option==0, fofgin(2,npwin*ndat)=holds input wavefunction in G sphere;
942 : !! fofr(2,n4,n5,n6) contains the output Fourier Transform of fofgin;
943 : !! no use of denpot, fofgout and npwout.
944 : !! for option==1, fofgin(2,npwin*ndat)=holds input wavefunction in G sphere;
945 : !! denpot(cplex*n4,n5,n6) contains the input density at input,
946 : !! and the updated density at output (accumulated);
947 : !! no use of fofgout and npwout.
948 : !! for option==2, fofgin(2,npwin*ndat)=holds input wavefunction in G sphere;
949 : !! denpot(cplex*n4,n5,n6) contains the input local potential;
950 : !! fofgout(2,npwout*ndat) contains the output function;
951 : !!
952 10259385 : do cnt=0, (Ftest%npw_k * ndat) - 1
953 10259165 : ipw = 1 + MOD(cnt, Ftest%npw_k)
954 41036660 : gg = Ftest%kg_k(:,ipw)
955 194924135 : gsq = two_pi**2 * DOT_PRODUCT(gg,MATMUL(Ftest%gmet,gg))
956 10259165 : fofg_in(1,cnt+1) = EXP(-gsq)
957 10259385 : fofg_in(2,cnt+1) = zero
958 : end do
959 :
960 45465740 : if (option_fourwf==1) denpot = one
961 :
962 220 : if (option_fourwf==2) then
963 : ! Init denpot
964 89 : if (cplex==1) then
965 6556 : do i3=0,n3-1
966 529116 : do i2=0,n2-1
967 44721040 : do i1=0,n1-1
968 : g0dotr= two_pi*( g0(1)*(i1/DBLE(n1)) &
969 : +g0(2)*(i2/DBLE(n2)) &
970 44192000 : +g0(3)*(i3/DBLE(n3)) )
971 44714560 : denpot(i1+1,i2+1,i3+1)=COS(g0dotr)
972 : end do
973 : end do
974 : end do
975 13 : else if (cplex==2) then
976 1313 : do i3=0,n3-1
977 131313 : do i2=0,n2-1
978 : idx=1
979 13131300 : do i1=0,n1-1
980 : g0dotr= two_pi*( g0(1)*(i1/DBLE(n1)) &
981 : +g0(2)*(i2/DBLE(n2)) &
982 13000000 : +g0(3)*(i3/DBLE(n3)) )
983 :
984 13000000 : denpot(idx, i2+1,i3+1)= COS(g0dotr)
985 13000000 : denpot(idx+1,i2+1,i3+1)= SIN(g0dotr)
986 13130000 : idx=idx+2
987 : end do
988 : end do
989 : end do
990 : end if
991 : end if
992 :
993 : case (3)
994 : !! for option==3, fofr(2,n4,n5,n6*ndat) contains the input real space wavefunction;
995 : !! fofgout(2,npwout*ndat) contains its output Fourier transform;
996 : !! no use of fofgin and npwin.
997 : idx=0
998 142 : do dat=1,ndat
999 80 : padat = (dat-1)*n6
1000 7302 : do i3=0,n3-1
1001 629160 : do i2=0,n2-1
1002 56773080 : do i1=0,n1-1
1003 : g0dotr= two_pi*( g0(1)*(i1/DBLE(n1)) &
1004 : +g0(2)*(i2/DBLE(n2)) &
1005 56144000 : +g0(3)*(i3/DBLE(n3)) )
1006 : !fofr_4(1,i1+1,i2+1,i3+1+padat)=COS(g0dotr)
1007 : !fofr_4(2,i1+1,i2+1,i3+1+padat)=SIN(g0dotr)
1008 56144000 : fofr_4(1,i1+1,i2+1,i3+1+padat)=10 * EXP(-g0dotr**2)
1009 56144000 : fofr_4(2,i1+1,i2+1,i3+1+padat)=zero
1010 56144000 : idx=idx+1
1011 56765920 : results(idx) = DCMPLX(fofr_4(1,i1+1,i2+1,i3+1+padat), fofr_4(2,i1+1,i2+1,i3+1+padat))
1012 : end do
1013 : end do
1014 : end do
1015 : end do
1016 :
1017 : case default
1018 282 : ABI_ERROR(sjoin("Wrong value for option_fourwf:", itoa(option_fourwf)))
1019 : end select
1020 :
1021 282 : call cwtime(cpu_time, wall_time, gflops, "start")
1022 :
1023 1602 : do icall=1,NCALLS_FOR_TEST
1024 :
1025 1320 : i1 = empty_cache(CACHE_KBSIZE)
1026 :
1027 : call fourwf(cplex,denpot,fofg_in,fofg_out,fofr_4,gbound_in,gbound_out,Ftest%istwf_k,&
1028 : Ftest%kg_k,Ftest%kg_kout,Ftest%mgfft,Ftest%MPI_enreg,ndat,Ftest%ngfft,Ftest%npw_k,npw_out,n4,n5,n6,option_fourwf,&
1029 1320 : tim0,weight_r,weight_i, gpu_option=ftest%gpu_option)
1030 :
1031 : ! Store results at the first call.
1032 1602 : if (icall == 1) then
1033 : select case (option_fourwf)
1034 : case (0)
1035 : !! for option==0, fofgin(2,npwin*ndat)=holds input wavefunction in G sphere;
1036 : !! fofr(2,n4,n5,n6) contains the output Fourier Transform of fofgin;
1037 : !! no use of denpot, fofgout and npwout.
1038 : idx=0
1039 128 : do dat=1,ndat
1040 73 : padat = (dat-1)*n6
1041 6728 : do i3=1,n3
1042 588273 : do i2=1,n2
1043 53708200 : do i1=1,n1
1044 53120000 : idx=idx+1
1045 53701600 : results(idx) = DCMPLX(fofr_4(1,i1,i2,i3+padat),fofr_4(2,i1,i2,i3+padat))
1046 : end do
1047 : end do
1048 : end do
1049 : end do
1050 : case (1)
1051 : !! for option==1, fofgin(2,npwin*ndat)=holds input wavefunction in G sphere;
1052 : !! denpot(cplex*n4,n5,n6) contains the input density at input,
1053 : !! and the updated density at output (accumulated);
1054 : !! no use of fofgout and npwout.
1055 76 : if (cplex==1) then
1056 : idx=0
1057 6556 : do i3=1,n3
1058 529116 : do i2=1,n2
1059 44721040 : do i1=1,n1
1060 44192000 : idx=idx+1
1061 44714560 : results(idx) = DCMPLX(denpot(i1,i2,i3),zero)
1062 : end do
1063 : end do
1064 : end do
1065 :
1066 0 : else if (cplex==2) then
1067 : idx=0
1068 0 : do i3=1,n3
1069 0 : do i2=1,n2
1070 0 : do i1=1,2*n1,2
1071 0 : idx=idx+1
1072 0 : results(idx) = DCMPLX(denpot(i1,i2,i3),denpot(i1+1,i2,i3))
1073 : end do
1074 : end do
1075 : end do
1076 : else
1077 0 : ABI_ERROR("Wrong cplex")
1078 : end if
1079 :
1080 : case (2)
1081 : !! for option==2, fofgin(2,npwin*ndat)=holds input wavefunction in G sphere;
1082 : !! denpot(cplex*n4,n5,n6) contains the input local potential;
1083 : !! fofgout(2,npwout*ndat) contains the output function;
1084 4803443 : do ipw=1,npw_out*ndat
1085 4803443 : results(ipw) = DCMPLX(fofg_out(1,ipw),fofg_out(2,ipw))
1086 : end do
1087 :
1088 : case (3)
1089 : !! for option==3, fofr(2,n4,n5,n6*ndat) contains the input real space wavefunction;
1090 : !! fofgout(2,npwout*ndat) contains its output Fourier transform;
1091 : !! no use of fofgin and npwin.
1092 2684881 : do ipw=1,npw_out*ndat
1093 2684661 : results(ipw) = DCMPLX(fofg_out(1,ipw),fofg_out(2,ipw))
1094 : end do
1095 : !write(Ftest%ngfft(7),*)"results opt 3 Ftest%ngfft(7)",Ftest%ngfft(7)
1096 : !do dat=1,ndat
1097 : ! do ipw=1,npw_out
1098 : ! idx = ipw + (dat-1)*npw_out
1099 : ! write(Ftest%ngfft(7),*)ipw,dat,results(idx)
1100 : ! end do
1101 : !end do
1102 : end select
1103 : end if
1104 : end do
1105 :
1106 282 : call cwtime(cpu_time, wall_time, gflops, "stop")
1107 : call Ftprof%init(test_name,Ftest%nthreads,NCALLS_FOR_TEST,Ftest%ndat,ftest%gpu_option,&
1108 282 : cpu_time,wall_time,gflops,results=results)
1109 :
1110 282 : ABI_FREE(denpot)
1111 282 : ABI_FREE(fofg_in)
1112 282 : ABI_FREE(fofg_out)
1113 282 : ABI_FREE(fofr_4)
1114 282 : ABI_FREE(gbound_in)
1115 282 : ABI_FREE(gbound_out)
1116 282 : ABI_FREE(results)
1117 :
1118 927 : end subroutine time_fourwf
1119 : !!***
1120 :
1121 : !----------------------------------------------------------------------
1122 :
1123 : !!****f* m_FFT_prof/fftprof_ncalls_per_test
1124 : !! NAME
1125 : !! fftprof_ncalls_per_test
1126 : !!
1127 : !! FUNCTION
1128 : !! Helper function used to set the number of calls to be used in each time_* routine.
1129 : !!
1130 : !! INPUTS
1131 : !! ncalls=Number of calls to be used.
1132 : !!
1133 : !! SIDE EFFECTS
1134 : !! NCALLS_FOR_TEST = ncalls
1135 : !!
1136 : !! SOURCE
1137 :
1138 17 : subroutine fftprof_ncalls_per_test(ncalls)
1139 :
1140 : !Arguments -----------------------------------
1141 : integer,intent(in) :: ncalls
1142 : ! *********************************************************************
1143 :
1144 17 : NCALLS_FOR_TEST = ncalls
1145 :
1146 17 : end subroutine fftprof_ncalls_per_test
1147 : !!***
1148 :
1149 : !----------------------------------------------------------------------
1150 :
1151 : !!****f* m_FFT_prof/time_rhotwg
1152 : !! NAME
1153 : !! time_rhotwg
1154 : !!
1155 : !! FUNCTION
1156 : !! Profiling of the rho_tw_g routine.
1157 : !!
1158 : !! INPUTS
1159 : !!
1160 : !! OUTPUT
1161 : !!
1162 : !! SOURCE
1163 :
1164 6 : subroutine time_rhotwg(Ftest, map2sphere, use_padfft, osc_npw, osc_gvec, header, Ftprof)
1165 :
1166 : !Arguments -----------------------------------
1167 : !scalars
1168 : class(FFT_test_t),intent(inout) :: Ftest
1169 : integer,intent(in) :: map2sphere,use_padfft,osc_npw
1170 : character(len=500),intent(out) :: header
1171 : class(FFT_prof_t),intent(out) :: Ftprof
1172 : !arrays
1173 : integer,intent(in) :: osc_gvec(3,osc_npw)
1174 :
1175 : !Local variables-------------------------------
1176 : !scalars
1177 : integer,parameter :: nspinor1=1,dim_rtwg1=1,istwfk1=1
1178 : integer :: icall,ifft,itim1,itim2,nfft,dat,sprc,ptr,ndat, n1,n2,n3,n4,n5,n6
1179 : real(dp) :: cpu_time,wall_time,gflops
1180 : complex(dp) :: ktabp1 = cone, ktabp2 = cone
1181 : character(len=TNAME_LEN) :: test_name
1182 : logical :: not_implemented
1183 6 : type(MPI_type) :: MPI_enreg_seq
1184 : !arrays
1185 : !integer,parameter :: g1(3)=[1,1,2],g2(3)=[-1,-2,-1]
1186 : integer,parameter :: g1(3)=[-1,0,0], g2(3)=[1,0,0]
1187 6 : integer,allocatable :: gbound(:,:), ktabr1(:), ktabr2(:), igfftg0(:)
1188 : real(dp),parameter :: spinrot1(4)=(/one,zero,zero,one/),spinrot2(4)=(/one,zero,zero,one/)
1189 6 : logical,allocatable :: mask(:)
1190 6 : complex(dp),allocatable :: results(:)
1191 6 : complex(gwp),allocatable :: rhotwg(:), wfn1(:), wfn2(:)
1192 : ! *********************************************************************
1193 :
1194 6 : test_name = Ftest%get_name()
1195 :
1196 6 : nfft = Ftest%nfft; ndat = Ftest%ndat
1197 6 : n1=Ftest%ngfft(1); n2=Ftest%ngfft(2); n3=Ftest%ngfft(3)
1198 6 : n4=Ftest%ngfft(4); n5=Ftest%ngfft(5); n6=Ftest%ngfft(6)
1199 :
1200 6 : write(header,'(3(a,i2))')"rho_tw_g with use_padfft ",use_padfft,", map2sphere ",map2sphere,", ndat ",ndat
1201 :
1202 : ! TODO: zero-pad not available with SG2001 routines.
1203 6 : not_implemented = (use_padfft==1.and.Ftest%ngfft(7) == 412)
1204 :
1205 6 : if (Ftest%available==0.or.not_implemented) then
1206 3 : call Ftprof%init(test_name,0,0,0,0,zero,zero,zero)
1207 3 : return
1208 : end if
1209 :
1210 3 : call xomp_set_num_threads(Ftest%nthreads)
1211 :
1212 3 : if (Ftest%ngfft(7)/100 == FFT_FFTW3) call fftw3_set_nthreads(Ftest%nthreads)
1213 :
1214 3 : call initmpi_seq(MPI_enreg_seq)
1215 3 : call MPI_enreg_seq%distribfft%init_seq('c',n2,n3,'all')
1216 :
1217 3 : itim1=1; itim2=1
1218 9 : ABI_MALLOC(ktabr1,(nfft))
1219 6 : ABI_MALLOC(ktabr2,(nfft))
1220 :
1221 2187003 : do ifft=1,nfft
1222 2187000 : ktabr1(ifft)= ifft
1223 2187003 : ktabr2(ifft)= ifft
1224 : end do
1225 :
1226 9 : ABI_MALLOC(igfftg0,(osc_npw*map2sphere))
1227 :
1228 3 : if (map2sphere > 0) then
1229 9 : ABI_MALLOC(mask,(osc_npw))
1230 3 : call kgindex(igfftg0,osc_gvec,mask,MPI_enreg_seq,Ftest%ngfft,osc_npw)
1231 36162 : ABI_CHECK(ALL(mask)," FFT parallelism not supported")
1232 3 : ABI_FREE(mask)
1233 : end if
1234 :
1235 12 : ABI_MALLOC(gbound,(2*Ftest%mgfft+8,2*use_padfft))
1236 3 : if (use_padfft == 1) call sphereboundary(gbound,istwfk1,osc_gvec,Ftest%mgfft,osc_npw)
1237 :
1238 9 : ABI_MALLOC(wfn1, (nfft*nspinor1*ndat))
1239 6 : ABI_MALLOC(wfn2, (nfft*nspinor1*ndat))
1240 :
1241 6 : do dat=1,ndat
1242 9 : do sprc=1,nspinor1
1243 3 : ptr = 1 + (sprc-1)*nfft + (dat-1)*nfft*nspinor1
1244 3 : call calc_ceigr(g1,nfft,nspinor1,Ftest%ngfft,wfn1(ptr:))
1245 6 : call calc_ceigr(g2,nfft,nspinor1,Ftest%ngfft,wfn2(ptr:))
1246 : end do
1247 : end do
1248 :
1249 9 : ABI_MALLOC(rhotwg,(osc_npw*dim_rtwg1*ndat))
1250 6 : ABI_MALLOC(results,(osc_npw*dim_rtwg1*ndat))
1251 :
1252 3 : call cwtime(cpu_time, wall_time, gflops, "start")
1253 :
1254 18 : do icall=1,NCALLS_FOR_TEST
1255 15 : ifft = empty_cache(CACHE_KBSIZE)
1256 : call rho_tw_g(nspinor1,osc_npw,nfft,ndat,Ftest%ngfft,map2sphere,use_padfft,igfftg0,gbound,&
1257 : wfn1,itim1,ktabr1,ktabp1,spinrot1,&
1258 : wfn2,itim2,ktabr2,ktabp2,spinrot2,&
1259 15 : dim_rtwg1,rhotwg)
1260 : ! Store results at the first call.
1261 36180 : if (icall==1) results = rhotwg
1262 : end do
1263 :
1264 3 : call cwtime(cpu_time, wall_time, gflops, "stop")
1265 : call Ftprof%init(test_name,Ftest%nthreads,NCALLS_FOR_TEST,Ftest%ndat,ftest%gpu_option, &
1266 3 : cpu_time,wall_time,gflops,results=results)
1267 :
1268 3 : ABI_FREE(ktabr1)
1269 3 : ABI_FREE(ktabr2)
1270 3 : ABI_FREE(igfftg0)
1271 3 : ABI_FREE(gbound)
1272 3 : ABI_FREE(rhotwg)
1273 3 : ABI_FREE(wfn1)
1274 3 : ABI_FREE(wfn2)
1275 3 : ABI_FREE(results)
1276 3 : call destroy_mpi_enreg(MPI_enreg_seq)
1277 :
1278 12 : end subroutine time_rhotwg
1279 : !!***
1280 :
1281 : !----------------------------------------------------------------------
1282 :
1283 : !!****f* m_FFT_prof/time_fftu
1284 : !! NAME
1285 : !! time_fftu
1286 : !!
1287 : !! FUNCTION
1288 : !! Profiling of the fftu routines.
1289 : !!
1290 : !! INPUTS
1291 : !!
1292 : !! OUTPUT
1293 : !!
1294 : !! SOURCE
1295 :
1296 6 : subroutine time_fftu(Ftest, isign, header, Ftprof)
1297 :
1298 : !Arguments -----------------------------------
1299 : class(FFT_test_t),intent(inout) :: Ftest
1300 : integer,intent(in) :: isign
1301 : character(len=500),intent(out) :: header
1302 : class(FFT_prof_t),intent(out) :: Ftprof
1303 :
1304 : !Local variables-------------------------------
1305 : !scalars
1306 : integer,parameter :: nspinor1=1
1307 : integer :: icall,i1,i2,i3,n1,n2,n3,ifft,npw_k,ndat,dat,nfft,cnt,ipw,padat,istwf_k
1308 : !integer :: n4,n5,n6,n456,idx
1309 : real(dp) :: cpu_time,wall_time,gflops,gsq,g0dotr
1310 : logical :: not_implemented
1311 : !character(len=500) :: msg
1312 : character(len=TNAME_LEN) :: test_name
1313 : !arrays
1314 : integer,parameter :: g0(3) = [1,-2,1]
1315 : integer :: gg(3)
1316 6 : integer,allocatable :: kg_k(:,:),gbound(:,:)
1317 6 : complex(dp),allocatable :: ug(:),results(:),ur(:)
1318 : ! *********************************************************************
1319 :
1320 6 : test_name = Ftest%get_name()
1321 :
1322 6 : n1=Ftest%ngfft(1); n2=Ftest%ngfft(2); n3=Ftest%ngfft(3)
1323 : !n4=Ftest%ngfft(4); n5=Ftest%ngfft(5); n6=Ftest%ngfft(6)
1324 :
1325 6 : nfft = n1*n2*n3
1326 : !n456 = n4*n5*n6
1327 6 : ndat = Ftest%ndat
1328 :
1329 6 : write(header,'(2(a,i2))')" fftu with isign ",isign,", ndat ",ndat
1330 :
1331 : ! TODO: zero-pad not available with SG2001 routines.
1332 6 : not_implemented = (Ftest%ngfft(7) == 412)
1333 :
1334 6 : if (Ftest%available==0.or.not_implemented) then
1335 4 : call Ftprof%init(test_name,0,0,0,0,zero,zero,zero)
1336 : return
1337 : end if
1338 :
1339 2 : call xomp_set_num_threads(Ftest%nthreads)
1340 :
1341 2 : if (Ftest%ngfft(7)/100 == FFT_FFTW3) call fftw3_set_nthreads(Ftest%nthreads)
1342 : !
1343 2 : istwf_k = Ftest%istwf_k
1344 : !istwf_k = 1 ! Do not use istwf_k trick here
1345 2 : call get_kg(Ftest%kpoint,istwf_k,Ftest%ecut,Ftest%gmet,npw_k,kg_k)
1346 :
1347 8 : ABI_MALLOC(gbound,(2*Ftest%mgfft+8,2))
1348 2 : call sphereboundary(gbound,istwf_k,kg_k,Ftest%mgfft,npw_k)
1349 :
1350 6 : ABI_MALLOC(ug,(npw_k*ndat))
1351 6 : ABI_MALLOC(ur, (nfft*ndat))
1352 4 : ABI_MALLOC(results,(nfft*ndat))
1353 1458002 : results=czero ! needed for R --> G since npw_k < nfft
1354 :
1355 2 : if (isign==1) then
1356 34169 : do cnt=0,(npw_k * ndat) - 1
1357 34168 : ipw = 1 + MOD(cnt, npw_k)
1358 136672 : gg = kg_k(:,ipw)
1359 649192 : gsq = two_pi**2 * DOT_PRODUCT(gg,MATMUL(Ftest%gmet,gg))
1360 34169 : ug(cnt+1) = DCMPLX(EXP(-gsq), zero)
1361 : end do
1362 : !
1363 : ! Replicate input data
1364 1 : do dat=2,ndat
1365 0 : padat = (dat-1) * npw_k
1366 1 : do ipw=1,npw_k
1367 0 : ug(ipw+padat) = DBLE(dat) * ug(ipw)
1368 : end do
1369 : end do
1370 :
1371 1 : else if (isign==-1) then
1372 :
1373 91 : do i3=0,n3-1
1374 8191 : do i2=0,n2-1
1375 737190 : do i1=0,n1-1
1376 : g0dotr= two_pi*( g0(1)*(i1/DBLE(n1)) &
1377 : +g0(2)*(i2/DBLE(n2)) &
1378 729000 : +g0(3)*(i3/DBLE(n3)) )
1379 729000 : ifft = 1 + i1 + i2*n1 + i3*n2*n3
1380 737100 : ur(ifft)=DCMPLX(DCOS(g0dotr),DSIN(g0dotr))
1381 : end do
1382 : end do
1383 : end do
1384 : !
1385 : ! Replicate input data
1386 1 : do dat=2,ndat
1387 0 : padat = (dat-1)*nfft
1388 1 : do ifft=1,nfft
1389 0 : ur(ifft+padat) = DBLE(dat) * ur(ifft)
1390 : end do
1391 : end do
1392 :
1393 : else
1394 0 : ABI_ERROR(sjoin("Wrong isign:", itoa(isign)))
1395 : end if
1396 :
1397 2 : call cwtime(cpu_time, wall_time, gflops, "start")
1398 :
1399 12 : do icall=1,NCALLS_FOR_TEST
1400 10 : ifft = empty_cache(CACHE_KBSIZE)
1401 :
1402 : !call fftpad(ug,Ftest%ngfft,n1,n2,n3,n4,n5,n6,ndat,Ftest%mgfft,isign,gbound)
1403 12 : if (isign == +1) then
1404 5 : call fft_ug(npw_k,nfft,nspinor1,ndat,Ftest%mgfft,Ftest%ngfft,istwf_k,kg_k,gbound,ug,ur)
1405 : ! Store results at the first call.
1406 5 : if (icall == 1) call xcopy(nfft*ndat,ur,1,results,1)
1407 :
1408 : else
1409 5 : call fft_ur(npw_k,nfft,nspinor1,ndat,Ftest%mgfft,Ftest%ngfft,istwf_k,kg_k,gbound,ur,ug)
1410 : ! Store results at the first call.
1411 5 : if (icall==1) call xcopy(npw_k*ndat,ug,1,results,1)
1412 : end if
1413 : !if (isign==-1) then
1414 : ! write(Ftest%ngfft(7),*)"ngfft, isign ",Ftest%ngfft(7),isign
1415 : ! do idx =1,n4*n5*n6*ndat; write(Ftest%ngfft(7),*)idx,results(idx); end do
1416 : !end if
1417 : end do
1418 :
1419 2 : call cwtime(cpu_time, wall_time, gflops, "stop")
1420 : call Ftprof%init(test_name,Ftest%nthreads,NCALLS_FOR_TEST,ndat,ftest%gpu_option, &
1421 2 : cpu_time,wall_time,gflops,results=results)
1422 :
1423 2 : ABI_FREE(kg_k)
1424 2 : ABI_FREE(gbound)
1425 2 : ABI_FREE(ug)
1426 2 : ABI_FREE(ur)
1427 2 : ABI_FREE(results)
1428 :
1429 4 : end subroutine time_fftu
1430 : !!***
1431 :
1432 : !----------------------------------------------------------------------
1433 :
1434 : !!****f* m_FFT_prof/prof_fourdp
1435 : !! NAME
1436 : !! prof_fourdp
1437 : !!
1438 : !! FUNCTION
1439 : !! Profile fourdp
1440 : !!
1441 : !! INPUTS
1442 : !!
1443 : !! OUTPUT
1444 : !!
1445 : !! SOURCE
1446 :
1447 0 : subroutine prof_fourdp(fft_setups, isign, cplex, necut, ecut_arth, boxcutmin, rprimd, nsym, symrel, MPI_enreg_in)
1448 :
1449 : !Arguments -----------------------------------
1450 : !scalars
1451 : integer,intent(in) :: nsym,isign,cplex,necut
1452 : real(dp),intent(in) :: boxcutmin
1453 : type(MPI_type),intent(in) :: MPI_enreg_in
1454 : !arrays
1455 : integer,intent(in) :: fft_setups(:,:),symrel(3,3,nsym)
1456 : real(dp),intent(in) :: ecut_arth(2)
1457 : real(dp),intent(in) :: rprimd(3,3)
1458 :
1459 : !Local variables-------------------------------
1460 : !scalars
1461 : integer :: iec,nsetups,set,funt
1462 0 : type(FFT_test_t) :: Ftest
1463 0 : type(FFT_prof_t) :: Ftprof
1464 : character(len=500) :: msg,frm,header
1465 : character(len=fnlen) :: fname
1466 : !arrays
1467 0 : integer :: ngfft_ecut(18,necut)
1468 : real(dp),parameter :: k_gamma(3)=zero
1469 0 : real(dp) :: ecut_list(necut)
1470 0 : real(dp),allocatable :: prof_res(:,:,:)
1471 : ! *********************************************************************
1472 :
1473 0 : nsetups = size(fft_setups, dim=2)
1474 0 : ecut_list = arth(ecut_arth(1), ecut_arth(2), necut)
1475 :
1476 : ! Open file and write header with info.
1477 0 : write(fname,'(2(a,i1))')"PROF_fourdp_cplex",cplex,"_isign",isign
1478 0 : if (open_file(fname, msg, newunit=funt) /= 0) then
1479 0 : ABI_ERROR(msg)
1480 : end if
1481 :
1482 0 : write(msg,'(2(a,i0))')"Benchmark: routine = fourdp, cplex =",cplex,", isign=",isign
1483 0 : write(std_out,'(a)')" Running "//TRIM(msg)
1484 :
1485 0 : write(funt,'(a)')"# "//TRIM(msg)
1486 0 : do set=1,nsetups
1487 0 : write(funt,'(a, 6(a,i0))') "#",&
1488 0 : " fftalg = " ,fft_setups(1,set), &
1489 0 : ", fftcache = " ,fft_setups(2,set), &
1490 0 : ", ndat = " ,fft_setups(3,set), &
1491 0 : ", nthreads = " ,fft_setups(4,set), &
1492 0 : ", available = ",fft_setups(5,set), &
1493 0 : ", gpu_option = ",fft_setups(6,set)
1494 : end do
1495 :
1496 0 : ABI_MALLOC(prof_res,(2,necut,nsetups))
1497 :
1498 0 : do set=1,nsetups
1499 0 : do iec=1,necut
1500 0 : call Ftest%init(fft_setups(:,set),k_gamma,ecut_list(iec),boxcutmin,rprimd,nsym,symrel,MPI_enreg_in)
1501 0 : call Ftest%time_fourdp(isign, cplex, header, Ftprof)
1502 :
1503 0 : prof_res(1,iec,set) = Ftprof%cpu_time /Ftprof%ncalls
1504 0 : prof_res(2,iec,set) = Ftprof%wall_time/Ftprof%ncalls
1505 :
1506 : ! Save FFT divisions.
1507 0 : if (set == 1) ngfft_ecut(:,iec) = Ftest%ngfft
1508 :
1509 0 : call Ftprof%free()
1510 0 : call Ftest%free()
1511 : end do
1512 : end do
1513 :
1514 : ! Write the wall-time as a function of ecut.
1515 0 : write(frm,*)"(f7.1,3i4,",nsetups,"(f7.4))"
1516 0 : do iec=1,necut
1517 0 : write(funt,frm) ecut_list(iec),ngfft_ecut(4:6,iec),prof_res(2,iec,:)
1518 : end do
1519 :
1520 0 : close(funt)
1521 0 : ABI_FREE(prof_res)
1522 :
1523 0 : end subroutine prof_fourdp
1524 : !!***
1525 :
1526 : !----------------------------------------------------------------------
1527 :
1528 : !!****f* m_FFT_prof/prof_fourwf
1529 : !! NAME
1530 : !! prof_fourwf
1531 : !!
1532 : !! FUNCTION
1533 : !! profile fourwf
1534 : !!
1535 : !! INPUTS
1536 : !!
1537 : !! OUTPUT
1538 : !!
1539 : !! SOURCE
1540 :
1541 0 : subroutine prof_fourwf(fft_setups, cplex, option, kpoint, necut, ecut_arth, &
1542 0 : boxcutmin, rprimd, nsym, symrel, MPI_enreg_in)
1543 :
1544 : !Arguments -----------------------------------
1545 : !scalars
1546 : integer,intent(in) :: nsym,cplex,necut,option
1547 : real(dp),intent(in) :: boxcutmin
1548 : type(MPI_type),intent(in) :: MPI_enreg_in
1549 : !arrays
1550 : integer,intent(in) :: fft_setups(:,:),symrel(3,3,nsym)
1551 : real(dp),intent(in) :: ecut_arth(2)
1552 : real(dp),intent(in) :: kpoint(3),rprimd(3,3)
1553 :
1554 : !Local variables-------------------------------
1555 : !scalars
1556 : integer :: iec,nsetups,set,funt,istwf_k
1557 0 : type(FFT_test_t) :: Ftest
1558 0 : type(FFT_prof_t) :: Ftprof
1559 : character(len=500) :: msg,frm,header
1560 : character(len=fnlen) :: fname
1561 : !arrays
1562 0 : integer :: ngfft_ecut(18,necut)
1563 0 : real(dp) :: ecut_list(necut)
1564 0 : real(dp),allocatable :: prof_res(:,:,:)
1565 : ! *********************************************************************
1566 :
1567 0 : nsetups = size(fft_setups, dim=2)
1568 0 : ecut_list = arth(ecut_arth(1), ecut_arth(2), necut)
1569 0 : istwf_k = set_istwfk(kpoint)
1570 :
1571 : ! Open file and write header with info.
1572 0 : write(fname,'(3(a,i1))')"PROF_fourwf_cplex",cplex,"_option",option,"_istwfk",istwf_k
1573 0 : if (open_file(fname, msg, newunit=funt) /= 0) then
1574 0 : ABI_ERROR(msg)
1575 : end if
1576 :
1577 0 : write(msg,'(3(a,i1))')"Benchmark: routine = fourwf, cplex = ",cplex,", option= ",option,", istwfk= ",istwf_k
1578 0 : write(std_out,'(a)')" Running "//TRIM(msg)
1579 :
1580 0 : write(funt,'(a)')"# "//TRIM(msg)
1581 0 : do set=1,nsetups
1582 0 : write(funt,'(a,6(a,i0))') "#",&
1583 0 : " fftalg = " ,fft_setups(1,set), &
1584 0 : ", fftcache = " ,fft_setups(2,set), &
1585 0 : ", ndat = " ,fft_setups(3,set), &
1586 0 : ", nthreads = " ,fft_setups(4,set), &
1587 0 : ", available = ",fft_setups(5,set), &
1588 0 : ", gpu_option = ",fft_setups(6,set)
1589 : end do
1590 :
1591 0 : ABI_MALLOC(prof_res,(2,necut,nsetups))
1592 :
1593 0 : do set=1,nsetups
1594 0 : do iec=1,necut
1595 0 : call Ftest%init(fft_setups(:,set),kpoint,ecut_list(iec),boxcutmin,rprimd,nsym,symrel,MPI_enreg_in)
1596 0 : call Ftest%time_fourwf(cplex, option, header, Ftprof)
1597 :
1598 0 : prof_res(1,iec,set) = Ftprof%cpu_time /Ftprof%ncalls
1599 0 : prof_res(2,iec,set) = Ftprof%wall_time/Ftprof%ncalls
1600 :
1601 : ! Save FFT divisions.
1602 0 : if (set == 1) ngfft_ecut(:,iec) = Ftest%ngfft
1603 0 : call Ftprof%free()
1604 0 : call Ftest%free()
1605 : end do
1606 : end do
1607 :
1608 : ! Write the wall-time as a function of ecut.
1609 0 : write(frm,*)"(f7.1,3i4,",nsetups,"(f7.4))"
1610 0 : do iec=1,necut
1611 0 : write(funt,frm) ecut_list(iec),ngfft_ecut(4:6,iec),prof_res(2,iec,:)
1612 : end do
1613 :
1614 0 : close(funt)
1615 0 : ABI_FREE(prof_res)
1616 :
1617 0 : end subroutine prof_fourwf
1618 : !!***
1619 :
1620 : !----------------------------------------------------------------------
1621 :
1622 : !!****f* m_FFT_prof/prof_rhotwg
1623 : !! NAME
1624 : !! prof_rhotwg
1625 : !!
1626 : !! FUNCTION
1627 : !! profile rhotwg
1628 : !!
1629 : !! INPUTS
1630 : !!
1631 : !! OUTPUT
1632 : !!
1633 : !! SOURCE
1634 :
1635 0 : subroutine prof_rhotwg(fft_setups,map2sphere,use_padfft,necut,ecut_arth,osc_ecut,boxcutmin,&
1636 0 : rprimd,nsym,symrel,gmet,MPI_enreg_in)
1637 :
1638 : !Arguments -----------------------------------
1639 : !scalars
1640 : integer,intent(in) :: nsym,necut,map2sphere,use_padfft
1641 : real(dp),intent(in) :: boxcutmin,osc_ecut
1642 : type(MPI_type),intent(in) :: MPI_enreg_in
1643 : !arrays
1644 : integer,intent(in) :: fft_setups(:,:),symrel(3,3,nsym)
1645 : real(dp),intent(in) :: ecut_arth(2)
1646 : real(dp),intent(in) :: rprimd(3,3),gmet(3,3)
1647 :
1648 : !Local variables-------------------------------
1649 : !scalars
1650 : integer :: iec,nsetups,set,funt,osc_npw
1651 0 : type(FFT_test_t) :: Ftest
1652 0 : type(FFT_prof_t) :: Ftprof
1653 : character(len=500) :: msg,frm,header
1654 : character(len=fnlen) :: fname
1655 : !arrays
1656 0 : integer,allocatable :: osc_gvec(:,:)
1657 0 : integer :: ngfft_ecut(18,necut)
1658 : real(dp),parameter :: k_gamma(3)=zero
1659 0 : real(dp) :: ecut_list(necut)
1660 0 : real(dp),allocatable :: prof_res(:,:,:)
1661 : ! *********************************************************************
1662 :
1663 0 : nsetups = size(fft_setups, dim=2)
1664 0 : ecut_list = arth(ecut_arth(1), ecut_arth(2), necut)
1665 :
1666 : ! Open file and write header with info.
1667 0 : write(fname,'(2(a,i1))')"PROF_rhotwg_map2sphere",map2sphere,"_use_padfft",use_padfft
1668 0 : if (open_file(fname, msg, newunit=funt) /= 0) then
1669 0 : ABI_ERROR(msg)
1670 : end if
1671 :
1672 : write(msg,'(2(a,i0),a,f5.1)') &
1673 0 : "Benchmark: routine = rho_tw_g, map2sphere = ",map2sphere,", use_padfft = ",use_padfft,", osc_ecut = ",osc_ecut
1674 0 : write(std_out,'(a)')" Running "//TRIM(msg)
1675 :
1676 0 : write(funt,'(a)')"# "//TRIM(msg)
1677 0 : do set=1,nsetups
1678 0 : write(funt,'(a,6(a,i0))') "#",&
1679 0 : " fftalg = " ,fft_setups(1,set),&
1680 0 : ", fftcache = " ,fft_setups(2,set),&
1681 0 : ", ndat = " ,fft_setups(3,set),&
1682 0 : ", nthreads = " ,fft_setups(4,set),&
1683 0 : ", available = ",fft_setups(5,set),&
1684 0 : ", gpu_option = ",fft_setups(6,set)
1685 : end do
1686 :
1687 0 : call get_kg([zero,zero,zero],1,osc_ecut,gmet,osc_npw,osc_gvec)
1688 : ! TODO should reorder by shells to be consistent with the GW part!
1689 : ! Moreover I guess this ordering is more efficient when we have
1690 : ! to map the box to the G-sphere!
1691 :
1692 0 : ABI_MALLOC(prof_res,(2,necut,nsetups))
1693 :
1694 0 : do set=1,nsetups
1695 0 : do iec=1,necut
1696 0 : call Ftest%init(fft_setups(:,set),k_gamma,ecut_list(iec),boxcutmin,rprimd,nsym,symrel,MPI_enreg_in)
1697 :
1698 0 : call Ftest%time_rhotwg(map2sphere,use_padfft,osc_npw,osc_gvec,header,Ftprof)
1699 :
1700 0 : prof_res(1,iec,set) = Ftprof%cpu_time /Ftprof%ncalls
1701 0 : prof_res(2,iec,set) = Ftprof%wall_time/Ftprof%ncalls
1702 : ! Save FFT divisions.
1703 0 : if (set==1) ngfft_ecut(:,iec) = Ftest%ngfft
1704 :
1705 0 : call Ftprof%free()
1706 0 : call Ftest%free()
1707 : end do
1708 : end do
1709 :
1710 : ! Write the wall-time as a function of ecut.
1711 0 : write(frm,*)"(f7.1,3i4,",nsetups,"(f7.4))"
1712 0 : do iec=1,necut
1713 0 : write(funt,frm) ecut_list(iec),ngfft_ecut(4:6,iec),prof_res(2,iec,:)
1714 : end do
1715 :
1716 0 : close(funt)
1717 0 : ABI_FREE(prof_res)
1718 0 : ABI_FREE(osc_gvec)
1719 :
1720 0 : end subroutine prof_rhotwg
1721 : !!***
1722 :
1723 : !----------------------------------------------------------------------
1724 :
1725 : !!****f* m_FFT_prof/empty_cache
1726 : !! NAME
1727 : !! empty_cache
1728 : !!
1729 : !! FUNCTION
1730 : !! Empty the memory cache
1731 : !!
1732 : !! INPUTS
1733 : !!
1734 : !! OUTPUT
1735 : !!
1736 : !! SOURCE
1737 :
1738 1445 : integer function empty_cache(kbsize) result(fake)
1739 :
1740 : !Arguments -----------------------------------
1741 : integer,intent(in) :: kbsize
1742 :
1743 : !Local variables-------------------------------
1744 : integer :: sz
1745 1445 : real(dp),allocatable :: chunk(:)
1746 : ! *********************************************************************
1747 :
1748 1445 : fake = 0
1749 1445 : if (kbsize <= 0) RETURN
1750 :
1751 0 : sz = int((100._dp * kbsize) / dp)
1752 :
1753 0 : ABI_MALLOC(chunk,(sz))
1754 0 : call random_number(chunk)
1755 0 : fake = int(SUM(chunk)) ! Need a result, otherwise smart compilers may skip the call.
1756 0 : ABI_FREE(chunk)
1757 :
1758 1445 : end function empty_cache
1759 : !!***
1760 :
1761 : !----------------------------------------------------------------------
1762 :
1763 1612 : end module m_FFT_prof
1764 : !!***
|