Eigenvalue SoLvers for Petaflop-Applications (ELPA) 2024.05.001.rc1
Loading...
Searching...
No Matches
global_product_template.F90
Go to the documentation of this file.
1subroutine global_product_&
2&precision&
3&(obj, z, n, mpi_comm_rows, mpi_comm_cols, npc_0, npc_n, success)
4 ! This routine calculates the global product of z.
5 use precision
7 use elpa_mpi
8 use elpa_utilities
9#ifdef WITH_OPENMP_TRADITIONAL
10 !use elpa_omp
11#endif
12 implicit none
13 class(elpa_abstract_impl_t), intent(inout) :: obj
14 integer(kind=ik), intent(in) :: mpi_comm_cols, mpi_comm_rows
15 integer(kind=ik), intent(in) :: npc_0, npc_n
16#ifdef WITH_MPI
17 integer(kind=MPI_KIND) :: mpierr,my_pcolMPI, np_colsMPI, np_rowsMPI
18#endif
19 integer(kind=ik) :: n, my_pcol, np_cols, np_rows
20 real(kind=real_datatype) :: z(n)
21
22 real(kind=real_datatype) :: tmp(n)
23 integer(kind=ik) :: np
24 integer(kind=MPI_KIND) :: allreduce_request1, allreduce_request2
25 logical :: useNonBlockingCollectivesCols
26 logical :: useNonBlockingCollectivesRows
27 integer(kind=c_int) :: non_blocking_collectives_rows, error, &
28 non_blocking_collectives_cols
29 logical :: success
30
31 success = .true.
32
33 call obj%get("nbc_row_global_product", non_blocking_collectives_rows, error)
34 if (error .ne. elpa_ok) then
35 write(error_unit,*) "Problem setting option for non blocking collectives for rows in global_product. Aborting..."
36 success = .false.
37 return
38 endif
39
40 call obj%get("nbc_col_global_product", non_blocking_collectives_cols, error)
41 if (error .ne. elpa_ok) then
42 write(error_unit,*) "Problem setting option for non blocking collectives for cols in global_product. Aborting..."
43 success = .false.
44 return
45 endif
46
47 if (non_blocking_collectives_rows .eq. 1) then
48 usenonblockingcollectivesrows = .true.
49 else
50 usenonblockingcollectivesrows = .false.
51 endif
52
53 if (non_blocking_collectives_cols .eq. 1) then
54 usenonblockingcollectivescols = .true.
55 else
56 usenonblockingcollectivescols = .false.
57 endif
58
59#ifdef WITH_MPI
60 call obj%timer%start("mpi_communication")
61 call mpi_comm_size(int(mpi_comm_rows,kind=mpi_kind) ,np_rowsmpi, mpierr)
62 np_rows = int(np_rowsmpi,kind=c_int)
63
64 call mpi_comm_rank(int(mpi_comm_cols,kind=mpi_kind) ,my_pcolmpi, mpierr)
65 my_pcol = int(my_pcolmpi,kind=c_int)
66 call mpi_comm_size(int(mpi_comm_cols,kind=mpi_kind) ,np_colsmpi, mpierr)
67 np_cols = int(np_colsmpi,kind=c_int)
68
69 call obj%timer%stop("mpi_communication")
70#endif
71
72 if (npc_n==1 .and. np_rows==1) return ! nothing to do
73
74 ! Do an mpi_allreduce over processor rows
75#ifdef WITH_MPI
76
77 if (usenonblockingcollectivesrows) then
78 call obj%timer%start("mpi_nbc_communication")
79 call mpi_iallreduce(z, tmp, int(n,kind=mpi_kind), mpi_real_precision, mpi_prod, int(mpi_comm_rows,kind=mpi_kind), &
80 allreduce_request1, mpierr)
81 call mpi_wait(allreduce_request1, mpi_status_ignore, mpierr)
82 call obj%timer%stop("mpi_nbc_communication")
83 else
84 call obj%timer%start("mpi_communication")
85 call mpi_allreduce(z, tmp, int(n,kind=mpi_kind), mpi_real_precision, mpi_prod, int(mpi_comm_rows,kind=mpi_kind), &
86 mpierr)
87 call obj%timer%stop("mpi_communication")
88 endif
89#else /* WITH_MPI */
90 tmp = z
91#endif /* WITH_MPI */
92
93 ! If only 1 processor column, we are done
94 if (npc_n==1) then
95 z(:) = tmp(:)
96 return
97 endif
98
99 ! If all processor columns are involved, we can use mpi_allreduce
100 if (npc_n==np_cols) then
101#ifdef WITH_MPI
102 if (usenonblockingcollectivescols) then
103 call obj%timer%start("mpi_nbc_communication")
104 call mpi_iallreduce(tmp, z, int(n,kind=mpi_kind), mpi_real_precision, mpi_prod, int(mpi_comm_cols,kind=mpi_kind), &
105 allreduce_request2, mpierr)
106 call mpi_wait(allreduce_request2, mpi_status_ignore, mpierr)
107 call obj%timer%stop("mpi_nbc_communication")
108 else
109 call obj%timer%start("mpi_communication")
110 call mpi_allreduce(tmp, z, int(n,kind=mpi_kind), mpi_real_precision, mpi_prod, int(mpi_comm_cols,kind=mpi_kind), &
111 mpierr)
112 call obj%timer%stop("mpi_communication")
113 endif
114#else /* WITH_MPI */
115 z = tmp
116#endif /* WITH_MPI */
117 return
118 endif
119
120 ! We send all vectors to the first proc, do the product there
121 ! and redistribute the result.
122
123 if (my_pcol == npc_0) then
124 z(1:n) = tmp(1:n)
125 do np = npc_0+1, npc_0+npc_n-1
126#ifdef WITH_MPI
127 call obj%timer%start("mpi_communication")
128 call mpi_recv(tmp, int(n,kind=mpi_kind), mpi_real_precision, int(np,kind=mpi_kind), 1117_mpi_kind, &
129 int(mpi_comm_cols,kind=mpi_kind), mpi_status_ignore, mpierr)
130 call obj%timer%stop("mpi_communication")
131#else /* WITH_MPI */
132 tmp(1:n) = z(1:n)
133#endif /* WITH_MPI */
134 z(1:n) = z(1:n)*tmp(1:n)
135 enddo
136 do np = npc_0+1, npc_0+npc_n-1
137#ifdef WITH_MPI
138 call obj%timer%start("mpi_communication")
139 call mpi_send(z, int(n,kind=mpi_kind), mpi_real_precision, int(np,kind=mpi_kind), 1118_mpi_kind, &
140 int(mpi_comm_cols,kind=mpi_kind), mpierr)
141 call obj%timer%stop("mpi_communication")
142#else
143#endif /* WITH_MPI */
144 enddo
145 else
146#ifdef WITH_MPI
147 call obj%timer%start("mpi_communication")
148 call mpi_send(tmp, int(n,kind=mpi_kind), mpi_real_precision, int(npc_0,kind=mpi_kind), 1117_mpi_kind, &
149 int(mpi_comm_cols,kind=mpi_kind), mpierr)
150 call mpi_recv(z, int(n,kind=mpi_kind), mpi_real_precision, int(npc_0,kind=mpi_kind), 1118_mpi_kind, &
151 int(mpi_comm_cols,kind=mpi_kind), mpi_status_ignore, mpierr)
152 call obj%timer%stop("mpi_communication")
153#else /* WITH_MPI */
154 z(1:n) = tmp(1:n)
155#endif /* WITH_MPI */
156
157 endif
158end subroutine global_product_&
159 &precision
Fortran module to provide an abstract definition of the implementation. Do not use directly....
Definition elpa_abstract_impl.F90:50
Definition elpa_abstract_impl.F90:73