基于GPU的K-Means聚类算法

聚类是信息检索、数据挖掘中的一类重要技术,是分析数据并从中发现有用信息的一种有效手段。它将数据对象分组成为多个类或簇,使得在同一个簇中的对象之间具有较高的相似度,而不同簇中的对象差别很大。作为统计学的一个分支和一种无监督的学习方法,聚类从数学分析的角度提供了一种准确、细致的分析工具。而k-means算法是最常用和最典型的聚类算法之一,k-means算法是典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。k-means的优点在于能快速的收敛及易于实现,但是该算法在一些数据量非常大的应用中表现出的性能是比较差的,因此,本文在研究了k-means算法的基础上,提出了利用GPU(Graphic Processing Unit)的并行计算能力来优化k-means算法的方案。

聚类分析及k-means算法

1.1 聚类分析技术

  对于给定的数据集,按照一定的度量,把其中相似度大的归为一类,这样的过程称为聚类(Clustering)。聚类分析的结果是一个个的数据或对象的集合,称之为簇(Cluster):同一个簇中的对象相似,而与其他簇中的对象则不相似。现在主流的聚类分析技术一般可以分为以下几类:

    (1)基于划分的方法。对于给定的n个对象,提供数值k(k≤N),将对象划分为k份,每一份满足“簇”的定义。典型的基于划分的算法有K-Means算法和K-Medoids算法。划分方法需要在运算之前就确定K的值。

    (2)基于层次的方法。层次方法创建给定数据对象集的层次分解。层次方法可分为:凝聚法,开始时每个对象为一类,合并相似项,直至所有对象被合并为一个类;分裂法,开始时将所有对象都归类为一个类,逐次将每个类分裂为更小的类,直至所有对象的类满足“簇”的概念,或满足其他既定的收敛条件。典型的基于层次的算法有:BIRCH算法、ROCK(RObust Clusteringusing linKs)算法和Chameleon算法。

    (3)基于密度的方法。基于距离的聚类算法更容易发现球形簇,但对于发现任意形状的簇,则力不从心。基于密度的方法能解决这个问题:对于数据集中的每一个点,在给定的半径邻域内,假设包含M个点,如果M满足既定的条件,则算法继续。常用的基于密度的方法有:DBSCAN(Density-Based Spatial Clustering of Applications with Noise)、DENCLUE(DENsity-based CLUstEring)和OPTICS(Ordering Points to Identify the Clustering Structure)。

    (4)基于网格的方法[1]。该方法将对象空间划分为一定数量的单元,组成网格,并在此基础上进行聚类。典型的例子有:STING(Statistical Information Grid)、WaveCluster。

1.2    K-Means算法

在众多基于划分方法的聚类算法中,K-Means算法是最著名和最常用的算法之一。K-Means算法以k为输入参数,将给定的n个对象,划分为k个簇,使得簇内的对象相似度高,而不同簇内的对象的相似度低。

K-Means 算法的主要流程如下:

(1)在给定的n个对象中,随机选取k个对象,作为每一个簇的初始均值(中心);

(2)对于其余的n-k个对象,分别计算与k个中心的距离,将对象指派到最接近的簇;

(3)更新每个簇的新均值,得出k个新的中心;

(4)根据k个新的中心,重复(2)(3)两个步骤,直至准则函数收敛。

虽然K-Means算法实现起来比较简单,但K-Means算法也存在以下问题:

(1)需要对全部N个数据进行多次遍历,假设为 M 次;每次遍历中,对每个数据都需要进行 k 次比较运算,则计算复杂度为O(N*M*k),同时还需要反复读取原数据,并将比较结果多次写到存放分类信息的结果集中。虽然通常情况下,M<<N,且k<<N,但算法的计算复杂度依然偏高,执行效率较低,并且对系统I/O的压力也很大;

(2)K的大小需要在算法前确定,并且一般需要用户指定。这就需要依靠用户的经验,在运算前就明确,或大概明确现有的数据有多少个分类;

(3)对于异常点、离群点较敏感,一个异常点就可能影响整个算法的结果;

(4)初始簇中心的选取可能会对整个聚类结果产生很大的影响,甚至能产生截然不同的聚类结果。

因此,不少学者针对以上问题从不同方面提出了一些优化的方案[2]。例如,文献3中提出了一种使用K-D Tree来加速算法的执行时间的方案[3]。另一种方案是将K-Means算法中的计算部分高度并行化,文献4中提出利用OpenMP来优化K-Means算法[4]。但这种方法不可避免地会产生大量的多线程通信代价。

目前,大多数桌面计算机都配置了可编程的图形处理器(GPU,Graphic Processing Unit)。GPU是一种单指令流多数据流(SIMD)计算模式的处理器,在处理单元的数量上要远远超过CPU ,拥有数十个甚至上百个处理核心。尽管GPU的运行频率低于CPU,但更多的执行单元数量能够使GPU在浮点运算能力上获得大幅优势,同时期主流的GPU性能可以达到CPU性能的10倍左右。近年来,GPU性能的飞速发展,加上基于GPU的可编程性越来越简单,使得基于GPU并行计算来优化K-Means算法成为可行。

本文提出了一种基于GPU并行计算的K-Means算法的优化方案,将传统K-Means算法中计算密集部分采用并行化的方法在GPU上计算。下文将详细介绍GPU并行计算的相关原理及基于GPU并行计算的K-Means算法。

2     GPU通用计算编程模型

    图形处理器技术的迅速发展带来的并不只是速度的提高,还产生了很多全新的图形硬件技术,使GPU具有流处理、高密集并行运算、可编程流水线等特性,从而极大的拓展了GPU的处理能力和应用范围。正是由于GPU具有高效的并行性和灵活的可编程性等特点,越来越多的研究人员和商业组织开始利用GPU完成一些非图形绘制方面的计算,并开创了一个新的研究领域:基于GPU的通用计算(GPGPU,General-Purpose computation on GPU),其主要研究内容是如何利用GPU在图形处理之外的其他领域进行更为广泛的科学计算。

GPU通用计算通常采用CPU+GPU异构模式[5],由CPU负责执行复杂逻辑处理和事务处理等不适合数据并行的计算,由GPU负责计算密集型的大规模数据并行计算。这种利用GPU强大处理能力和高带宽弥补CPU性能不足的计算方式在发掘计算机潜在性能,在成本和性价比方面有显著的优势。在2007年NVIDIA推出CUDA(Compute Unified Device Architecture,统一计算设备架构)之前,GPU通用计算受硬件可编程性和开发方式的制约,开发难度较大。2007年以后,CUDA不断发展的同时,其他的GPU通用计算标准也被相继提出,如由Apple提出Khronos Group最终发布的OpenCL,AMD推出的Stream SDK,Microsoft则在其最新的Windows7系统中集成了Direct Compute以支持利用GPU进行通用计算,程序员利用这些语言可以比较轻松地把一些应用程序移植到GPU上。

        CUDA编程模型[6]将CPU作为主机(Host),GPU作为设备(Device)。在一个系统中可以存在一个主机和若干个设备。CPU、GPU各自拥有相互独立的存储地址空间:主机端内存和设备端显存。CUDA对内存的操作与一般的C程序基本相同,但是增加了一种新的pinned memory;操作显存则需要调用CUDA API存储器管理函数。一旦确定了程序中的并行部分,就可以考虑把这部分计算工作交给GPU。运行在GPU上的CUDA并行计算函数称为kernel(内核函数)。一个完整的CUDA程序是由一系列的设备端kernel函数并行步骤和主机端的串行处理步骤共同组成的。这些处理步骤会按照程序中相应语句的顺序依次执行,满足顺序一致性。

3     基于GPU的K-Means算法

        从上文对K-Means算法主要流程的介绍中可以看到,K-Means算法的主要计算任务集中在第(2)、(3)这两个步骤,即计算每个对象与K个簇的距离,并将每个对象分配到一个簇中以及更新每个簇的新中心。因此,基于GPU的K-Means算法主要从这两方面来考虑如何进行并行优化。

3.1    数据对象分配

基于GPU的K-Means算法在进行数据对象分配这一步骤的时候有两种策略。第一种策略是面向每个簇的中心,通过计算出该簇的中心与每个数据对象的距离,然后将每个数据对象归并到距离簇中心最近的那个簇中。这种策略适应于GPU的处理核心数量比较少的情况,此时,GPU中的每个处理核心可以对应一个簇的中心,并且能够连续的处理所有的数据对象。另一种策略是面向每个数据对象,每个数据对象计算与所有簇中心的距离,然后数据对象将会被分配到距离簇中心最近的那个簇当中。该策略适应于GPU的处理核心比较大的情况,目前主流的GPU一般都有超过100个处理核心,因此第二种处理策略比较合适。图1展示了上述两种策略的不同思想。

 

图1 数据分配过程不同策略对比图

3.2    更新K个簇的中心

新的簇中心是通过计算原有簇中所有数据对象的数学平均值得到的。K-Means算法中K个簇中心的位置也可以通过GPU来计算,CUDA中的每个线程负责一个簇中心,如图2所示。

图2 更新K个簇的中心

当数据对象分配结束之后,可以得到每个数据对象所属的簇的下标。要重新计算每个簇的中心位置,一个直观的想法就是读取所有的数据对象,然后判断哪些属于一同个簇。但是,在GPU上如果大量线程都需要同时访问共享内存的话,势必会因为等待访问造成大量的延时,因此这里先将数据对象分配的结果从设备(GPU)传送到主机(CPU),然后由主机来重新安排,并计算出每个簇包含数据对象的数量。之后,将处理过的数据再传送给设备的共享内存。通过这种途径,CUDA中每个线程只需连续地读取属于该簇的数据对象的数据来计算平均值,从而不会发生多个线程对共享内存竞争的情况。

3.3    整体思想

基于GPU的K-Means算法的主要思想是将传统的K-Means算法中的数据独立,计算密集的部分从主机转移到设备上处理,从而提高性能。更具体的说,数据对象的分配过程和K个簇中心的更新过程虽然要执行很多次,但每次计算以及每次计算的数据之间都是相互独立的,并不存在前后依赖的关系,因此可以将其分离成两个单独的内核函数,交给GPU的大量的处理核心来并行计算。

尽管GPU的SIMD的计算模式擅长并行计算,但是基于GPU的K-Means算法有三个重要的原则需要说明。第一,GPU设备的分支转移控制和数据缓存机制都非常弱,因为大量的计算处理单元占用了GPU内部的大部分空间。第二,GPU与GPU全局内存之间的数据传输速率和CPU与CPU高速缓存之间的数据传输速率相比要慢很多,因此适当的线程块和线程束大小才能体现出GPU的强大计算能力。第三,与传统的K-Means算法相比,基于GPU的K-Means算法增加了在GPU全局内存与CPU内存之间传输数据的时间。因此要达到优化算法性能的目的,必须合理地分配主机与设备的职责,合理地设计与实现数据存储和并行计算的模式。

基于GPU的K-Means算法的主要流程图如图3所示。

图3 基于GPU的K-Means算法流程图

如图3所示,在任务职责分配方面,主机部分主要负责随机产生初始的K个簇的中心,对数据对象分配的结果进行预处理以及判断聚类过程是否已经收敛;而设备部分则主要负责数据独立的密集型计算过程。在数据存储方面,所有的数据对象以及簇中心的数据都需要在设备上以数组的形式存储。在GPU设备上,核函数中所有线程所共享的内存有三类:常量内存,纹理内存以及全局内存。常量内存和纹理内存都是只读的而且其有用的大小也很有限,所以对于算法中的数据是不合适的。另外,在GPU和显存之间的传输带宽要比在主机内存和显存之间传输数据的带宽高得多,考虑到这一点,在基于GPU的K-Means算法中,在主机和设备之间传输的簇中心的下标数据大小要尽量的小。这种基于CPU+GPU异构模式虽然会产生额外的数据I/O的时间消耗,但是GPU的计算模型中,大量线程的并行能够减少读取内存的延迟。

4     总结

        本文阐述了传统的K-Means聚类算法的具体过程以及其中的复杂性和效率问题,并提出将其中计算密集的处理部分分离到GPU上进行处理的优化方案。随着CUDA、OpenCL、Stream SDK等其他GPU通用计算标准的提出和发展,GPU的强大处理能力和高带宽的特点将会越来越突显。本文的主要研究目的在于提出将信息检索和数据挖掘方面的部分经典算法与GPU并行计算相结合的思想,使其通过并行处理在性能上达到高效的优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/448785.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GPU通用计算调研报告

摘要&#xff1a;NVIDIA公司在1999年发布GeForce256时首先提出GPU&#xff08;图形处理器&#xff09;的概念&#xff0c;随后大量复杂的应用需求促使整个产业蓬勃发展至今。GPU在这十多年的演变过程中&#xff0c;我们看到GPU从最初帮助CPU分担几何吞吐量&#xff0c;到Shader…

git 图形化工具 GitKraken 的使用 —— 分支的创建与合并

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 分支管理是Git工作流的重点 在之前的文章中通过GitKraken可以很清楚的看到&#xff0c;每一次commit&#xff0c;git把他们串成了一条线…

GitKraken - 简单教程

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 简单介绍&#xff1a;外观 GitKraken首页预览图 常用快捷键 模糊搜索&#xff1a;(cmd p) 在进行模糊搜索的时候会在当前页面弹出一个…

LeetCode刷题第二天——3Longest Substring Without repeating character 4 Median of Two Sorted Arrays...

混淆点&#xff1a; 子串 连续 子序列 可以不连续 知识点&#xff1a; HashMap&#xff1a; 出现问题&#xff1a; 1.使用unordered_map头文件时报错 #error This file requires compiler and library support for the ISO C 2011 standard. This support is currently experi…

【BZOJ 3339 / BZOJ 3585 / luogu 4137】Rmq Problem / mex

【原题题面】传送门 【题解大意】 都说了是莫队练习题。 考虑已知[l,r]区间的mex值时&#xff0c;如何求[l1,r]的mex值。 比较a[l1]与已知ans的大小&#xff0c;如果a[l1]>ans或者a[l1]<ans&#xff0c;均对答案没有影响。 如果a[l1]ans&#xff0c;考虑找到一个比当前an…

postman 无法正常返回结果 Could not get any response

在浏览器输入地址可以返回结果&#xff0c;但是由于返回的json没有格式&#xff0c;看起来比较麻烦&#xff0c;用postman却报错Could not get any response。 可以注意到下面写了可能的情况&#xff1a;比如服务器无响应&#xff08;由于浏览器可以访问&#xff0c;所以排除…

在Windows 下使用OpenCL

目前&#xff0c;NVIDIA和AMD的Windows driver均有支援OpenCL&#xff08;NVIDIA的正式版driver是从195.62版开始&#xff0c;而AMD则是从9.11版开始&#xff09;。NVIDIA的正式版driver中包含OpenCL.dll&#xff0c;因此可以直接使用。AMD到目前为止&#xff0c;则仍需要安装其…

[Swift]快速反向平方根 | Fast inverse square root

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号&#xff1a;山青咏芝&#xff08;shanqingyongzhi&#xff09;➤博客园地址&#xff1a;山青咏芝&#xff08;https://www.cnblogs.com/strengthen/&#xff09;➤GitHub地址&a…

适用于ATI卡的GPU计算MD5的小程序源码,基于AMD APP SDK开发

以下代码在win7 home basic , ati hd 5450平台测试通过&#xff0c;处理速度为每秒100万次。 程序很简单&#xff0c;只有一个main.cpp程序。Device端只有一个md5.cl文件。 下面我把代码贴出来&#xff0c;因为不能上传附件&#xff0c;我把完整工程包放到了242337476的群共享里…

【CentOS 7笔记11】,目录权限,所有者与所有组,隐藏权限#171022

2019独角兽企业重金招聘Python工程师标准>>> shallow丿ove 一. 文件或目录权限change mode r4&#xff0c;w2&#xff0c;x1 selinux开启则权限后面会有个. 更改SElinux配置文件&#xff0c;将永久关闭SElinux [rootlocalhost ~]# vi /etc/selinux/config #将默认…

python字符编码与转码

详细文章: http://www.cnblogs.com/yuanchenqi/articles/5956943.html http://www.diveintopython3.net/strings.html 需知: 1.在python2默认编码是ASCII, python3里默认是unicode 2.unicode 分为 utf-32(占4个字节),utf-16(占两个字节)&#xff0c;utf-8(占1-4个字节)&#xf…

IntelliJ IDEA 详细图解最常用的配置

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 刚刚使用IntelliJ IDEA 编辑器的时候&#xff0c;会有很多设置&#xff0c;会方便以后的开发&#xff0c;磨刀不误砍柴工。 比如&#x…

OpenCL快速入门教程

OpenCL快速入门教程 原文地址&#xff1a;http://opencl.codeplex.com/wikipage?titleOpenCL%20Tutorials%20-%201 翻译日期&#xff1a;2012年6月4日星期一 这是第一篇真正的OpenCL教程。这篇文章不会从GPU结构的技术概念和性能指标入手。我们将会从OpenCL的基础API开始&…

Git使用教程-idea系列中git使用教程

一、新建项目 新建项目后记得复制git仓库的地址。 二、上传项目到git仓库 在你的idea里新建git仓库&#xff0c;这是新建本地仓库&#xff0c;等会会同步到线上git仓库 新建后如果代码不是文件名不是绿色的表示没有加入到git索引中 将需要上传的文件按照下图方式add 添加后&…

分布式开放 消息系统 (RocketMQ) 的原理与实践

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 分布式消息系统作为实现分布式系统可扩展、可伸缩性的关键组件&#xff0c;需要具有高吞吐量、高可用等特点。而谈到消息系统的设计&…

使用 OpenCL.Net 进行 C# GPU 并行编程

在 初探 C# GPU 通用计算技术 中&#xff0c;我使用 Accelerator 编写了一个简单的 GPU 计算程序。也简单看了一些 Brahma 的代码&#xff0c;从它的 SVN 最新代码看&#xff0c;Brahma 要转移到使用 OpenCL.Net 作为底层了&#xff0c;于是也去网上搜索了一下&#xff0c;发现…

模拟真实环境之内网漫游

0x00 前言 目标ip&#xff1a;192.168.31.55&#xff08;模拟外网&#xff09; 目的&#xff1a;通过一个站点渗透至内网&#xff0c;发现并控制内网全部主机 0x01 信息收集 用nmap进行端口探测 浏览站点时查看元素发现该站点是DotNetCMS v2.0 该版本cms存在SQL注入漏洞&#x…

超简单:解析 yml 类型(application.yml)配置文件 、springboot 工程读取 yml 文件中的值

方法三是我觉得最简单的。 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 工程结构&#xff1a; 2. 我要读取 application.yml 中属性 &#xff1a;spring.rocketmq.namesrvAddr …

初探 C# GPU 通用计算技术

GPU 的并行计算能力高于 CPU&#xff0c;所以最近也有很多利用 GPU 的项目出现在我们的视野中&#xff0c;在 InfoQ 上看到这篇介绍 Accelerator-V2 的文章&#xff0c;它是微软研究院的研究项目&#xff0c;需要注册后才能下载&#xff0c;感觉作为我接触 GPU 通用运算的第一…

Jenkins 详细安装、构建部署 使用教程

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Jenkins是一个开源软件项目&#xff0c;是基于Java开发的一种持续集成工具&#xff0c;用于监控持续重复的工作&#xff0c;功能包括&…