【发布时间】:2016-03-08 00:21:45
【问题描述】:
对于进化算法,我需要一个容器来存储个体群体 - 即对象向量。我需要在每次迭代时对该向量进行排序,这应该是有效的。此外,我想避免缓存未命中,所以我想预先批量分配整个人口(它的大小是已知的并且是固定的)。但是,我并不满足于类的默认构造函数,而是想在每个对象上调用一个特定的构造函数。
我在当前代码上运行了cachegrind,发现缓存未命中次数最多的是Individual::operator <(const Individual &other),这是我对总体进行排序的谓词。由于我的人口在每次迭代中都进行了排序,我认为此时进行优化会给我带来最大的好处。我已经将operator <() 中的缓存未命中解释为源于Individual 对象在我的系统内存上的分布——如果不是这样,我会在访问器函数中看到缓存未命中,例如存储的std::vector<double>个人的参数吧?
根据我的要求,我选择了boost::ptr_vector。主要是因为它允许我 (a) 将我的对象保存在一块内存中,同时提供不创建和销毁临时对象的 sort() 实现。
现在,为了避免缓存未命中,我想将整个人口分配为一块。我想做的是类似于......
boost::ptr_vector<Individual> population;
auto *rawPopulaton = new Individual[populationSize](templateObject);
population.transfer(population.begin(), rawPopulation, populationSize);
return population;
然而,我不确定如何实现这一点,以便不违反空间局部性的概念(即,我想避免缓存未命中)。我可以愉快地循环:
for (size_t i = 0; i < populationSize; ++i) {
auto *individual = new Individual(templateObject);
population.push_back(individual);
}
...但我担心这会导致我的人口分布在不同的内存块上。
所以这里其实有两个问题:
- 我的设计选择是否符合优化目标?
- 如何批量分配我的人口并调用特定的构造函数?
【问题讨论】:
-
实际上是否存在缓存未命中导致的性能瓶颈? (任何测量完成?) 使用memory pool 分配对象怎么样? (或者自己写,使用placement new)
-
关于 更具体——由于分配导致的未命中,而不是说似乎很可能发生的对该内存的非顺序访问。
-
@DanMašek:关于(1),是的,我进行了测量。我会更新我的问题以反映这些。
标签: c++ optimization boost