2026PKUCourseHW5:使用 std::mt19937 替代 rand() 以提高浮点数精度#7137
2026PKUCourseHW5:使用 std::mt19937 替代 rand() 以提高浮点数精度#7137Tornado1016 wants to merge 1 commit intodeepmodeling:developfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR modernizes stochastic-orbital random number generation in the SDFT PW module by introducing a std::mt19937 RNG in Stochastic_WF, aiming to improve reproducibility/quality over rand().
Changes:
- Adds a
std::mt19937RNG member toStochastic_WFand seeds it ininit_sto_orbitals. - Replaces
rand()-based phase/sign generation inupdate_sto_orbitalswithstd::uniform_real_distribution/std::bernoulli_distribution. - Adjusts some device-type checks to explicitly use the templated
get_device_type<Device>(...)form.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| source/source_pw/module_stodft/sto_wf.h | Adds an RNG member to Stochastic_WF. |
| source/source_pw/module_stodft/sto_wf.cpp | Seeds and uses std::mt19937 + standard distributions in stochastic orbital generation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| private: | ||
| // random number generator | ||
| std::mt19937 rng; |
There was a problem hiding this comment.
std::mt19937 is used in the class definition, but sto_wf.h does not include <random>. Any translation unit that includes this header (without separately including <random>) will fail to compile. Add #include <random> to sto_wf.h (or hide the RNG behind a PIMPL so the header doesn’t depend on <random>).
| unsigned int final_seed; | ||
| if (seed_in == 0 || seed_in == -1) | ||
| { | ||
| srand(static_cast<unsigned int>(time(nullptr)) + GlobalV::MY_RANK * rank_seed_offset); // GlobalV global variables are reserved | ||
| final_seed = (unsigned)time(nullptr) + GlobalV::MY_RANK * 10000; | ||
| } | ||
| else | ||
| { | ||
| srand(static_cast<unsigned int>(std::abs(seed_in)) + (GlobalV::MY_BNDGROUP * GlobalV::NPROC_IN_BNDGROUP + GlobalV::RANK_IN_BPGROUP) * rank_seed_offset); | ||
| final_seed = (unsigned)std::abs(seed_in) + (GlobalV::MY_BNDGROUP * GlobalV::NPROC_IN_BNDGROUP + GlobalV::RANK_IN_BPGROUP) * 10000; | ||
| } |
There was a problem hiding this comment.
The seed offset value 10000 is now duplicated in both seeding branches. This used to be a named constant, and keeping it as a single constexpr/const improves readability and reduces the chance of future inconsistencies if the offset changes.
| unsigned int final_seed; | ||
| if (seed_in == 0 || seed_in == -1) | ||
| { | ||
| srand(static_cast<unsigned int>(time(nullptr)) + GlobalV::MY_RANK * rank_seed_offset); // GlobalV global variables are reserved | ||
| final_seed = (unsigned)time(nullptr) + GlobalV::MY_RANK * 10000; | ||
| } | ||
| else | ||
| { | ||
| srand(static_cast<unsigned int>(std::abs(seed_in)) + (GlobalV::MY_BNDGROUP * GlobalV::NPROC_IN_BNDGROUP + GlobalV::RANK_IN_BPGROUP) * rank_seed_offset); | ||
| final_seed = (unsigned)std::abs(seed_in) + (GlobalV::MY_BNDGROUP * GlobalV::NPROC_IN_BNDGROUP + GlobalV::RANK_IN_BPGROUP) * 10000; | ||
| } | ||
|
|
||
| // initialize the random number generator with the final seed | ||
| this->rng.seed(final_seed); | ||
|
|
||
| this->allocate_chi0(); | ||
| this->update_sto_orbitals(seed_in); |
There was a problem hiding this comment.
The PR description says all rand()/srand() usage was replaced, but this file still contains srand(seed)/rand() usage in init_sto_orbitals_Ecut (later in sto_wf.cpp), and module_stodft/sto_tool.cpp also uses std::rand(). Either migrate those remaining call sites to the new std::mt19937 approach as well, or adjust the PR description/scope accordingly to avoid misleading reproducibility/thread-safety expectations.
std::mt19937random number generator as a private member of theStochastic_WFclass and included<random>in the implementation file. [1] [2]rand()andsrand()with the new RNG, seeding it appropriately ininit_sto_orbitalsbased on input parameters and MPI rank/group information.update_sto_orbitalsto usestd::uniform_real_distributionfor generating random phases andstd::bernoulli_distributionfor random sign selection, ensuring reproducibility and thread safety.