我正在尝试为canonical genetic algorithm编写一个C ++程序,其中你有一群长度为N的个体(染色体),其中每个元素都是O或1。
我已经开始使用 STL向量编写我的程序,但在我深入研究之前,我想问一下你如何以最有效的方式编写函数和数据结构的意见
内存占用不是问题,我有大约100个人口,每个人都是一个64字符长的0-s和1-s字符串。另一方面,表现非常重要,因为会有大约数千代人,每人都有数千次操作。
这是我到目前为止的实现(只是最重要的功能和数据结构):
typedef vector<int> chromosome;
typedef vector<chromosome> population;
population popul;
float eval[number];
void cross_chromosomes( const chromosome &parent_a, const chromosome &parent_b, chromosome &child_a, chromosome &child_b )
{
int crossing_point = crossing_point_gen( gen );
child_a.reserve( length );
child_a.insert( child_a.end(), parent_a.cbegin(), parent_a.cbegin() + crossing_point );
child_a.insert( child_a.end(), parent_b.cbegin() + crossing_point, parent_b.cend() );
child_b.reserve( length );
child_b.insert( child_b.end(), parent_b.cbegin(), parent_b.cbegin() + crossing_point );
child_b.insert( child_b.end(), parent_a.cbegin() + crossing_point, parent_a.cend() );
}
void calculate_eval()
{
for( int i = 0; i < number; i++ )
{
eval[i] = evaluate_chromosome( popul[i] );
}
}
您认为这是实现此算法的有效方式吗?我最初使用矢量作为染色体,但我已阅读此问题:C++ Vector vs Array (Time)我将代码更新为{ {1}}。
您是否认为我应该对代码进行其他优化以提高效率?交叉码是否现在有效?
答案 0 :(得分:4)
如何利用进化算法中的embarasing并行性。那么尝试在GPU上移植您的解决方案呢?就像chetan和David说的那样,使用现有框架比编写自己的 fast 框架要花费更少的时间。
众所周知,OpenBeagle和EO支持得很好且效率很高。
请注意,在进化算法中真正需要快速的唯一部分是评估其他所有内容通常不会耗费时间。您还可以查找DEAP,它允许在超级计算机上轻松分发评估(以及更多)(我们通过更改串行算法中的单行代码在Colosse超级计算机的1024个核心上进行了测试)。
答案 1 :(得分:2)
对于你试图用向量做的事情,交叉代码看起来效率最高。根据我的遗传算法经验,适应度函数和选择算子是最耗时的。由于您将在群体样本上使用交叉和变异,因此您不必过分担心交叉运算符的效率。专注于为您的数据定义良好的表示和最佳的适应度函数实现。
答案 2 :(得分:0)
如果您已经知道阵列的大小,那么使用数组将比使用向量快得多。向量需要比数组更多的开销。
答案 3 :(得分:0)
你可以稍微压缩你的记忆:使用4个字节来表示二进制值是非常浪费的。我建议您使用chromosome
或std::array<unsigned char, 64>
替换std::bitset<64>
以将其打包更多。
即使您声称不担心内存,压缩内存也会导致CPU中的缓存使用率提高,从而加快程序的运行速度。
但是,如果你真的想要优化你的程序,那么唯一明智的方法就是使用一个完整的分析器。我过去曾经相继使用过callgrind,但是还有其他的,取决于你的开发环境。