2007年11月13日星期二

关于并行计算

佳点集方法要求计算N个染色体的fitness值,选择最好的两个作为后代,这就对计算的速度提出了很高的要求!现在的问题是单个染色体decode为模糊集后计算一组实测数据的时间无法减少,只有从并行性上入手来提高速度。由于染色体之间没有任何关联,可以分别计算各个染色体的fitness值,因此可以分为N个线程来计算。主要方向确定了,细节的问题还有很多。首先是模糊集不是多线程安全的,所以每个线程要复制一个模糊集来使用。其次,每次交叉时要计算N个染色体,一代中要交叉多次,最好能重复使用这N个线程,减少创建和销毁线程的开销。这就牵扯到线程的同步、复用,以及其中模糊集的复用。
通过查阅资料,在Java中,并行编程的几个模式基本清楚了。其中,比较适合目前情况的有两个:barrier和executor。barrier的特点是同步方便,通过设置一个Runnable可以在所有线程计算完毕后将结果收集到一个list中。也方便复用,reset即可。不方便的是,它好像只能直接使用Thread。Thread的复用要自己编程实现。executor则是一个框架,可以提供一个线程池,只要用submit提交要计算的线程即可。优点是不用管线程的复用,缺点是得到的计算结果同步要自己实现。两者各有利弊吧。前者适合反复多次计算、同步、再计算、再同步。。。的场合,后者适合大量短时线程要执行的场合。
从我个人角度来说,更倾向于用barrier。一是因为以前用过,相对熟悉一些,二是感觉Thread的复用相对计算结果的同步要简单一些。当然了,最好是能将两者结合,Runnable里用barrier来同步,然后将Runnable提交给executor来处理,最后坐等barrier完成同步。这样Thread的复用就不用操心了,同步问题也解决了,但此时要注意复用fuzzyRuleSet的问题。这还是要自己实现。解决的方法如下:先建立一个模糊集pool,大小为N,这样可以保证一次barrier同步足够用。注意pool中的fuzzyRuleSet值相同,但其中每个对应的rules、RuleImplicationMethod、Variable等都是不同的对象,这样才能彻底杜绝数据的并发访问的问题,嘿嘿,这就完全是用空间来换时间啦。然后用一个链表来保存空闲的模糊集,使用时取一个,用完后还回来。
为了保证和前面的程序兼容,GCO要改名为PGCO(代表并行的GCO),fitnessFuction里新建一个evalute函数,通过参数不同与原来的那个区分来。还有一些细节,编程的时候再说啦,现在困死了,回去睡一会儿先~~

3 条评论:

刀巴虫子 说...

还是有问题,barrier+executor行不通,现在要确定问题是出在哪里。
是barrier同步后线程继续运行的问题,还是FuzzyRuleSet根本就无法并行的evaluate?希望是前者。

刀巴虫子 说...

找出程序中的一个bug,不过barrier还是有问题的。
发现ExecutorService的invokeAll方法是批量提交计算任务,全部完成后返回结果列表,这样可以不用barrier了,下午试试看效果。

刀巴虫子 说...

不用barrier果然就没什么问题了,可惜是双核的,要是四核、八核的就好了~~
现在并行计算的问题算是初步解决了,下面要关注收敛速度慢,甚至倒退的问题!