科学计算 | Matlab 使用 GPU 并行计算

 
 
 

Matlab下直接使用GPU并行计算(预告)<-- 这预告也贴出来太久了,然而我的大论文还是没有写完,但是自己挖的坑一定要填上,我可不是写小说的。

 

小引言

说它小是因为它只是博士论文的附录一部分,但是其实我还是用了很久才学明白的

中心处理器(CentralProcessing Unit, CPU)是计算机系统的计算和控制核心,在轨道设计中使用计算机程序进行研究和仿真都依赖于CPU的强大计算能力,是研究者经常接触并且熟悉的概念。图形处理器(Graphics Processing Unit, GPU)是计算机设备中用来进行绘图运算,支持显示器设备的芯片。GPU的计算速度和指令复杂度远不及CPU,但是由于其支持高刷新率高分辨率显示设备的需求,GPU具有高并行数、大数据吞吐量的特征,并且在这方面的能力远高于CPU。早在2001年左右,便有人提出了基于GPU的通用计算(General-purpose computing ongraphics processing units, GPGPU)的概念,利用GPU的强大的并行计算能力和相对的低功耗来加速科学计算。基本思路是把需要计算的数据打包成GPU可以处理的图像信息,然后利用处理图像信息的运算来实现科学计算。直到2008年左右,NVIDIA公司推出了CUDA(Compute Unified Device Architecture)并行计算架构,代替了GPGPU的概念,并发布了支持C,C++,Fortran的函数库和编译器。CUDA是NVIDIA发明的一种并行计算平台和编程模型。它通过利用图形处理器 (GPU) 的处理能力,可大幅提升计算性能。此后经过一系列的发展和迭代,现在CUDA已经能够支持符合IEEE标准的双精度运算,并且支持越来越丰富的流程控制,至于是多维数组和显存动态分配等功能。

了解GPU的物理结构和动作方式,在一定程序上有助于提高代码的效率,也有且于开发和调试程序。下面基于本论文使用的GPU型号GTX850M,简要介绍一下GPU的物理结构。如下图所示,该GPU核心的实际运算单位有640个,即每个绿色的小块代表的最基础的计算单元流处理器(Streaming Process,SP),它们在GPU内部被组织成不同的结构,来实现常用的图像处理功能。

上图是计算结构的放大图,一行中的每4个SP和一些共用的存储资源等被组织成一个流多处理器(Stream Multiprocessor,SM);每8个SM,即每8行,添加一些指令调度功能构成一个warp,是GPU中最小的调度单元。在直接调用CUDA进行C/C++编程时,多个计算thread被组成一个block,然后多个block被组织一个grid,最终GPU按照block来调度所有任务在每个warp上进行计算。可以想象,每个block中thread个数,每个grid中block个数的划分,都会影响到能否充分利用GPU的计算能力,而合理的选择即需要不断的尝试,也需要对并行计算算法的理解和较高水下的编辑能力,是一个极其复杂的过程。

好了,看完这些,实际上并不能帮助你了解GPU大概有什么作用,怎么用,还不如直接去看Matlab帮助文档,上述基本都是废话,然而我相信等你熟悉了用Matlab调用GPU跑程序以后,你会发现这些废话基本还算是精髓。

GPU怎么工具

GPU有显存,还有缓存,也不管它对应上面那个图中哪些块块儿,反正我们也涉及不到这么深入的编程,统称为显存好啦。GPU只能直接计算显存中的数据,就好像CPU只能计算内存中的数据,显存中的数据或者由CPU从内存移入到显存,或者直接由GPU在显存中创建。(很好理解吧,总不能拿个电池在显存上搓一搓就写入了数据吧,你知道我在讲哪个段子对吧,很冷对吧。)

然后,GPU就可以对显存里的数据进行各种计算,但是很显然可以执行哪些计算决定于GPU的能力。比如我的执行 gpuDevice 这个命令后,可以查看显卡的能力 ComputeCapability 是5.0,我只记得1.3以上就可以支持双精度运算,即 double,因此 Matlab 也要求必须是 1.3 以上的 GPU 才可以调用。(一般 gtx 8xx 以上的显卡都是5.0)。


平时不用显卡做数值计算的时候,它其实就是每秒算60几张屏幕大小的图,然后不停地输送给显示器。所以可以想象,显卡的计算能力有多大,然而遗憾的是,喂显示器数据的计算都很简单,简单倒可以把一些算法硬件化来提速,而且单精度就足够了,而且偶尔错一两个像素也无所谓,而且帧数算不过来就跳几帧也看不出来……总之因为它的出身是显卡,这些职业特性导致让它做数值计算会有很多麻烦。当然,Nvidia也在解决,你们肯花钱就好。

好在,用Matlab调用GPU计算,一切都简单了,反正除了修改代码和调研,上述困难我都暂时没有碰到~

在 Matlab 中使用 ode45

这就是本文主要实现的功能,相信有很多人想过用并行计算来加速积分器ode45,但是很遗憾,RKxx这种积分器的数学性质决定它一定是不可以并行的,可以去网上搜,一般中文的答非所问,英文的告诉你不行(有一些其它的积分器有学者在研究并行,基本理念都是用特殊函数基底去近似微分方程的解,然后基函数的系数是有办法可以并行迭代求解的,不展开,外行)。

此处实现的GPU上并行计算ode45是这样,每个GPU的小核计算一个ode45,所以同时可以有1000多个ode45在跑,这个意义上的并行。我的应用场景是搜索参数空间里的格点,每个格点都要积分较长时间,并且在积分中判断每步的状态。

(写得好累,语言的表达总是跟不上思路……)

越写越觉得这个事情不是一句两句能说清楚的,但是实际真的不难……

啰嗦的详细步骤

 

还是一样的工具箱,在熟悉的parfor下面不远处,有个GPU Computing的条目,建议把它通读一遍,内容很少,不比一篇高水平的文章多。

具体要学**的目录如下

一点都不多,而且只需要学**前三个就好,为了把ode45改写到可以在GPU上运行,我选中的这第三个才要重点理解。

点进去首先看这部分,学**怎么在GPU上建立矩阵

”Transfer Arrays Between Workspace and GPU“基本就是一句语法,

agpu = gpuArray(a)

这样就把正常的一个矩阵a变成了GPU上的矩阵agpu(不用非这么命名,也可以叫axianka,嗯,我是在吐槽)。这是之前讲的CPU把数据从内存移动到显存,可以想象,GPU自动生成数据的功能就是上面那个”Create GPU Arrays Directly“,包含一些随机数函数啥的,而且Matlab一再强调与CPU下的不同,用的时候再看就好了,反正我是用不到。

然后就是是学**怎么用这些gpuArray类型的数据。哦对,上述这些显存上的数据,类型是gpuArray,如下图whos a agpu的结果


想要让CPU用这些gpuArray的时候,用gather可以把它们取回到内存变成double(此处不要问问题,不要多想,我假装啥也不知道,用到时候查查文档或者google一下就可能解决的,相信我~)

继续

然后就是是学**怎么用这些gpuArray类型的数据,学**下图中的Run Built-in Functions on a GPU部分

这部分介绍了Matlab内嵌的,可以支持gpuArray数据类型的数据的函数。就是说,你给这些函数输入之前的agpu,它们是会傻傻地算的,并且计算是发生在GPU上,结果也是在显存中。但是,……算了一会儿下一小段再但是。

再来学**如何在Matlab上运行自定义函数,这里也就是我们将要修改的ode45函数


可以看到,我在这里强调了element-wise函数,在Matlab上运行的自定义函数,必须是每个输入都是1维的,element-wise,就像 .*,./,.^ 什么的一样的element-wise operator。这个element-wise的要求,是对自定义函数内部全部操作而言的,即没有向量操作,没有矩阵操作,没有矩阵乘,没有求逆,没有各种……甚至不能有索引出现,当然,没有前面那些还要索引做什么。我的GPU版本的ode45中矩阵都是折成分量,把乘法一点点写出来的,就跟当年学C时候一样,感觉自己像个小孩子。

哦,值得说一下,在内部不能动态定义数组,比如a = [a,1]这种操作是不可以的,因为CUDA好像不支持这功能,而且,这不就出现数组了嘛,记住原则是element-wise。

然后最令人崩溃的一个表格来了,下图,支持的Matlab code


我当时看到这个的时候, 直接略过,这什么嘛,又重复一遍,和前面那个图不是一样样的嘛。

当我在GPU什么都跑不起来的时候,自定义函数不停报错的时候,我又看到这部分的时候,唉,让我静静……再次告诉我,别以为Matlab里有一句是废话,一定仔细看,不然全是坑……

说正经的,这些函数Matlab称之为Supported Matlab Code的意思(我揣测)是说这些函数是所有你可以在GPU上运行的自定义代码里使用的函数,即你写GPU自定义code只能用这些,别的不支持。比如**惯了写成sind(30)的必须现在写成sin(30/180*pi),明白了?好在pi是支持。仔细看看,其实跟C的基础数学库差不多,多个inf,pi,randi啥的,值得注意的是支持全部的常用流程控制for,while,continue,然而switch,try,catch这些高级货是没有的。

好了,有这些知识 ,基本上就可以改你手头的代码了,改成符合上述要求的:

  • 只用了这些基本函数和流程控制

  • 通篇element-wise操作

  • 其它……

(写其它是为了严谨,毕竟我也是新手门外汉二把刀,纯粹是为了提高公众号知名度才来写这**的,才不是因为真心热爱学术喜欢搞技术呢~~话都说这儿了,得帮我推广一下吧,您呢~)

改完以后,用arrayfun这个函数调用,像这样:


arrayfun的第一个参数是在GPU上运行的自定义函数fungpu,这里它内部调用了下面要讲的ode45修改版,后续的参数依次是fungpu的参数,其中只要有一个是gpuArray类型的(这里的t10vector),其它参数全部会被传送到显存,然后fungpu就会在GPU上运行。

下面我就开始介绍修改ode45的过程,

(其实想想你跟我修改ode45并没有多大用,重点还是上面讲的那些多看看多琢磨,平时科研碰到用得上的问题留个心,有功夫了就尝试一下,有问题多思考或者去google或者来交流讨论,这样才有效果)

考虑到这么深切的原因而不是因为我懒,我就精简地讲一下。

先看下ode45的源码,我知道其实很多人都已经读过了。

没读过也不要紧,相信我,如果不是有需求被逼,你情愿自己写一个rk45或者rk78也不愿意读这功能强大的代码(不得不说官方的代码写得很好,好用又好读,还好改)

上面红杠的部分,基本是要删掉的,因为在GPU上不支持,这些都是一些高级功能,比如Event啊啥的,还有一些通用性的功能。

我们需要的功能主要在红框中,主要是ode45的rk45算法部分。

(注意上面的代码我折叠了很多,折叠了很多,折叠了很多,而且不是严格按照我划的改,随手一划,你懂得,随手)

修改这部分代码

比如我是积分三维空间中的轨道,所以输入的变量是6维,时间是1维,还有些其它质量比例什么的参数。

改后的结果如下:可以看到此时精度也作为独标量直接输入,而不能再用Name-Value pair的形式输入,其它的功能都被精简掉了,因为GPU不支持。


可以看到原先的矩阵操作都被写成了分量形式,其实也不难,对吧。

下面看到的一些中文注释,很多是在读ode45代码时根据当时理解添加的。注释总不嫌多,对吧。


看,RK45每步求微分的过程,也要用分量形式写出来了,其中的OdeRtbpElementWise函数应该能猜到是什么吧,就是要积分的动力学方程,也被写成了分量形式的输入输出,1个时间,6个状态。


误差分析也要一点一点拆,就当复**了一遍数值分析,对吧。你看这大段大段的英文原版注释,我都没有动过的,说明修改的工作量其实也不大,对吧。


这就结束了,有没有觉得很神奇?这货就可以在GPU上积分啦!

等等,并没有,还没有讲输出。因为GPU不支持自定义函数的索引功能,不支持动态数组,我们不能像正常ode45一样输出轨道的时刻序列,只能输出某一个状态,这里我们选择末状态[t,y1,y2,y3,y4,y5,y6]。

这样便存在一个问题,如何验证整个过程中轨道是正确的?很简单。

用ode45从t0到t1积分一遍,取ii=1:1000个点画图。

用ode45gpu积分一遍,分别从t0到t0+ii/1000积分ii=1:1000条轨道,注意这1000条轨道是同时被计算的,所以和从t0到t1直接积分的耗时只差一点点一点点。

然后gather回来重叠画图比较
这个图就是这么画的,所以你看这么多小点点~~怎么样,不难吧?

还有一个调试的问题没有讲到,是程序就免不了调试。其实也不用讲,都在Matlab下了,还要怎么讲,直接在CPU下串行调试就好啦,保证element-wise的原则,正常调试喽。

应该就讲完了,再讲就是各种细节了,我觉得没必要。

最后上个图说明一下有效性:

上图是在星历模型下搜索得到的某种结果图,下图是在某种近似模型下搜索得到的同种结果图,关键点在于分布规律是一样的!说明GPU的积分精度和直接在CPU上的RK78积分精度是可比拟的,是可用的。

上图大约14小时,分12x16线程计算,2.3GHz的CPU,用的UPC的服务器,还是FORTRAN77的计算效率;

下图大约13小时,显卡GTX850M超频后1.2GHz,Matlab自动划分各种Warp,Block啥的。

可见,加速能力还是相当强悍的,才是个不到1000块钱的笔记本显卡。

当然这里有一个问题,GPU如何使用星历模型,窃以为这个问题并不存在一个简单的可以仅依靠Matlab解决的途径,所以,管它呢……


写得着实太粗糙,如果有问题或者有错误,还请右下角随意“留言”,我会认真回复的。

如果有想以我这个为基础研究一下的,我可以考虑分享我的代码给你,暂时还没有想好形式,而且应该要在6月份以后了。


科学计算 | Matlab 使用 GPU 并行计算的更多相关文章

  1. 动态可视化 数据可视化之魅D3,Processing,pandas数据分析,科学计算包Numpy,可视化包Matplotlib,Matlab语言可视化的工作,Matlab没有指针和引用是个大问题

    动态可视化 数据可视化之魅D3,Processing,pandas数据分析,科学计算包Numpy,可视化包Matplotlib,Matlab语言可视化的工作,Matlab没有指针和引用是个大问题 D3 ...

  2. 为什么GPU可以用于科学计算【转载】

    转自:https://blog.csdn.net/xihuanyuye/article/details/81178352 https://www.zhihu.com/question/35063258 ...

  3. 【书单】matlab 科学计算、数值分析以及数学物理问题

    1. 数学计算 MATLAB数值计算 MATLAB之父 : 编程实践 2. 数学物理问题 高等应用数学问题的MATLAB求解(第3版)(豆瓣评价极好) 3. 模式识别

  4. Julia语言:让高性能科学计算人人可用

    Julia语言:让高性能科学计算人人可用要:一群科学家对现有计算工具感到不满:他们想要一套开源系统,有C的快速,Ruby的动态,Python的通用,R般在统计分析上得心应手,Perl的处理字符串处理, ...

  5. julia,集Python、C++、R为一体!Julia 1.0重磅发布, MIT发布史上最强科学计算编程语言?创始人独家解答11个问题

    这个编程语言的新版本之所以受到整个人工智能界的关注,最主要的原因正是其将 C 语言的速度.Ruby 的灵活.Python 的通用性前所未有地结合在一起,支持并行处理,易于学习和使用,尤其适合科学和工程 ...

  6. Python 网页爬虫 & 文本处理 & 科学计算 & 机器学习 & 数据挖掘兵器谱(转)

    原文:http://www.52nlp.cn/python-网页爬虫-文本处理-科学计算-机器学习-数据挖掘 曾经因为NLTK的缘故开始学习Python,之后渐渐成为我工作中的第一辅助脚本语言,虽然开 ...

  7. [resource-]Python 网页爬虫 & 文本处理 & 科学计算 & 机器学习 & 数据挖掘兵器谱

    reference: http://www.52nlp.cn/python-%e7%bd%91%e9%a1%b5%e7%88%ac%e8%99%ab-%e6%96%87%e6%9c%ac%e5%a4% ...

  8. Desktop Ubuntu 14.04LTS/16.04科学计算环境配置

    Desktop Ubuntu 14.04LTS/16.04科学计算环境配置 计算机硬件配置 cpu i5 6代 内存容量 8G gpu GTX960 显存容量 2G(建议显存在4G以上,否则一些稍具规 ...

  9. Python 科学计算-介绍

    Python 科学计算 作者 J.R. Johansson (robert@riken.jp) http://dml.riken.jp/~rob/ 最新版本的 IPython notebook 课程文 ...

随机推荐

  1. 二进制<3>

    Matrix67:位运算简介及实用技巧(三) 进阶篇(2) (2010-07-27 11:10:44) 转载▼ 标签: it 分类: 老贾·OI相关 n皇后问题位运算版    n皇后问题是啥我就不说了 ...

  2. NOIP2017赛前模拟(5):总结

    题目: 1.刮刮卡 已知n(n<=1000000)张刮刮卡按顺序排列,刮开可以获得B元现金和B个积分,购买刮刮卡需要A元,某人若按照顺序刮开的话··当B的总和小于A时便会停止刮卡(即花出去的钱多 ...

  3. CF985F Isomorphic Strings (字符串Hash,巧解)

    题目链接 题意翻译 给你一个长度为 \(n\) 的字符串,\(m\) 次询问. 问两个相同长度的子串是否匹配. 我们称两个子串是匹配的,当且仅当其满足: 其中一个子串的字母可替代另一个子串的字母 例如 ...

  4. adb shell am命令

    adb shell am命令是在cmd命令行可以通过命令来启动Activity,Boradcast,Service等,更多使用可以参考下面附件. 比如在cmd串口我们发送广播,广播action是&qu ...

  5. IOs动画的那些事儿

    CoreAnimation介绍 1:Core Animation是直接作用在CALayer上的(并非UIView上)非常强大的跨Mac OS X和iOS平台的动画处理API,Core Animatio ...

  6. uva 103 Stacking Boxes(最长上升子序列)

    Description    Stacking Boxes  Background Some concepts in Mathematics and Computer Science are simp ...

  7. STL学习笔记(七) 程序中使用STL

    条款43:算法调用优先于手写循环 class Widget { public: bool test(); }; vector<Widget> vec; 算法调用: for_each(vec ...

  8. Introduction to the WinPcap Networking Libraries

    Introduction to the WinPcap Networking Libraries use wire shark or fiddler

  9. 学习javascript设计模式之装饰者模式

    1.装饰者模式定义:给对象动态添加职责的方式称为装饰者(decorator)模式. js如何实现装饰者模式 通过保存原函数引用方式改写某函数 window.onload = function(){al ...

  10. eclipse 的SVN安装

    打开eclipse -> Help ->Install New Software选项, 点击Add按钮   根据需要,添加自己需要的版本svn控制器的版本,填写name和url,点击ok. ...