【发布时间】:2022-01-14 10:09:32
【问题描述】:
我正在对聚合物进行蒙特卡罗模拟。系统当前状态的整个配置由名为Grid 的对象给出。这是我对Grid的定义:
class Grid{
public:
std::vector <Polymer> PolymersInGrid; // all the polymers in the grid
int x; // length of x-edge of grid
int y; // length of y-edge of grid
int z; // length of z-edge of grid
double kT; // energy factor
double Emm_n ; // monomer-solvent when Not aligned
double Emm_a ; // monomer-solvent when Aligned
double Ems; // monomer-solvent interaction
double Energy; // energy of grid
std::map <std::vector <int>, Particle> OccupancyMap; // a map that gives the particle given the location
Grid(int xlen, int ylen, int zlen, double kT_, double Emm_a_, double Emm_n_, double Ems_): x (xlen), y (ylen), z (zlen), kT (kT_), Emm_n(Emm_n_), Emm_a (Emm_a_), Ems (Ems_) { // Constructor of class
// this->instantiateOccupancyMap();
};
// Destructor of class
~Grid(){
};
// assignment operator that allows for a correct transfer of properties. Important to functioning of program.
Grid& operator=(Grid other){
std::swap(PolymersInGrid, other.PolymersInGrid);
std::swap(Energy, other.Energy);
std::swap(OccupancyMap, other.OccupancyMap);
return *this;
}
.
.
.
}
如果需要,我可以了解对象Polymer 和Particle 的详细信息。
在我的驱动程序代码中,这就是我要执行的操作: 定义最大迭代次数。
- 定义一个完整的网格
G。 - 创建名为
G_的G的副本。 - 我正在扰乱
G_的配置。 - 如果
G_上的扰动按照 Metropolis 标准被接受,我将G_分配给G(G=G_)。 - 重复步骤 1-4,直到达到最大迭代次数。
这是我的驱动代码:
auto start = std::chrono::high_resolution_clock::now();
Grid G_ (G);
int acceptance_count = 0;
for (int i{1}; i< (Nmov+1); i++){
// choose a move
G_ = MoveChooser(G, v);
if ( MetropolisAcceptance (G.Energy, G_.Energy, G.kT) ) {
// accepted
// replace old config with new config
acceptance_count++;
std::cout << "Number of acceptances is " << acceptance_count << std::endl;
G = G_;
}
else {
// continue;
}
if (i % dfreq == 0){
G.dumpPositionsOfPolymers (i, dfile) ;
G.dumpEnergyOfGrid(i, efile, call) ;
}
// G.PolymersInGrid.at(0).printChainCoords();
}
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds> (stop-start);
std::cout << "\n\nTime taken for simulation: " << duration.count() << " milliseconds" << std::endl;
这是有趣的部分:如果我使用没有很多“接受度”(低温、不良溶剂)的条件运行模拟,则模拟运行得非常快。但是,如果有大量接受,模拟会变得非常慢。 我的假设是我的赋值运算符 = 正在减慢我的模拟速度。 我进行了一些测试:
接受次数 = 25365,挂钟时间 = 717770 毫秒 (!)
接受次数 = 2165,挂钟时间 = 64412 毫秒
接受次数 = 3000,挂钟时间 = 75550 毫秒
而且这种趋势还在继续。 谁能建议我如何提高效率?我认为,由于 = 运算符,有没有办法绕过我正在经历的减速?
非常感谢您对我的任何建议!
【问题讨论】:
-
你在复制值,试试
G = std::move(G_) -
Grid& operator=(Grid other)调用构造函数时似乎确实效率低下,Grid& operator=(const Grid&) = default; Grid& operator=(Grid&&) = default;似乎更好(不知道为什么不复制所有成员,可能更好地使用命名函数)。 -
@Jarod42,谢谢你的建议。你能举个例子来说明你的意思吗?
标签: c++ oop optimization operator-overloading