zoukankan      html  css  js  c++  java
  • CUDA显卡运算编程菜鸟入门指南1——Hello world

     第一次知道有显卡(GPU)编程这个东西,是去年比特币最热门的时候,看了几篇关于比特币的文章,说比特币挖矿要靠显卡,CPU的速度与GPU根本就没法比,于是就非常好奇,显卡是什么神奇的东西?为什么运算速度会比CPU快很多?当时也只是好奇而已,根本没想过这东西会与自己有任何关系。

    去年年底的时候,我开始研究机器学习,试着用PHP编了几个遗传算法和神经网络算法的程序,发现很有趣,功能很强大,我一直想做医学方面的人工智能开发,觉得机器学习这个东西很有用,但就是运算速度太慢,估算了一下按程序的运行速度,要初略的解决我的问题至少要算一两个星期,如果要以较高的精确度解决我的问题,可能要算几个月。仔细权衡利弊之后,我决定从头学C语言,毕竟C是高级语言中运算速度最快的(现在后悔,当时要从C++开始学就更好了)。从初学到把我的php程序改写为C,一共花了两个星期左右,可喜的是运算速度提高了大约150倍。

    后来发现神经网络用遗传算法来驱动远不如用退火算法驱动效率高,并且神经网络算法可以有很多冗余计算可以去掉,这样一来,我的算法效率前前后后又提高了一万多倍,与最初的PHP程序相比,运算效率已经提高了大约200万倍。 尽管如此,我还是不满意,因为问题稍微复杂些,且要求的精度再高些,我的电脑还是要没日没夜转好几天,我希望程序运算速度能够再有至少一个数量级的提升,在软件上能改进的地方几乎都改进了,只能在硬件上想办法了。

    我本以为,按照摩尔定律,CPU的运算速度每一年半要提升一倍,不怕大家笑话,我现在的电脑是2007年买的,已经过去七年了,最新的CPU速度应该提升二十多倍了,于是我上网查了一下,竟然发现最新款的电脑,CPU的主频不过比我的多10%左右,这是怎么回事?再查才知道,原来CPU的摩尔定律到2008年左右就失效了,这么多年来CPU主频都没有大的变化,主要靠不断增加CPU的数量(双核、四核、八核.......)进一步提高电脑性能,但这种多核结构对于我要解决的问题,帮助似乎并不明显。

    于是我就想到比特币文章中提到的GPU运算——这个从来没觉得会与自己有关系的东西。

    查了一些文章,大致了解到GPU之所以比CPU快得多,并不是GPU的处理器运算速度更快——其实目前最好的显卡,处理器的主频也不到CPU的一半——但是CPU只有一个处理器,而GPU的处理器少则几十个,多则几千个,一只手干活干得再快,也没有成百上千只手一起干活干得快,就是这个道理。

    GPU这个特点决定了并不是所有程序都适合用GPU来加速,只有你的问题能够分解为若干能够独立执行的部分(即一部分程序的运算,并不依赖于另一部分运算的运行结果),才适合考虑用GPU来处理,这也是GPU编程的核心观念:并行运算。

    既然GPU是成百上千只手一起干活,那么GPU的价格为什么不是CPU的成百上千倍呢?关键就在于GPU的“手”与CPU的“手”相比是带有明显残疾的,只有完成某些特定动作的时候效率高,完成其他动作效率就很低。具体表现在:

    (1)所有的“手”(或者叫处理器、线程)完成相同动作时效率高,完成不同动作时效率低——这一条是显卡编程最关键、最核心的部分,这决定了GPU虽然有几千只手,但不可能像工厂工人那样进行流水作业,你装填,我打包,他装箱,这对于GPU是行不通的。大家都一起打包,然后大家一起来装箱,只有这样的方式才适合让GPU来处理。    

    (2)如果各个并行的部分(即各个线程),需要共享大量数据,那么不适合用GPU进行处理。要注意,我说的是“不能共享大量数据”,这里并不是说GPU不适合处理大量数据,相反,由于GPU具有较大的显存空间(比较差的显卡也有2G显存)和非常快的数据吞吐速度(专业术语叫带宽),所以非常适合做大数据的处理。GPU编程的一个早期经典案例就是医学图像的处理,据说有个医生发明了一种彩超快速诊断子宫肌瘤的方法,但是如果用CPU处理几个T的彩超检查数据的话,几天都搞不定,后来改用GPU处理,几十分钟就解决了——所以处理大数据是GPU的强项。

    但这是指各个线程独立的读取一部分专属于自己的数据,那么处理的速度可以很高。如果大量的线程,要相互交错的同时访问大量数据那么运行效率就很低。打个比方:菜市场每一个摊位相当于一个要被访问的数据,逛菜市场的人相当于不同的线程,那么大家杂乱无章的在市场里乱逛,运行效率就很低。如果大家排好队进场,规定一个人只准面对一个摊位,那么运行效率就会很高。

    (3)并行处理的线程数不能太少。如果你的程序只能分解为几百个并行运算的部分,就不适合用GPU来处理——至少要有几千个并行的线程才能勉强体现出GPU的优势,如果你的程序撑死了也就分解为两三千个并行的部分,那么还是建议你不要考虑用GPU加速了——举个例子,我用GPU运行我的神经网络(我的显卡非常差,只有48个处理器),刚把程序运行通的时候,我安排了1024个线程进行测试,与我原来的CPU程序相比,速度只提高了20%左右,让我大失所望。后来发发狠,把并行的线程数安排到8192个——速度竟然提高到了原来的八倍左右——这让我欣喜若狂,这意味着如果我换更好的显卡,比如有两千多个处理器的显卡,那么我的程序速度还有四五十倍的提升空间,这样一来我的算法速度有望比在CPU的速度提高2-3个数量级,想想都让人兴奋。  

     需要说明一下,这个教程叫“菜鸟入门”,这里的“菜鸟”是指显卡编程方面的菜鸟,而不是指编程菜鸟。要学显卡编程,一定要对C/C++比较熟练,对指针的运用比较自如,才可能进行显卡编程——也可以说距离显卡编程就很近了,据说很久很久以前......显卡编程是一件非常麻烦的大工程,后来一种叫CUDA的东西横空出世——显卡厂商NVIDIA推出的显卡运算平台——显卡编程就变得非常简单了,只要在熟练C的前提下,学几个简单的语句就可以搞定。

    由于我是在windows上进行显卡编程的,我简单说一下我我在windows上安装CUDA遇到的一些问题(详细安装步骤请自行搜索相关文献,我这里只提一下文献中很少提及的需要注意的问题,以帮助各位少走弯路,至于使用Linux的同学,只能是自己查阅文献慢慢摸索了)。

    (一)需要先安装Visual Studio(其他C/C++的SDK似乎都不行),有的文献说可以用VC EXPRESS,但我安了VC EXPRESS,死活用不了,后来装了全套Visual Studio 才搞定。

    (二)安装好Visual Studio之后,到NVIDIA官网下载CUDA安装包,安装时务必选择“自定义安装”,务必勾选全部安装项目。

    (三)CUDA安装好后,可以搜索一个叫CUDA-Z的小软件,这个软件可以显示你的显卡的状态。下载运行后,如果告诉你显卡没有运行,很可能是你的显卡驱动太旧了——哪怕你是刚下载的最新的安装包,也可能出这个问题——你需要升级显卡驱动。另外我有个朋友遇到这样的问题:显卡没有运行,后来发现他是远程登陆,他到本地使用的时候,显卡就正常了——我分析是远程登陆后,显卡就休眠了。

    上面步骤完成后,就可以打开VS,新建一个CUDA工程,然后就可以开始第一个CUDA程序了:

     

    1. #include <cuda_runtime.h>
    2.  
    3. void main()
    4.  
    5. {printf("Hello world");
    6.  
    7. }

     

     http://blog.csdn.net/yfszzx/article/details/41654415

    慢着,这个程序和C有什么区别?用到显卡了吗?

    答:没有区别,没用显卡。如果你非要用显卡干点什么事情的话,可以改成这个样子:

    1. #include <cuda_runtime.h>
    2. __global__ void test()
    3.  
    4. {int i=0;}
    5.  
    6. void main()
    7.  
    8. {test<<<1,1>>>();
    9.  
    10. printf("Hello world");
    11.  
    12. }

    这样,我们就用显卡的一个线程,执行了一个int i=0语句。

  • 相关阅读:
    OnEraseBkgnd、OnPaint与画面重绘
    .编译ADO类DLL时报错的解决方案
    VC列表框样式
    Codeforces 131D. Subway 寻找环树的最短路径
    Codeforces 103B. Cthulhu 寻找奈亚子
    Codeforces 246D. Colorful Graph
    Codeforces 278C. Learning Languages 图的遍历
    Codeforces 217A. Ice Skating 搜索
    Codeforces 107A. Dorm Water Supply 搜图
    Codeforces 263 D. Cycle in Graph 环
  • 原文地址:https://www.cnblogs.com/carl2380/p/7122662.html
Copyright © 2011-2022 走看看