Skip to content

Commit b337fa8

Browse files
committed
...EJB
1 parent 346ae3b commit b337fa8

3 files changed

Lines changed: 196 additions & 48 deletions

File tree

Nwpw/nwpwlib/lattice/PGrid.cpp

Lines changed: 150 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -856,12 +856,13 @@ void PGrid::cc_pack_ndot(const int nb, const int nn, double *a, double *b, doubl
856856
{
857857
int one = 1;
858858
// int ng = 2*(nida[nb]+nidb[nb]);
859-
int ng = 2 * (nida[nb] + nidb[nb]);
860-
int ng0 = 2 * nida[nb];
859+
int ng = 2*(nida[nb] + nidb[nb]);
860+
int ng0 = 2*nida[nb];
861861

862-
for (int i = 0; i < nn; ++i) {
863-
sum[i] = 2.0 * DDOT_PWDFT(ng, &(a[i * ng]), one, b, one);
864-
sum[i] -= DDOT_PWDFT(ng0, &(a[i * ng]), one, b, one);
862+
for (size_t i=0; i<nn; ++i)
863+
{
864+
sum[i] = 2.0*DDOT_PWDFT(ng, &(a[i * ng]), one, b, one);
865+
sum[i] -= DDOT_PWDFT(ng0, &(a[i * ng]), one, b, one);
865866
}
866867

867868
parall->Vector_SumAll(1, nn, sum);
@@ -3879,17 +3880,36 @@ void PGrid::tc_pack_Mul(const int nb, const double *a, double *c) {
38793880
* PGrid:tcc_pack_aMulAdd *
38803881
* *
38813882
********************************/
3882-
void PGrid::tcc_pack_aMulAdd(const int nb, const double alpha, const double *a, const double *b, double *c)
3883+
/**
3884+
* @brief Performs an interleaved multiply-accumulate: c = c + (alpha * a[i] * b[2i:2i+1])
3885+
*
3886+
* This function scales the components of the interleaved array 'b' by the scalar
3887+
* value 'a[i]' and the global constant 'alpha', adding the result to 'c'.
3888+
*
3889+
* @param nb The index of the band/neighboring block.
3890+
* @param alpha A global scaling factor.
3891+
* @param a Pointer to input real scalars (Size: N).
3892+
* @param b Pointer to interleaved input [Re, Im, Re, Im...] (Size: 2N).
3893+
* @param c Pointer to output array for accumulation (Size: 2N).
3894+
*
3895+
* @note Use of __restrict__ allows the compiler to use SIMD vectorization.
3896+
*/
3897+
void PGrid::tcc_pack_aMulAdd(const int nb, const double alpha,
3898+
const double *__restrict__ a,
3899+
const double *__restrict__ b,
3900+
double *__restrict__ c)
38833901
{
3884-
int i, ii;
3885-
int ng = nida[nb] + nidb[nb];
3902+
const size_t ng = nida[nb] + nidb[nb];
38863903

3887-
ii=0;
3888-
for (i=0; i<ng; ++i)
3904+
for (size_t i = 0; i < ng; ++i)
38893905
{
3890-
c[ii] += alpha*b[ii] * a[i];
3891-
c[ii+1] += alpha*b[ii+1]*a[i];
3892-
ii += 2;
3906+
// Calculate the effective weight once per scalar element
3907+
const double weight = alpha * a[i];
3908+
const size_t idx = 2 * i;
3909+
3910+
// Perform the accumulation
3911+
c[idx] += weight * b[idx];
3912+
c[idx + 1] += weight * b[idx + 1];
38933913
}
38943914
}
38953915

@@ -3898,19 +3918,39 @@ void PGrid::tcc_pack_aMulAdd(const int nb, const double alpha, const double *a,
38983918
* PGrid:tcc_pack_iMul *
38993919
* *
39003920
********************************/
3901-
void PGrid::tcc_pack_iMul(const int nb, const double *a, const double *b,
3902-
double *c) {
3903-
int i, ii;
3904-
int ng = nida[nb] + nidb[nb];
3921+
/**
3922+
* @brief Performs an interleaved real-to-complex expansion and multiplication.
3923+
*
3924+
* Calculates: i * a[i] * (b_re[i] + i * b_im[i])
3925+
* = (-a[i] * b_im[i]) + i * (a[i] * b_re[i])
3926+
*
3927+
* @param nb The index of the band/neighboring block.
3928+
* @param a Pointer to input real scalars (Size: N).
3929+
* @param b Pointer to interleaved input [Re, Im, Re, Im...] (Size: 2N).
3930+
* @param c Pointer to output expanded components (Size: 2N).
3931+
*
3932+
* @note The arrays 'b' and 'c' must be of size at least 2*(nida[nb]+nidb[nb]).
3933+
*/
3934+
void PGrid::tcc_pack_iMul(const int nb, const double *__restrict__ a, const double *__restrict__ b, double *__restrict__ c)
3935+
{
3936+
const size_t ng = nida[nb] + nidb[nb];
39053937

3906-
ii = 0;
3907-
for (i = 0; i < ng; ++i) {
3908-
c[ii] = -b[ii + 1] * a[i];
3909-
c[ii + 1] = b[ii] * a[i];
3910-
ii += 2;
3911-
}
3938+
// Using __restrict__ (if using GCC/Clang/MSVC) tells the compiler
3939+
// that the pointers do not overlap, enabling much better SIMD optimization.
3940+
3941+
for (size_t i = 0; i < ng; ++i)
3942+
{
3943+
const double scalar = a[i];
3944+
const size_t base_idx = 2 * i;
3945+
3946+
// Real part of result: -a * Im(b)
3947+
c[base_idx] = -scalar * b[base_idx + 1];
3948+
// Imaginary part of result: a * Re(b)
3949+
c[base_idx + 1] = scalar * b[base_idx];
3950+
}
39123951
}
39133952

3953+
39143954
/*******************************************
39153955
* *
39163956
* PGrid:tcr_pack_iMul_unpack_fft *
@@ -3956,19 +3996,37 @@ void PGrid::tcr_pack_iMul_unpack_fft(const int nb, const double *a, const double
39563996
* PGrid:tc_pack_iMul *
39573997
* *
39583998
********************************/
3959-
void PGrid::tc_pack_iMul(const int nb, const double *a, double *c)
3999+
/**
4000+
* @brief Performs an in-place interleaved complex rotation and scaling.
4001+
*
4002+
* Computes: c[2i : 2i+1] = c[2i : 2i+1] * (i * a[i])
4003+
* Which expands to:
4004+
* c[2i] = -a[i] * Im(c_old)
4005+
* c[2i+1] = a[i] * Re(c_old)
4006+
*
4007+
* @param nb The index of the band/neighboring block.
4008+
* @param a Pointer to input real scalars (Size: N).
4009+
* @param c Pointer to interleaved complex array to be modified in-place (Size: 2N).
4010+
*
4011+
* @note Use of __restrict__ is critical here to allow the compiler to
4012+
* vectorize despite 'a' and 'c' being different pointers.
4013+
*/
4014+
void PGrid::tc_pack_iMul(const int nb, const double *__restrict__ a, double *__restrict__ c)
39604015
{
3961-
double x, y;
3962-
int ng = nida[nb] + nidb[nb];
3963-
int ii = 0;
3964-
for (auto i=0; i<ng; ++i)
4016+
const size_t ng = nida[nb] + nidb[nb];
4017+
4018+
for (size_t i = 0; i < ng; ++i)
39654019
{
3966-
x = c[ii];
3967-
y = c[ii+1];
3968-
3969-
c[ii] = -y*a[i];
3970-
c[ii+1] = x*a[i];
3971-
ii += 2;
4020+
const size_t idx = 2 * i;
4021+
const double scale = a[i];
4022+
4023+
// We must capture the original values before overwriting c[idx]
4024+
// This is essentially what your x and y did, but more explicit.
4025+
const double re = c[idx];
4026+
const double im = c[idx + 1];
4027+
4028+
c[idx] = -scale * im;
4029+
c[idx + 1] = scale * re;
39724030
}
39734031
}
39744032

@@ -3977,6 +4035,19 @@ void PGrid::tc_pack_iMul(const int nb, const double *a, double *c)
39774035
* PGrid:ttc_pack_MulSum2 *
39784036
* *
39794037
********************************/
4038+
/**
4039+
* @brief Performs weighted accumulation into interleaved array: c = c + (b * a[i])
4040+
*
4041+
* For each index i from 0 to ng-1:
4042+
* c[2i] += b[2i] * a[i]
4043+
* c[2i+1] += b[2i+1] * a[i]
4044+
*
4045+
* @param nb The index of the band/neighboring block.
4046+
* @param a Pointer to input real scalars (Size: N).
4047+
* @param b Pointer to interleaved input array (Size: 2N).
4048+
* @param c Pointer to output array for accumulation (Size: Must be at least 2N).
4049+
*
4050+
*/
39804051
void PGrid::tcc_pack_MulSum2(const int nb, const double *a, const double *b, double *c)
39814052
{
39824053
int ng = nida[nb] + nidb[nb];
@@ -4035,27 +4106,65 @@ double PGrid::ttt_pack_MulDot(const int nb, const double *a, const double *b, co
40354106
* PGrid:cc_pack_Sum2 *
40364107
* *
40374108
********************************/
4038-
void PGrid::cc_pack_Sum2(const int nb, const double *a, double *b)
4109+
/**
4110+
* @brief Performs vector addition in-place: b = b + a.
4111+
*
4112+
* This function adds elements of array 'a' to array 'b'.
4113+
*
4114+
* @param nb The index of the band/neighboring block.
4115+
* @param a Pointer to input array (Size: ng).
4116+
* @param b Pointer to output array (Size: ng) - modified in-place.
4117+
*
4118+
* @note Using __restrict__ is critical here to enable SIMD vectorization.
4119+
*/
4120+
void PGrid::cc_pack_Sum2(const int nb, const double *__restrict__ a, double *__restrict__ b)
40394121
{
4040-
int ng = 2*(nida[nb] + nidb[nb]);
4122+
// Use size_t to prevent overflow on large datasets
4123+
const size_t ng = 2 * (static_cast<size_t>(nida[nb]) + static_cast<size_t>(nidb[nb]));
40414124

4042-
for (auto i=0; i<ng; ++i)
4125+
// The compiler can now use AVX/SSE instructions to add 4-8 doubles at a time
4126+
for (size_t i = 0; i < ng; ++i)
4127+
{
40434128
b[i] += a[i];
4129+
}
40444130
}
40454131

4132+
40464133
/********************************
40474134
* *
40484135
* PGrid:cccc_pack_Sum *
40494136
* *
40504137
********************************/
4051-
void PGrid::cccc_pack_Sum(const int nb, const double *a, const double *b, const double *c, double *d)
4138+
/**
4139+
* @brief Performs element-wise sum of three arrays into a fourth: d = a + b + c.
4140+
*
4141+
* This function is a high-throughput streaming operation.
4142+
*
4143+
* @param nb The index of the band/neighboring block.
4144+
* @param a Pointer to input array 1 (Size: ng).
4145+
* @param b Pointer to input array 2 (Size: ng).
4146+
* @param c Pointer to input array 3 (Size: ng).
4147+
* @param d Pointer to output array (Size: ng) - modified in-place.
4148+
*
4149+
* @note Using __restrict__ is critical here to allow the compiler to use SIMD.
4150+
*/
4151+
void PGrid::cccc_pack_Sum(const int nb,
4152+
const double *__restrict__ a,
4153+
const double *__restrict__ b,
4154+
const double *__restrict__ c,
4155+
double *__restrict__ d)
40524156
{
4053-
int ng = 2*(nida[nb] + nidb[nb]);
4157+
// Use size_t to prevent overflow on very large grids
4158+
const size_t ng = 2 * (static_cast<size_t>(nida[nb]) + static_cast<size_t>(nidb[nb]));
40544159

4055-
for (auto i=0; i<ng; ++i)
4056-
d[i] = (a[i] + b[i] + c[i]);
4160+
// The compiler can now use AVX instructions to process multiple elements per cycle
4161+
for (size_t i = 0; i < ng; ++i)
4162+
{
4163+
d[i] = a[i] + b[i] + c[i];
4164+
}
40574165
}
40584166

4167+
40594168
/********************************
40604169
* *
40614170
* PGrid:c_pack_addzeros *

Nwpw/nwpwlib/psp_library/Psp1d_Hamann.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1488,7 +1488,8 @@ void Psp1d_Hamann::vpp2_generate_stress_ray(Parallel *myparall,
14881488
const double a = -sn[i]/(q*q) + rho[i]*cs[i]/q;
14891489
f[i] = a * wp[i + indx[n + 0*5]*nrho] * vp[i + 0*nrho];
14901490
}
1491-
dvnl_ray[0*lmaxnray + k1 + indx[n + 0*5]*nray] = P0 * util_simpson(nrho, f, drho) / q;
1491+
//dvnl_ray[0*lmaxnray + k1 + indx[n + 0*5]*nray] = P0 * util_simpson(nrho, f, drho) / q;
1492+
dvnl_ray[0*lmaxnray + k1 + indx[n + 0*5]*nray] = P0 * util_simpson(nrho, f, drho);
14921493

14931494
/* B-term for l=0 is typically zero/unused; keep if your formulation requires it.
14941495
Here we leave dvnl_ray[1*...] as already zeroed. */
@@ -1892,6 +1893,11 @@ void Psp1d_Hamann::vpp2_generate_stress_spline(PGrid *mygrid, int nray, double *
18921893
const double DD = util_splint(G_ray, &(dvnlDD[ch*nray]), &(dvnlDD_splineray[ch*nray]), nray, nx, q);
18931894

18941895
emit(D, DD, 1.0, 0.0, 0.0, 0.0);
1896+
1897+
//--lcount;
1898+
//dvnl[k + (0 + 3*lcount)*npack1] = D*ux;
1899+
//dvnl[k + (1 + 3*lcount)*npack1] = D*uy;
1900+
//dvnl[k + (2 + 3*lcount)*npack1] = D*uz;
18951901
}
18961902
}
18971903
}

Nwpw/pspw/lib/psp/Pseudopotential.cpp

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,6 +1544,9 @@ static void vpp_generate(PGrid *mygrid, char *pspname, char *fname, char *commen
15441544
mygrid->t_read(5, tmp2, -1);
15451545
mygrid->t_pack(1, tmp2);
15461546
mygrid->tt_pack_copy(1, tmp2, &prj[(i+3*l) * mygrid->npack(1)]);
1547+
1548+
double sum = mygrid->tt_pack_dot(1, tmp2,tmp2);
1549+
std::cout << "read dvnl, i=" << i << " l=" << l << " dvnl|dvnl=" << sum << std::endl;
15471550
}
15481551
}
15491552
if (*semicore)
@@ -1744,6 +1747,10 @@ static void vpp2_write(PGrid *mygrid, char *fname2, char *comment, int psp_type,
17441747
for (auto i=0; i<3; ++i)
17451748
{
17461749
mygrid->tt_pack_copy(1, &prj[(i + 3*l)*mygrid->npack(1)], tmp2);
1750+
1751+
double sum = mygrid->tt_pack_dot(1, tmp2,tmp2);
1752+
std::cout << "write dvnl, i=" << i << " l=" << l << " dvnl|dvnl=" << sum << std::endl;
1753+
17471754
mygrid->t_unpack(1, tmp2);
17481755
mygrid->t_write_buffer(6, tmp2, 0);
17491756
}
@@ -1853,6 +1860,14 @@ static void vpp2_generate(// input
18531860
psp1d.vpp2_generate_stress_spline(mygrid, nray, G_ray, dvl_ray, dvnl_ray,
18541861
rho_sc_k_ray, dvl, *dvnl, *dncore);
18551862

1863+
double sum = mygrid->tt_pack_dot(1, *dvnl,*dvnl);
1864+
std::cout << "generate dvnl, l=" << 0 << " dvnl|dvnl=" << sum << std::endl;
1865+
double sum1 = mygrid->tt_pack_dot(1, *dvnl+(mygrid->npack(1)),*dvnl+(mygrid->npack(1)) );
1866+
std::cout << "generate dvnl, l=" << 1 << " dvnl|dvnl=" << sum1 << std::endl;
1867+
double sum2 = mygrid->tt_pack_dot(1, *dvnl+2*(mygrid->npack(1)),*dvnl+2*(mygrid->npack(1)) );
1868+
std::cout << "generate dvnl, l=" << 2 << " dvnl|dvnl=" << sum2 << std::endl;
1869+
double sum3 = mygrid->tt_pack_dot(1, *dvnl+3*(mygrid->npack(1)),*dvnl+3*(mygrid->npack(1)) );
1870+
std::cout << "generate dvnl, l=" << 3 << " dvnl|dvnl=" << sum3 << std::endl;
18561871

18571872
/* deallocate ray formatted grids */
18581873
delete[] rho_sc_k_ray;
@@ -3851,7 +3866,7 @@ void Pseudopotential::v_nonlocal_euv(const double *psi, double *stress, double *
38513866

38523867

38533868
//**** calculate dF^(lm)_I/dhus ****
3854-
for (auto l=0; l < nprj[ia]; ++l)
3869+
for (auto l=0; l<nprj[ia]; ++l)
38553870
{
38563871
bool sd_function = !(l_projector[ia][l] & 1);
38573872

@@ -3861,21 +3876,33 @@ void Pseudopotential::v_nonlocal_euv(const double *psi, double *stress, double *
38613876
auto dvnlprj = dvnl[ia] + s*npack1 + l*3*npack1;
38623877
auto prj = prjtmp + (l*npack2) + u*nprj[ia]*npack2 + s*3*nprj[ia]*npack2;
38633878

3879+
double sum = mypneb->tt_pack_dot(1, dvnlprj, dvnlprj);
3880+
std::cout << "ii=" << ii << " s=" << s << " l=" << l << " sum=" << sum << std::endl;
3881+
38643882
mypneb->ttt_pack_Mul(1, dvnlprj, g_segments[u], tmp2);
38653883

3884+
double sum2= mypneb->tt_pack_dot(1, tmp2, tmp2);
3885+
std::cout << "ii=" << ii << " s=" << s << " u=" << u << " l=" << l << " sum2=" << sum2 << std::endl;
3886+
38663887
if (sd_function)
38673888
mypneb->tcc_pack_Mul(1, tmp2, exi, prj);
38683889
else
38693890
mypneb->tcc_pack_iMul(1, tmp2, exi, prj);
38703891

3871-
//mypneb->cc_pack_ndot(1,nn psi,prj, sw3+u*nn+s*3*nn);
3892+
mypneb->cc_pack_ndot(1,nn,const_cast<double*>(psi),prj, sw3+u*nn+s*3*nn);
38723893
}
3873-
}
3874-
mypneb->cc_pack_inprjdot(1, nn, 9*nprj[ia], const_cast<double*>(psi), prjtmp, sw3);
3894+
3895+
std::cout << "ii=" << ii << " sw2= ";
3896+
for (auto k = 0; k<nn*nprj[ia]; ++k)
3897+
std::cout << sw2[k] << " " ;
3898+
std::cout << std::endl;
3899+
3900+
std::cout << "ii=" << ii << " l=" << l << " sw3= ";
3901+
for (auto k = 0; k<9*nn; ++k)
3902+
std::cout << sw3[k] << " " ;
3903+
std::cout << std::endl;
38753904

38763905

3877-
for (auto l=0; l<nprj[ia]; ++l)
3878-
{
38793906
for (size_t i=0; i<nn; ++i)
38803907
{
38813908
// Pre-calculate the part that only depends on band and l
@@ -3886,8 +3913,14 @@ void Pseudopotential::v_nonlocal_euv(const double *psi, double *stress, double *
38863913
{
38873914
//Bus[u+3*s] -= weight * sw3[i + u*nn + s*3*nn];
38883915
Bus[s+3*u] -= weight * sw3[i + u*nn + s*3*nn];
3916+
std::cout << "i=" << i << "u=" << u << "s=" << s << " weight=" << weight << " sw3=" << sw3[i+u*nn+s*3*nn] << " bb=" << Bus[s+3*u] << std::endl;
38893917
}
38903918
}
3919+
3920+
std::cout << "ii=" << ii << " l=" << l << " Bus= ";
3921+
for (auto k = 0; k<9; ++k)
3922+
std::cout << Bus[k] << " " ;
3923+
std::cout << std::endl;
38913924
}
38923925

38933926

0 commit comments

Comments
 (0)