使用mapreduce实现GA

来源:互联网 发布:二维数组全部初始化为0 编辑:程序博客网 时间:2024/06/08 16:31
摘要:遗传算法在大规模问题的求解中得到越来越多的应用。传统的基于MPI的并行遗传算法需要知道机器架构的细节。另一方面,由Google提出的MapReduce可用于开发具有扩展性和容错能力的应用,是一个强大的抽象模型。本文演示了如何使用MapReduce模型来为遗传算法建模。我们描述了GA的算法设计和在Hadoop上的实现,后者是MapReduce的开源实现。实验演示了多达10的5次方个变量的问题的收敛性和可扩展性。如若增加资源,那么我们能够求解更大规模的问题,而不需要修改算法及其实现,因为我们没有引入任何的性能瓶颈。

关键词:遗传算法,MapReduce,可扩展性

1.导论

因特网的发展使得所有学科的研究人员需要处理大量的信息,而其唯一可行的途径是利用数据密集型框架(data-intensive framework)[29],[1],[5],[22]。遗传算法正在越来越多地被用于大规模问题求解,如非线性优化[7],集群[6]和作业调度[24]。进化算法固有的并行性,使它们成为并行化的最佳候选算法[2]。虽然已有大量的关于并行进化计算算法的研究[2],但很少有人探索数据密集型计算的用法[19]。
本文的主要贡献如下:
* 我们将遗传算法转换为Map和Reduce原语。
* 我们实现了MapReduce程序,并演示了其在大规模问题上的可扩展性。
本文结构如下:第二部分我们介绍了MapReduce模型及其运行概要。然后在第三部分,我们讨论如何使用MapReduce为遗传算法建模,并在第四部分给出实验报告。在第五部分,我们讨论并对比了相关工作。最后在第六部分做了总结。

2.MapReduce

Google从函数式语言的“映射”和“化简”原语中获得灵感,提出了MapReduce[3]编程模型,便于用户开发大规模分布式应用。相关的实现很容易将大型计算并行化,因为map函数的调用时各自独立的,并以重启作为主要容错机制。
在此模型中,计算过程输入的是一组key/value对,并产生一组key/value输出对。MapReduce库的用户须将计算过程表达为两类函数:Map和Reduce。用户编写的Map,获得一组输入,并产生中间的key/value对。然后,MapReduce框架将具有相同中间key I的中间value聚合起来,传递给Reduce函数。用户编写的Reduce函数,接受中间key I及其对应的一组value。它将这些value合并在一起形成可能更小的一组value。中间value是以iterator的形式提供给Reduce函数的。这使得模型能够处理那些因太大而不适合在主存中处理的value列表。
从概念上讲,用户提供的Map和Reduce函数具有如下的形式:
map(k1, v1) → list(k2, v2)
reduce(k2, list(v2)) → list(v3)
即,输入的key和value与输出的key和value由不同的域来刻画。此外,中间的key和value与输入的key和value具有相同的域。

通过将输入数据自动分割为M份,Map在多台机器上分布式调度。输入的每份数据可以在不同的机器上并行处理。而Reduce则是将中间key空间分割为R份来分布式调度,分割过程使用分区函数,hash(key)%R,它依赖于Hadoop的默认配置(后面根据需要会提到)。分区数量R和分区函数可以由用户指定。图1给出了MapReduce操作的高层数据流。感兴趣的读者可以参考[3]以及Hadoop查看其他实现细节。随同的分布式文件系统,如GFS[8]使得数据管理具有可扩展性和容错性。


图1.MapReduce数据流程图

3.MapReduce实现GA

这一部分,我们从一个简单的遗传算法模型开始介绍,然后将其转换为MapReduce实现,并讨论可这一过程需要考虑的一些组成部分。我们将GA的每一次迭代封装为一个独立的MapReduce任务。客户端接受命令行参数,建立种群并提交MapReduce任务。

A. 遗传算法
GA的最简单形式之一,选择-重组遗传算法[10],[11],主要依赖于选择和重组算子的使用。我们之所以选择以此入手,是因为它们提供了足以帮助我们说明创建一个数据密集型流程副本的最小算子集合。我们想以数据密集型流程方式实现的基本算法,可以简要描述如下:
1)随机产生初始种群的个体。
2)计算个体的适应值。
3)用s-wise锦标赛选择算子不替换选出好的解[12]。
4)使用均匀交叉算子重组选出的种群以创建新的个体[28]。
5)计算所有子代个体的适应值。
6)重复3-5步,直到满足某种收敛条件。


B. Map
种群适应值函数的计算(步骤2和5)匹配Map函数,它必须独立于其他实例来计算。如算法1所示,Map计算给定个体的适应值。并且,它将最好的个体的路径保存下来最终写到分布式文件系统HDFS的全局文件中。初始化任务的客户端,在MapReduce结束时从mapper中读取这些值并检查收敛条件是否满足。
----------------------------------------------------------------------------------------------------
算法1 GA每次迭代的Map阶段
Map(key, value):
----------------------------------------------------------------------------------------------------
individual ← INDIVIDUAL REPRESENTATION(key)
fitness ← CALCULATEFITNESS(individual)
EMIT (individual, fitness)


{Keep track of the current best}
if fitness > max then
max ← fitness
maxInd ← individual
end if


if all individuals have been processed then
Write best individual to global file in DFS
end if
----------------------------------------------------------------------------------------------------


C. Partitioner
若GA的选择算子(步骤3)在每个节点本地执行,空间约束将会人为引入并降低选择压力[25],并可能导致收敛时间增加。因此,去中心化的、分布式的选择算法[16]成为首选。MapReduce模型唯一的全局通信点是Map和Reduce之间的Shuffle。在Map阶段的最后,MapReduce框架使用分区将key/value对输出给Reduce过程。分区会将中间的key/value对在各个Reduce之间进行拆分。函数GetPartition()返回给定的(key, value)应该发送给的Reducer。在默认应用中,它使用Hash(key)%numReducers,以便具有相同key的值分配给同一个reducer,从而可以应用Reduce函数。然而,这并不符合遗传算法的需求,原因有两个:
首先,Hash函数将个体N的命名空间划分为r个不同的类:N0, N1, ..., Nr-1,其中Ni={n: Hash(n)=i}。每个分区中的个体与其他分区相隔离。这样,HashPartitioner基于低阶位引入了一个人工空间约束。因此,遗传算法的收敛可能花费更多的迭代次数,或者根本不会收敛。
其次,随着遗传算法的迭代进行,相同(接近最优)的个体开始主导种群。该个体的所有副本将会发送给一个单独的reducer,这会导致过载。因此,分布将逐渐变倾斜,偏离均匀分布(这会最大化并行处理器的利用)。最后,当GA收敛的时候,所有个体会被单个reducer处理。这样,并行度会随着GA收敛而减小,因而需要更多的迭代。
由于上述原因,我们提供了自己的分区工具,覆盖默认的,它随机地把个体分配给不同的Reducer,如算法2所示。
----------------------------------------------------------------------------------------------------
算法2 GA的随机分割
int GETPARTITION(key, value, numReducers):
----------------------------------------------------------------------------------------------------
      return RANDOMINT(0, numReducers - 1)
----------------------------------------------------------------------------------------------------


D. Reduce
我们采用无替换竞争选择算子[9]。一场竞争在S个随机选择的个体直接进行,选出其中的赢家。重复这个过程,重复次数为种群大小。由于随机选择个体相当于随机对所有个体洗牌并按顺序处理它们,我们的reduce函数也按顺序处理每个个体。最初的个体为最后一轮竞赛而缓存,当比赛窗口满了,执行SelectionAndCrossover算法,如算法3所示。当交叉窗口满了,我们使用随机交叉算子。在实际应用中,我们将S设为5,交叉算子采用选出的两个连续的父代个体进行。


----------------------------------------------------------------------------------------------------
算法3 GA每次迭代的Reduce阶段
Initialize processed ← 0,
tournArray [2· tSize], crossArray [cSize]
REDUCE(key, values):
----------------------------------------------------------------------------------------------------
while values.hasNext() do
individual ← INDIVIDUALREPRESENTATION(key)
fitness ← values.getValue()
if processed < tSize then
{Wait for individuals to join in the tournament and
put them for the last rounds}
tournArray [tSize + processed%tSize] ← individual
else
{Conduct tournament over past window}
SELECTIONANDCROSSOVER()
end if
processed ← processed + 1
if all individuals have been processed then
{Cleanup for the last tournament windows}
for k=1 to tSize do
SELECTIONANDCROSSOVER()
processed ← processed + 1
end for
end if
end while
SELECTIONANDCROSSOVER:
crossArray[processed%cSize] ← TOURN(tournArray)
if (processed - tSize) % cSize = cSize - 1 then
newIndividuals ← CROSSOVER(crossArray)
for individual in newIndividuals do
EMIT (individual, dummyFitness)
end for
end if
----------------------------------------------------------------------------------------------------


E.优化
初始实验之后,我们注意到对于较大规模的问题,种群的串行初始化会花费较长时间。根据Amdahl定律,加速比会受限于串行组件。因此,我们在一个单独的MapReduce阶段来创建初始种群,其中的Map阶段产生随机个体,Reduce阶段是Identity Reducer。我们用mapper_id*current_time作为每个mapper的伪随机数发生器的种子。个体中变量的位,用一组长长整型紧凑地表示,我们采用高效的位操作做交叉算子和适应值计算。由于MapReduce模型无法表达循环操作,由一个Map和一个Reduce组成的每次迭代,需要执行到满足收敛条件。




4.实验结果

OneMax问题[27](或者称为BitCounting)是个简单的问题,旨在最大化一个位串中1的数量。通常,该问题可描述如下,寻找一个字符串x={x1, x2, ..., xN},其中xi属于{0, 1},最大化以下方程:
我们在Hadoop 0.19中解决这个简单的问题,在416核(52个节点)的Hadoop集群上运行,每个节点运行在两台双英特尔四核机器上,内存16GB,硬盘2TB。节点都集成到一个分布式文件系统(HDFS),得到一个2*52/3=34.6TB(由于HDFS的复制因子设为3)大小的潜在的单图像存储空间。集群配置的详细说明可以在其他地方找到。每个节点可以并行运行5个mapper和3个reducer。某些节点,尽管是全功能的,但由于磁盘竞争、网络流量或极端的计算负责,可能变得缓慢。这时使用推测执行,在空闲节点并行地运行分配给这些慢节点的任务。无论哪个节点首先完成,输出结果,并杀掉其他的推测任务。对于每一次实验,GA的种群大小设置为nlogn,其中n是变量的个数。
我们进行了以下实验:

1)收敛性分析:在该实验中,我们针对具有104个变量的OneMax问题,根据设置为1的比特位的数量监控实验过程。如图2所示,GA收敛于第220次迭代,平均每次迭代花费149秒。


图2.104个变量的OneMax问题的GA的收敛性


2)每个节点恒定负载的可扩展性:在该实验中,我们将负载设置为每个mapper 1000个变量。如图3所示,每次迭代的时间初始时会上升,然后稳定在75秒左右。因此,随着资源的增加而增大问题规模不会改变迭代时间。由于每个节点最多可运行5个mapper,整个map的容量是5*52(节点)=260。因此,在250个mapper中,由于资源缺乏而无法容纳如此多的mapper,每次迭代所耗费的时间会逐渐增加。


图3. OneMax问题每个节点恒定负载的可扩展性




3)恒定总负载的可扩展性:在这个实验中,我们将问题规模设置为50000个变量,增加mapper的数量。如图4所示,随着越来越多的mapper的加入,每次迭代的时间逐渐减小。因此,保持问题规模固定不变的同时增加更多的资源可以减少每次迭代的时间。再次,在250个mapper后,map容量的饱和导致每次迭代的时间略有增加。然而,整体增速受限于由Hadoop的开销(启动和终止一个MapReduce任务需要大约10秒钟)产生的Amdahl定律。然而,正如之前的实验中看到的,MapReduce模型非常适合处理大规模问题,其中涉及到特大规模的种群。


图4.具有50000个变量的OneMax问题的GA,随着mapper增加的可扩展性



4)问题规模增加的可扩展性:这里,我们使用最大的资源,增加变量的数量。如图5所示,我们扩展到n=105个变量,保持种群大小为nlogn。通过添加更多的节点,我们能够扩展问题规模。每次迭代的时间随着变量数增加到n=105以及种群大小超线性增加(nlogn)而急剧增加,种群中的个体数超过了1600万。


图5.变量数增长的OneMax问题的GA的可扩展性




5.结果讨论及相关工作

已经提出了几种不同的模型来实现并行GA,比如细粒度[21]、粗粒度[18]和分布式模型[17]。传统上,消息传递接口(MPI)已被用于实现并行GA。然而,MPI在商业集群上的扩展性并不好,失败是常态而非例外。一般来说,如果MPI集群的一个节点失败,整个程序都会重启。在大型集群中,一台机器在一个长期运行的程序的执行过程中很可能运行失败,从而有效的容错能力是必要的。这会强制用户通过使用复杂的检查点技术来处理故障。


MapReduce[3]是一个变成模型,它使用户能够轻松地开发大型分布式应用程序。Hadoop是MapReduce模型的一个开源实现。几种针对其他架构的MapReduce的不同实现已被开发出来,比如针对多核的Phoenix[23],和针对流媒体应用的CGL-MapReduce[4]。


尽我们所知,MRPGA[15]是将MapReduce和GA相结合的唯一尝试。然而,他们声称GA不能直接用MapReduce表达,他们讲模型扩展到MapReduceReduce,并提供自己的实现。我们指出几处不足:首先,Map函数用于评估适应值,ReduceReduce用于做局部和全局选择。然而,工作中的绝大部分——编译、交叉、收敛准则的评价以及调度是由一个单一的协调者来实现的。如其结果所展示的,由于其中固有的串行组件,该方法无法扩展到32个节点以上。其次,他们提出的“扩展”可以很容易地在传统的MapReduce模型中实现。本地reduce等价于一个组合器[3],可以在其中实现。最后,在他们的mapper,reducer和final_reducer函数中,他们用“default_key”和1作为它们的值。因此,他们不使用MapReduce模型的任何特性——通过key的分组以及洗牌。Mapper和Reducer很可能只是独立执行与协调者通信的过程。


我们采用不同的方法,试图让GA适应MapReduce,而不是改变MapReduce模型本身。我们在Hadoop中实现了GA,Hadoop已经日渐成为MapReduce事实上的标准实现,并在行业内多个生产环境中使用。Meandre[20],[19]扩展了MapReduce模型的一些限制,同时保持了其天然的数据密集性。它显示了简单GA和EDA在多核架构上的线性扩展性。对于非常大的问题(>109个变量),其他模型如紧凑型遗传算法(cGA)和扩展cGA(eCGA)已被探索[26]。




6.结论及进一步工作

本文主要解决了MapReduce用于缩放遗传算法的挑战。我们描述了GA算法设计及其在Hadoop上的实现。对算法的收敛性和可扩展性进行了研究。如若增加资源,那么我们能够求解更大规模的问题,而不需要修改算法及其实现。
未来我们将研究MapReduce实现更具可伸缩性的遗传算法模型,如紧凑型遗传算法(compact GAs)[14]和扩展的紧凑型遗传算法(extended compact GAs)[13]。我们还计划与已有的基于MPI的实现做性能对比。将通用GPU加入到集群的异质性是令人兴奋的。计算密集的Map阶段和随机数生产,可以在GPU中调度,其可以在GPU的Reduce上并行执行。我们也想展示可扩展GA在实际应用中的重要性。


致谢

我们要感谢匿名审稿人提出的宝贵意见。本研究部分由美国国家科学基金会(NSF)IIS Grant#0841765资助。本文仅代表作者观点。


参考文献






原文:Abhishek Verma等,Scaling Genetic Algorithm using MapReduce
Abhishek Verma†, Xavier Llor`a∗, David E. Goldberg# and Roy H. Campbell†
0 0