精华内容
下载资源
问答
  • 这是《高校云计算应用创新大赛》里的最后一道题,题目是莎士比亚文集词频统计并行化算法。由于原网站上的实验文件已经无法下载了,所以这里上传一份,包含 shakespear.zip、stopword.txt.
  • pso并行化算法.rar

    2019-06-27 11:16:59
    并行化实现了PSO算法,大大提高了算法的寻优效果。基于OpenMP和MPI两种方法实现。
  • 一种基于Spark的图像聚类并行化算法.pdf
  • 基于Spark的水库群多目标调度粒子群并行化算法.pdf
  • 基于GPU的光子映射并行化算法.pdf
  • Spark下BP神经网络并行化算法研究.pdf
  • 基于Spark的LIBSVM参数优选并行化算法
  • 基于GPU的交叉相关外推并行化算法.pdf
  • 基于深度学习的文本情感分析并行化算法.pdf
  • 马尔可夫聚类算法(MCL)是在大规模生物网络中寻找模块的一个有效方法,能够挖掘网络结构和功能影响力较大的模块。...针对复杂度高的问题,提出了基于消息传递接口(MPI)的并行化马尔可夫聚类算法以提高算法的计算性能。
  • 为了将BP算法用于大规模数据分类问题,采用MapReduce思想,将大数据集切分成若干小的数据集来并行加速处理,同时引入Bagging算法的思想来综合并行结果,提高分类的准确率。通过在各个节点上根据子数据集独立地训练各个BP...
  • 并行和分布式系统 使用C库进行并行化算法的项目,例如:Pthreads,OpenMP,Intel Cilk,OpenMPI,Nvidia CUDA
  • 使用OpenMP并行化常见算法

    千次阅读 2020-02-10 22:22:09
    OpenMP并行化常见算法 openmp是强大的并行编译库,可以动态地设置多线程,使用方便。 这里我将以搜索算法为例,介绍如何用OpenMP把常见算法并行化。 旅行商问题 旅行商问题已经老生常谈了。指在有向带权图内,寻找一...

    OpenMP并行化常见算法

    openmp是强大的并行编译库,可以动态地设置多线程,使用方便。
    这里我将以搜索算法为例,介绍如何用OpenMP把常见算法并行化。

    旅行商问题

    旅行商问题已经老生常谈了。指在有向带权图内,寻找一条最短回路(指经过每个顶点仅一次,且权值总和最小)。事实上该问题是一个NPhard问题,想解决它只能花费指数级的时间复杂度。
    我们尝试使用BFS和DFS去求解它。因为题目要求经过每个顶点仅一次,则不会出现环,即只要约定我们的搜索不走已经经过的顶点,搜索的状态就永远不会出现交叉,即我们是要在一个解空间树里求解。
    先定义用于表示一个搜索状态的结构体,以及一个用于求下一状态的算法。

    /*
    记录搜索状态的状态结点
    用经典数组保存路径,其中order[i]表示i顶点被造访的
    时间顺序,起点的order[i]为0,后续每下溯一层则加1
    front表示最新造访的顶点,以它为起点下溯一层。
    order[i]==-1表示从未造访过,也是我们可以扩展的顶点。
    */
    struct Node
    {
    	int order[N];
    	int front = -1;
    	int cost = 0;
    	Node() { fill(order, order + N, -1); }
    };
    

    successors算法很简单,我们在结构体里已经定义了分辨顶点是否被遍历过的方法order[i]==-1,只需要遍历所有顶点,并把未遍历过的顶点作为后继顶点生成新的解状态结点即可。
    考虑DFS算法,如果用非递归的形式,也就是用栈和循环模拟递归,自然可以实现循环形式的DFS算法。既然搜索的是解空间树,循环的各部分没有相关性,我们就能用parallel for语句直接把DFS并行化,这是相当简单的。
    解空间树的分支因子在最上层为n-1,每向下一层,如果要简单地划分for循环来实现并行,则在最上层划分是最优解。
    当n远大于线程数时自然可行,但是本问题是NPhard问题,n很大时是不可能求解的,一般n都在几十左右,而我们的线程数却有可能很多,这样就造成了极大的负载不均衡,会失去我们原有的并行优越性。
    为此可能需要并行化的BFS,BFS借助队列进行。每次从队首取出结点,然后求successors,把新的结点放入队尾。很容易看出,每个successors操作之间是可以并行的,而一次successors操作只需要线性时间复杂度,这就把原有的大规模问题变得颗粒化。只要我们的多线程每次都从队列中请求元素,然后并行地执行successors,再把新结点入队,就实现了很好的负载均衡的并行搜索算法。
    要注意的一点是,队列不允许并行的pop和push,因此操作队列的代码应该被设置线程锁;此外,修改全局变量,最优解solution时,也要设计线程锁。
    另一个问题,单线程中,我们直接认为队列为空的时候就是搜索完毕的时候。但多线程中,即使搜索未进行完,仍然有可能让队列为空,这时某个线程去队列内请求元素就会造成报错。因此对搜索进行完毕就需要其他的逻辑,当所有的叶结点,也就是goalstate都被搜索完的时候,搜索就真正结束了。在此之前,某些线程即使无法从队列中得到元素,也不能退出循环,而需要一直等待。
    bfs的cpp代码如下

    #include <iostream>
    #include <algorithm>
    #include <omp.h>
    #include <string>
    #include <vector>
    #include <queue>
    #include <set>
    
    using namespace std;
    
    #define N 4
    
    /*
    问题:
    开发能并行线程解决旅行商问题的程序。
    旅行商问题是在一张n个顶点的全连通带权图中,寻找一条经过
    每个顶点仅一次,并且能回到出发城市的“回路”,并让
    这个回路的cost最小。我们能够证明的是,没有多项式
    级别的算法能求解本问题,我们至少要花费指数级的时间
    去计算。
    
    分析:解决旅行商问题的基本算法就是朴素的搜索,一般使用
    空间占用较小的DFS搜索。首先分析问题,问题中提到“不重复
    结点”,即如果我们共有n个顶点,从第m个顶点出发,则总回路
    数(搜索树叶结点数)就为(n-1)!种。分支因子在最上层为n-1,越向下
    越小,如果要简单地划分for循环来实现并行,则在最上层划分
    是最优。但是如果comm_sz和n可比拟,这样的划分方式就会造成极大的
    负载不均衡,所以根据情况,我们也有必要选择广度优先搜索
    
    BFS时,在任一节点,每次我们只需要下溯一层,即把successors的
    状态结点推入队列。单次操作的运算复杂度O(n),实际上m=b,当前
    的分支数。这样就让计算的“粒度”更小,也就能更有效地实现负载
    均衡。算法执行时,我们只需要设置共享的queue,然后每个线程独立
    地向queue请求一个结点,然后在做下溯的过程中把新结点推入队列。
    如果当前结点是叶结点(最终回路),记录cost并更新我们的全局最小。
    
    缺点也很明显,对n级别的顶点数,队列需要的空间是n的指数级,空间
    复杂度高。
    
    */
    
    
    
    
    struct Node
    /*
    记录搜索状态的状态结点
    用经典数组保存路径,其中order[i]表示i顶点被造访的
    时间顺序,起点的order[i]为0,后续每下溯一层则加1
    front表示最新造访的顶点,以它为起点下溯一层。
    order[i]==-1表示从未造访过,也是我们可以扩展的顶点。
    */
    {
    	int order[N];
    	int front = -1;
    	int cost = 0;
    	Node() { fill(order, order + N, -1); }
    };
    
    queue<Node> Q;//存储状态的队列
    int bestPath[N];//最优解
    int bestCost = 9999999;
    int graph[N][N];//邻接矩阵
    
    
    void showpath(int order[N]) {
    	int path[N];
    	for (int i = 0;i < N;i++) {
    		path[order[i]] = i;
    	}
    	for (int i = 0;i < N;i++) {
    		cout << path[i] << "->";
    	}
    	cout << 0 << endl;
    }
    
    
    /*
    input.txt:
    0 1 3 8
    5 0 2 6
    1 18 0 10
    7 4 12 0
    */
    
    
    int main()
    {
    	freopen("input.txt", "r", stdin);
    	for (int i = 0;i < N;i++)
    		for (int j = 0;j < N;j++)
    			cin >> graph[i][j];
    	Node start;
    	start.order[0] = 0;
    	start.front = 0;//从0号顶点开始
    	Q.push(start);
    	omp_lock_t changeQ, changeSolu;
    	omp_init_lock(&changeQ);
    	omp_init_lock(&changeSolu);
    	int goal_cnt = 0;
    	/*已经访问的goal的计数器
    	这个计数器的设置是为了一个特殊的问题
    	单线程中,我们直接认为队列为空的时候就是搜索完毕的时候
    	但多线程中,即使搜索未进行完,仍然有可能让队列为空,这
    	时某个线程去队列内请求元素就会造成报错。因此对搜索进行
    	完毕就需要其他的逻辑,当所有的叶结点,也就是goalstate
    	都被搜索完的时候,搜索就真正结束了。在此之前,某些线程即使
    	无法从队列中得到元素,也不能退出循环,而需要一直等待*/
    	int MAX_CNT = 1;
    	for (int i = 1;i < N;i++) MAX_CNT *= i;
    #	pragma omp parallel num_threads(4)
    	{
    		while (goal_cnt<MAX_CNT) 
    		{
    			Node n;
    			omp_set_lock(&changeQ);
    			if (!Q.empty()) {
    				n = Q.front();
    				Q.pop();
    			}
    			omp_unset_lock(&changeQ);
    			if (n.front==-1) //无效的结点
    				continue;
    			bool goal = 1;
    			for (int i = 0;i < N;i++) {
    				if (n.order[i] != -1)
    					continue;
    				else {
    					Node newNode;
    					copy(n.order, n.order + N, newNode.order);
    					newNode.order[i] = n.order[n.front] + 1;
    					newNode.cost = n.cost + graph[n.front][i];
    					newNode.front = i;
    					omp_set_lock(&changeQ);
    					cout << "Process " << omp_get_thread_num() << " push" << endl;
    					for (int x : newNode.order)
    						cout << x << " ";
    					cout << endl;
    					Q.push(newNode);
    					omp_unset_lock(&changeQ);
    					goal = 0;
    				}
    			}
    			if (goal) {//更新最优解
    				omp_set_lock(&changeSolu);
    				int final_cost = n.cost + graph[n.front][0];
    				goal_cnt++;
    				if (final_cost < bestCost) {
    					bestCost = final_cost;
    					copy(n.order, n.order + N, bestPath);
    				}
    				omp_unset_lock(&changeSolu);
    			}
    		}
    	}
    	cout << "Best path is: ";
    	showpath(bestPath);
    	cout << "Cost: " << bestCost << endl;
    }
    
    
    
    
    展开全文
  • 矩阵乘法的并行化算法讨论

    万次阅读 多人点赞 2015-09-26 13:28:14
    另一方面,矩阵乘法同时也是并行计算领域常常被用来作为范例的一个话题。它的特点是首先计算量可能相当大,适合利用并行实现来提高效率。其次,它所使用的各种数据之间(矩阵中的元素)没有相互依赖性,可以充分使用...
    矩阵乘法是线性代数里面会讲到的一种非常基础、也十分普遍的计算规则。另一方面,矩阵乘法同时也是并行计算领域常常被用来作为范例的一个话题。它的特点是首先计算量可能相当大,适合利用并行实现来提高效率。其次,它所使用的各种数据之间(矩阵中的元素)没有相互依赖性,可以充分使用并行处理的计算资源。
    


    串行实现


    根据线性代数的基本知识,m × l 的矩阵A,乘以一个大小为 l × n 的矩阵B,将得到一个 m × n 的矩阵C=A×B,其中


    下图是用图示来表示的这种计算规则:


    为了方便讨论,我们可以不是普遍性地假设有所矩阵的大小都是 n × n 的,下面就是串行实现的矩阵乘法的代码:

    int A[n][n], B[n][n], C[n][n];
    ...
    for(i=0;i<n;i++){
        for(j=0;j<n;j++){
            C[i][j]=0;
            for(k=0;k<n;k++)
                C[i][j]+=A[i][k]*B[k][j];
        }
    }
    

    易见,这个算法的计算复杂度为O(n^3)。


    基本并行实现的讨论


    正如前面所讲的,矩阵相乘过程中,结果矩阵C中的每个元素都是可以独立计算的,即彼此之间并无依赖性。所以如果采用更多的处理器,将会显著地提高矩阵相乘的计算效率。


    对于大小为n × n 的矩阵,加入我们有n个处理器,那么结果矩阵中的每一行,都可以用一个处理器来负责计算。此时,总共的并行计算步数为 O(n^2)。你可以理解为在串行实现的代码中,最外层的循环 for(i=0;i<n;i++) 被分别由n个处理器来并行的执行,而每个处理需要完成的任务仅仅是内部的两层循环。


    如果采用n^2个处理器,那么就相当于结果矩阵中的每个元素都由一个处理器来负责计算。此时,总共的并行计算步数为 O(n)。你可以理解为在串行实现的代码中,最外面的两层循环 被分解到n^2个处理器来并行的执行,而每个处理需要完成的任务仅仅是内部的一层循环,即for(k=0;k<n;k++)。


    更进一步,如果有n^3个处理器,那么即使最内层的循环for(k=0;k<n;k++)也有n个处理器在并行的负责。但是最终的求和运算,我们需要一个类似reduction的操作,因此最终的计算复杂度就是O(log n)。


    当然,你一定会想到的是,实际中,通常并不可能有像矩阵元素那么多的处理器资源。这时我们该怎么做。对于一个大小为n × n 的大矩阵A,我们其实可以把它切分成s^2个子矩阵Ap,q,每个子矩阵的大小为 m × m,其中 m = n / s,即0 <= p, q < s。对于两个大矩阵A和B,现在我们有:


    用图示表示则有:



    Cannon算法


    著名的Cannnon算法使用一个由s^2个处理器组成的二维网孔结构(mesh),而且这个mesh还是周边带环绕的(The processors are connected as a torus)。处理器Processor (i,j) (我们用它来表示位于位置(i,j)处的处理器)最开始时存有子矩阵Ai,jBi,j。随着算法的进行,这些子矩阵会向左或向上位移。如下图所示:


    这个算法的根本出发点是在处理器阵列中,要合理分布两个待乘的矩阵元素。由乘积公式可知,要在处理单元 P(i,j)中计算乘积元素C(i,j),必须在该单元中准备好矩阵元素A(i,s)和B(s,j)。但是如果我们像下图那样分布矩阵元素,我们在计算C(i,j)时所需的元素显然是不足够的,但是可以通过向上循环位移B的元素,并向左循环位移A的元素,来获取合适的成对的矩阵元素。


    Cannnon算法的具体流程:



    下面是矩阵位移的一个示例,其中s=3;


    显然,算法的复杂度 t(n)=O(n), p(n) = n^2,w(n) = O(n^3),所以是成本最佳的。


    ---------------------------------------------

    参考文献与推荐阅读材料

    【1】陈国良,并行算法的设计与分析(第3版),高等教育出版社,2009

    【2】矩阵计算并行算法(百度文库地址:http://wenku.baidu.com/view/d64ba9b4b14e852458fb57fc.html)


    (本文完)


    展开全文
  • 基于OpenMP的粗粒度并行遗传算法,相比于串形遗传算法提升了运行速度。
  • 在多处理机中实现图像处理的并行化算法研究,在多处理机中实现图像处理的并行化算法研究
  • Aprior并行化算法在Spark上的实现

    千次阅读 2015-08-12 08:59:45
    本文为大家分享的Spark实战案例是K-频繁项集挖掘——Apriori并行化算法的实现。关联数据挖掘、频繁项集挖掘的常用算法有Apriori,Fp-growth以及eclat算法。这里我使用Apriori算法进行频繁项集挖掘。Apriori算法于2006...

    本文为大家分享的Spark实战案例是K-频繁项集挖掘——Apriori并行化算法的实现。关联数据挖掘、频繁项集挖掘的常用算法有Apriori,Fp-growth以及eclat算法。这里我使用Apriori算法进行频繁项集挖掘。Apriori算法于2006年12月被国际权威的学术组织ICDM评为数据挖掘领域的十大经典算法。不熟悉的同学可以关注我的文章,我会详细讲解其原理及实现。

    首先给出需求说明:在Chess标准数据集上进行1到8频繁项集的挖掘,其中支持度support=0.85。每个文件的输出格式为项集:频率,如a,b,c:0.85。

    我们在写Spark程序的时候一定要注意写出的程序是并行化的,而不是只在client上运行的单机程序。否则你的算法效率将让你跌破眼镜而你还在郁闷为什么Spark这么慢甚至比不上Hadoop-MR。此外还需要对算法做相关优化。在这里主要和大家交流一下算法思路和相关优化。

    对于Apriori算法的实现见下文源码。在Spark上实现这个算法的时候主要分为两个阶段。第一阶段是一个整体的遍历求出每个项集的阶段,第二阶段主要是针对第i个项集求出第i+1项集的候选集的阶段。

    对于这个算法可以做如下优化:
    1. 观察!这点很重要,经过观察可以发现有大量重复的数据,所谓方向不对努力白费也是这个道理,首先需要压缩重复的数据。不然会做许多无用功。
    2. 设计算法的时候一定要注意是并行化的,大家可能很疑惑,Spark不就是并行化的么?可是你一不小心可能就写成只在client端运行的算法了。
    3. 因为数据量比较大,切记多使用数据持久化以及BroadCast广播变量对中间数据进行相应处理。
    4. 数据结构的优化,BitSet是一种优秀的数据结构他只需一位就可以存储以个整形数,对于所给出的数据都是整数的情况特别适用。
    下面给出算法实现源码:

    import scala.util.control.Breaks._
    import scala.collection.mutable.ArrayBuffer
    import java.util.BitSet
    import org.apache.spark.SparkContext
    import org.apache.spark.SparkContext._
    import org.apache.spark._
    
    
    object FrequentItemset {
      def main(args: Array[String]) {
        if (args.length != 2) {
          println("USage:<Datapath> <Output>")
        }
        //initial SparkContext
        val sc = new SparkContext()
        val SUPPORT_NUM = 15278611 //Transactions total is num=17974836, SUPPORT_NUM = num*0.85
        val TRANSACITON_NUM = 17974836.0
        val K = 8
    
    
        //All transactions after removing transaction ID, and here we combine the same transactions.
        val transactions = sc.textFile(args(0)).map(line =>
          line.substring(line.indexOf(" ") + 1).trim).map((_, 1)).reduceByKey(_ + _).map(line => {
          val bitSet = new BitSet()
          val ss = line._1.split(" ")
          for (i <- 0 until ss.length) {
            bitSet.set(ss(i).toInt, true)
          }
          (bitSet, line._2)
        }).cache()
    
    
        //To get 1 frequent itemset, here, fi represents frequent itemset
        var fi = transactions.flatMap { line =>
          val tmp = new ArrayBuffer[(String, Int)]
          for (i <- 0 until line._1.size()) {
            if (line._1.get(i)) tmp += ((i.toString, line._2))
          }
          tmp
        }.reduceByKey(_ + _).filter(line1 => line1._2 >= SUPPORT_NUM).cache()
        val result = fi.map(line => line._1 + ":" + line._2 / TRANSACITON_NUM)
        result.saveAsTextFile(args(1) + "/result-1")
    
    
        for (i <- 2 to K) {
          val candiateFI = getCandiateFI(fi.map(_._1).collect(), i)
          val bccFI = sc.broadcast(candiateFI)
          //To get the final frequent itemset
          fi = transactions.flatMap { line =>
            val tmp = new ArrayBuffer[(String, Int)]()
            //To check if each itemset of candiateFI in transactions
            bccFI.value.foreach { itemset =>
              val itemArray = itemset.split(",")
              var count = 0
              for (item <- itemArray) if (line._1.get(item.toInt)) count += 1
              if (count == itemArray.size) tmp += ((itemset, line._2))
            }
            tmp
          }.reduceByKey(_ + _).filter(_._2 >= SUPPORT_NUM).cache()
          val result = fi.map(line => line._1 + ":" + line._2 / TRANSACITON_NUM)
          result.saveAsTextFile(args(1) + "/result-" + i)
          bccFI.unpersist()
        }
      }
    
    
      //To get the candiate k frequent itemset from k-1 frequent itemset
      def getCandiateFI(f: Array[String], tag: Int) = {
        val separator = ","
        val arrayBuffer = ArrayBuffer[String]()
        for(i <- 0 until f.length;j <- i + 1 until f.length){
          var tmp = ""
          if(2 == tag) tmp = (f(i) + "," + f(j)).split(",").sortWith((a,b) => a.toInt <= b.toInt).reduce(_+","+_)
          else {
            if (f(i).substring(0, f(i).lastIndexOf(',')).equals(f(j).substring(0, f(j).lastIndexOf(',')))) {
              tmp = (f(i) + f(j).substring(f(j).lastIndexOf(','))).split(",").sortWith((a, b) => a.toInt <= b.toInt).reduce(_ + "," + _)
            }
          }
          var hasInfrequentSubItem = false //To filter the item which has infrequent subitem
          if (!tmp.equals("")) {
            val arrayTmp = tmp.split(separator)
            breakable {
              for (i <- 0 until arrayTmp.size) {
                var subItem = ""
                for (j <- 0 until arrayTmp.size) {
                  if (j != i) subItem += arrayTmp(j) + separator
                }
                //To remove the separator "," in the end of the item
                subItem = subItem.substring(0, subItem.lastIndexOf(separator))
                if (!f.contains(subItem)) {
                  hasInfrequentSubItem = true
                  break
                }
              }
            } //breakable
          }
          else hasInfrequentSubItem = true
          //If itemset has no sub inftequent itemset, then put it into candiateFI
          if (!hasInfrequentSubItem) arrayBuffer += (tmp)
        } //for
        arrayBuffer.toArray
      }
    }

    在这里提一下我的实验结果以便大家参考,对于2G,1800W条记录的数据,在80G内存,10个虚拟节点的集群上18秒就算完了1-8频繁项集的挖掘。应该还算不错。

    先写到这里,欢迎大家提出相关的建议或意见。
    (by希慕,转载请注明出处)

    展开全文
  • 介绍了十余种代表性的基于 CPU 和 GPU 并行化碰撞检测算法,并从算法的可扩展性和存储空间消耗以及任务量均衡化等方面分析了这些算法的优缺点。最后总结了并行化碰撞检测算法研究中存在的问题和新的发展方向以及常用...
  • 文章研究了一种多核架构下基于OpenMP的Dijkstra并行算法,以Dijkstra算法为基础设计并行程序。对传统Dijkstra算法进行分析,明确优化方向,再利用OpenMP开发工具对并行程序进行优化调试。结果表明,文中算法易于操作...
  • kmeans算法并行化

    2014-04-11 22:53:08
    本代码是全局kmeans算法在异构架构下的实现,使用cuda c语言编写。(声明,改代码是一位大牛所写,希望对你有用)
  • 为解决AprioriTid算法对大数据执行效率不高的问题,根据Hadoop平台的MapReduce模型,分析了AprioriTid算法并行化方法,给出了并行化的主要步骤和Map、Reduce函数的描述。与串行的AprioriTid算法相比,并行算法利用...
  • 算法并行化基于高级多核体系结构的高级加密标准(AES),采用滑动窗口来稳定突发流量,感测流的速度,并使用由频率比计算的窗口阈值来动态缩放频率图形处理单元(GPU)可以降低能耗。 对不同速度的流进行的实验...
  • 并行pthread求π算法

    2014-06-01 15:19:37
    用pthread方法求π,体现了pthread的基础用法。
  • 基于Hadoop大数据平台实现遗传算法并行化,借助于Hadoop中的MapReduce模型,将遗传算法划分为Map和Reduce两个阶段,在Map阶段并行化执行。真正意义上实现了遗传算法并行化
  • 实验结果表明,多线程并行和MPI并行化算法可以大大提高整体计算效率。 并且,MPI并行化模式具有更高的运行效率。 并行处理的性能与计算机的体系结构密切相关。 从服务调度和产品算法的角度出发,采用MPI并行化方法...
  • 为了提高k-nearest neighbor algorith m(KNN)算法处理大数据集的能力,本文利用Ma pReduce并行编程模型,同时结合KNN算法自身的特点,给出了KNN算法在Hadoop平台下的并行化实现。通过设计Ma p、Co mbine和Reduce 3个...
  • 计算机系研究生并行课程自己做的讲义。详细介绍了模拟退火算法的基本原理及如何进行并行化。用MPI和GPU等方法。附有有详细的名词解释,适合智能计算方向的小白。
  • 浅谈聚类 聚类说白了就是根据数据特征的不同,将数据集中的数据进行一个分组,而最终被分成的一个个组就叫做簇,聚类的结果是使得...在图像处理,模式识别等领域,硬聚类算法(HCM)和模糊聚类算法(FCM)多被用来...

    浅谈聚类


    聚类说白了就是根据数据特征的不同,将数据集中的数据进行一个分组,而最终被分成的一个个组就叫做簇,聚类的结果是使得同一类的元素相似度高,不同类元素相差很大。在分类的过程中,我们常常会用一些聚类算法使得问题相应的简化。(实际上有时看好久都看不懂这些聚类算法的时候,我内心是坚决否认问题简化这一说的嘻嘻)。

    在图像处理,模式识别等领域,硬聚类算法(HCM)和模糊聚类算法(FCM)多被用来解决探索性数据分析问题。然而随着大数据计算时代的到来,计算资源正逐渐成为处理大数据集的一个主要瓶颈。在这样的背景下,一方面要求我们对串行算法进行重新设计与改进,另一方面我们应该充分利用新兴的大规模并行架构来提高大数据集处理的效率问题。
    因此,也就引出了本篇博客的主题:最小模糊聚类算法的并行化,即PFM算法。实验结果表明,与串行算法相比,并行算法在线性加速的同时,可以保证了很好的分类质量。

    并行化的必要性


    一开始难免都会觉得,像之前接触到的串行算法基本都已经能满足数据集的分类了,对那些算法进行并行化岂不是多此一举?当然不是!
    举个可能不大恰当的栗子简单说明一下:假如本来一台计算机需要单独执行一个超大任务量的计算任务(串行),你现在把这个超大任务拆分为多个部分分摊到多个处理器上同时运行(并行),很明显,后者在时效性上的优势非常明显。
    遇到多特征数据集(多维数据集)时,大多数聚类算法都依赖迭代来找局部或者整体最优解。而基于性能考虑,往往我们在找这些最优解的时候,要求用不同的算法来进行实验测试,同时还需要研究不同数据集特征的影响。因此,聚类过程具有很高的时间复杂度。
    例如:FCM算法的执行时间随着数据的增加会以指数形式增长(这是因为执行FCM算法的过程中需要用到许多聚类数目相关的先验知识,且在多次运行之后才可以达到最佳分类效果),显然,这是一件非常费时的事情。也正因如此,聚类算法的并行化在大数据时代可以说是势在必行啊!

    算法介绍


    The fuzzy minimals algorithm —— FM最小模糊聚类算法

    • 过程分析:
      这里写图片描述

    Algorithm 1:
    最小模糊聚类算法中,n表示数据集的大小,V是包含原型的算法输出,F是矢量空间的维度,ε1表示最小估计时的误差度,ε2表示聚类过程中最小值间的差异。
    算法过程及伪代码如下:

    1.选定阈值:选定ε1和ε2的值作为标准参数
    2.对F维的原型矩阵V进行初始化
    3.根据上图式2估算一个r值
    4.for k=1;k<n;k=k+1 do
         v(0) = Xk, t=0,E(0)=1
         while E(T)>=ε1 do
    
    

    闲了补充….

    展开全文
  • 使用GPU并行化遗传算法,并行方式为粗粒度式并行,开发环境为ubuntu16.04;最终计算结果相比于传统的遗传算法,在结果精度差不多的情况下,时间约为传统方法的五分之一

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 188,486
精华内容 75,394
关键字:

并行化算法