11#include " pw_basis.h"
22#include " source_base/global_function.h"
33#include " source_base/timer.h"
4+ #include < algorithm>
45#include < typeinfo>
56
67namespace ModulePW
78{
9+ namespace detail
10+ {
11+ template <typename T>
12+ inline void copy_complex_buffer (const std::complex <T>* in, std::complex <T>* out, const int count)
13+ {
14+ if (count <= 0 )
15+ {
16+ return ;
17+ }
18+
19+ std::copy_n (in, count, out);
20+ }
21+
22+ // Top-level transform copies own the OpenMP parallel region; gather/scatter
23+ // loops call the non-parallel helper inside their existing parallel regions.
24+ template <typename T>
25+ inline void copy_complex_buffer_parallel (const std::complex <T>* in, std::complex <T>* out, const int count)
26+ {
27+ constexpr int chunk_size = 1024 ;
28+ if (count <= chunk_size)
29+ {
30+ copy_complex_buffer (in, out, count);
31+ return ;
32+ }
33+
34+ #ifdef _OPENMP
35+ #pragma omp parallel for schedule(static)
36+ for (int offset = 0 ; offset < count; offset += chunk_size)
37+ {
38+ const int chunk_count = std::min (chunk_size, count - offset);
39+ std::copy_n (in + offset, chunk_count, out + offset);
40+ }
41+ #else
42+ copy_complex_buffer (in, out, count);
43+ #endif
44+ }
45+ } // namespace detail
46+
847/* *
948 * @brief gather planes and scatter sticks
1049 * @param in: (nplane,fftny,fftnx)
@@ -21,16 +60,18 @@ void PW_Basis::gatherp_scatters(std::complex<T>* in, std::complex<T>* out) const
2160 const int nst_ = this ->nst ;
2261 const int nz_ = this ->nz ;
2362 const int * istot2ixy_ = this ->istot2ixy ;
63+ ModuleBase::timer::start (this ->classname , " gatherp_copy_serial" );
2464#ifdef _OPENMP
2565#pragma omp parallel for
2666#endif
2767 for (int is = 0 ; is < nst_ ; ++is)
2868 {
2969 int ixy = istot2ixy_[is];
30- std::complex <T> * outp = &out[is*nz_];
31- std::complex <T> * inp = &in[ixy*nz_];
32- std::memcpy (outp, inp , nz_ * sizeof (std:: complex <T>) );
70+ std::complex <T>* outp = &out[is*nz_];
71+ const std::complex <T>* inp = &in[ixy*nz_];
72+ detail::copy_complex_buffer (inp, outp , nz_);
3373 }
74+ ModuleBase::timer::end (this ->classname , " gatherp_copy_serial" );
3475 return ;
3576 }
3677
@@ -41,16 +82,18 @@ void PW_Basis::gatherp_scatters(std::complex<T>* in, std::complex<T>* out) const
4182 const int nstot_gps = this ->nstot ;
4283 const int nplane_gps = this ->nplane ;
4384 const int * istot2ixy_gps = this ->istot2ixy ;
85+ ModuleBase::timer::start (this ->classname , " gatherp_copy_pack" );
4486#ifdef _OPENMP
4587 #pragma omp parallel for
4688#endif
4789 for (int istot = 0 ; istot < nstot_gps; ++istot)
4890 {
4991 int ixy = istot2ixy_gps[istot];
50- std::complex <T> * outp = &out[istot * nplane_gps];
51- std::complex <T> * inp = &in[ixy * nplane_gps];
52- std::memcpy (outp, inp , nplane_gps * sizeof (std:: complex <T>) );
92+ std::complex <T>* outp = &out[istot * nplane_gps];
93+ const std::complex <T>* inp = &in[ixy * nplane_gps];
94+ detail::copy_complex_buffer (inp, outp , nplane_gps);
5395 }
96+ ModuleBase::timer::end (this ->classname , " gatherp_copy_pack" );
5497
5598 // exchange data
5699 // (nplane,nstot) to (numz[ip],ns, poolnproc)
@@ -74,6 +117,7 @@ void PW_Basis::gatherp_scatters(std::complex<T>* in, std::complex<T>* out) const
74117 const int * numz_gps = this ->numz ;
75118 const int * startg_gps = this ->startg ;
76119 const int * startz_gps = this ->startz ;
120+ ModuleBase::timer::start (this ->classname , " gatherp_copy_unpack" );
77121#ifdef _OPENMP
78122 #pragma omp parallel for collapse(2)
79123#endif
@@ -84,11 +128,12 @@ void PW_Basis::gatherp_scatters(std::complex<T>* in, std::complex<T>* out) const
84128 int nzip = numz_gps[ip];
85129 std::complex <T> *outp0 = &out[startz_gps[ip]];
86130 std::complex <T> *inp0 = &in[startg_gps[ip]];
87- std::complex <T> * outp = &outp0[is * nz_gps];
88- std::complex <T> * inp = &inp0[is * nzip ];
89- std::memcpy (outp, inp , nzip * sizeof (std:: complex <T>) );
131+ std::complex <T>* outp = &outp0[is * nz_gps];
132+ const std::complex <T>* inp = &inp0[is * nzip ];
133+ detail::copy_complex_buffer (inp, outp , nzip);
90134 }
91135 }
136+ ModuleBase::timer::end (this ->classname , " gatherp_copy_unpack" );
92137#endif
93138 return ;
94139}
@@ -109,24 +154,28 @@ void PW_Basis::gathers_scatterp(std::complex<T>* in, std::complex<T>* out) const
109154 const int nst_ = this ->nst ;
110155 const int nz_ = this ->nz ;
111156 const int * istot2ixy_ = this ->istot2ixy ;
157+ ModuleBase::timer::start (this ->classname , " gathers_zero_serial" );
112158#ifdef _OPENMP
113159#pragma omp parallel for schedule(static)
114160#endif
115161 for (int i = 0 ; i < nrxx_; ++i)
116162 {
117163 out[i] = std::complex <T>(0 , 0 );
118164 }
165+ ModuleBase::timer::end (this ->classname , " gathers_zero_serial" );
119166
167+ ModuleBase::timer::start (this ->classname , " gathers_copy_serial" );
120168#ifdef _OPENMP
121169#pragma omp parallel for
122170#endif
123171 for (int is = 0 ; is < nst_ ; ++is)
124172 {
125173 int ixy = istot2ixy_[is];
126- std::complex <T> * outp = &out[ixy*nz_];
127- std::complex <T> * inp = &in[is*nz_];
128- std::memcpy (outp, inp , nz_ * sizeof (std:: complex <T>) );
174+ std::complex <T>* outp = &out[ixy*nz_];
175+ const std::complex <T>* inp = &in[is*nz_];
176+ detail::copy_complex_buffer (inp, outp , nz_);
129177 }
178+ ModuleBase::timer::end (this ->classname , " gathers_copy_serial" );
130179 return ;
131180 }
132181
@@ -140,6 +189,7 @@ void PW_Basis::gathers_scatterp(std::complex<T>* in, std::complex<T>* out) const
140189 const int * numz_ = this ->numz ;
141190 const int * startg_ = this ->startg ;
142191 const int * startz_ = this ->startz ;
192+ ModuleBase::timer::start (this ->classname , " gathers_copy_pack" );
143193#ifdef _OPENMP
144194 #pragma omp parallel for collapse(2)
145195#endif
@@ -150,11 +200,12 @@ void PW_Basis::gathers_scatterp(std::complex<T>* in, std::complex<T>* out) const
150200 int nzip = numz_[ip];
151201 std::complex <T> *outp0 = &out[startg_[ip]];
152202 std::complex <T> *inp0 = &in[startz_[ip]];
153- std::complex <T> * outp = &outp0[is * nzip];
154- std::complex <T> * inp = &inp0[is * nz_ ];
155- std::memcpy (outp, inp , nzip * sizeof (std:: complex <T>) );
203+ std::complex <T>* outp = &outp0[is * nzip];
204+ const std::complex <T>* inp = &inp0[is * nz_ ];
205+ detail::copy_complex_buffer (inp, outp , nzip);
156206 }
157207 }
208+ ModuleBase::timer::end (this ->classname , " gathers_copy_pack" );
158209
159210 // exchange data
160211 // (numz[ip],ns, poolnproc) to (nplane,nstot)
@@ -172,28 +223,32 @@ void PW_Basis::gathers_scatterp(std::complex<T>* in, std::complex<T>* out) const
172223 }
173224
174225 const int nrxx_gsp = this ->nrxx ;
226+ ModuleBase::timer::start (this ->classname , " gathers_zero_mpi" );
175227#ifdef _OPENMP
176228 #pragma omp parallel for schedule(static)
177229#endif
178230 for (int i = 0 ; i < nrxx_gsp; ++i)
179231 {
180232 out[i] = std::complex <T>(0 , 0 );
181233 }
234+ ModuleBase::timer::end (this ->classname , " gathers_zero_mpi" );
182235 // change (nplane,nstot) to (nplane fftnxy)
183236 const int nstot = this ->nstot ;
184237 const int nplane = this ->nplane ;
185238 const int * istot2ixy = this ->istot2ixy ;
239+ ModuleBase::timer::start (this ->classname , " gathers_copy_unpack" );
186240#ifdef _OPENMP
187241#pragma omp parallel for
188242#endif
189243 for (int istot = 0 ;istot < nstot; ++istot)
190244 {
191245 int ixy = istot2ixy[istot];
192246 // int ixy = (ixy / fftny)*ny + ixy % fftny;
193- std::complex <T> * outp = &out[ixy * nplane];
194- std::complex <T> * inp = &in[istot * nplane];
195- std::memcpy (outp, inp , nplane * sizeof (std:: complex <T>) );
247+ std::complex <T>* outp = &out[ixy * nplane];
248+ const std::complex <T>* inp = &in[istot * nplane];
249+ detail::copy_complex_buffer (inp, outp , nplane);
196250 }
251+ ModuleBase::timer::end (this ->classname , " gathers_copy_unpack" );
197252#endif
198253 return ;
199254}
0 commit comments