OpenHero 开勇

Open heart, bravely fly!

赵开勇ID:OpenHero
210239次访问,排名301好友95人,关注者104
OpenHero的文章
原创 234 篇
翻译 2 篇
转载 51 篇
评论 386 篇
OpenHero 开勇的公告
最近评论
OpenHero:就是在计算thread在全局的位置的时候:unsigned int index = xIndex(6) + size_x * yIndex(5); 这里的size_x就是一行一共有多少个士兵(Thread),例如上图,这里一行有3个block每一个block里面的每一行有5个Thread,所以size_x就应该为3×5=15,一个Grid的一行有15个士兵,那刚才叫道的那个人的线性编号就应该……
李求斌:不要气馁,加油
wgbljl:加-keep选项生成.cubin文件,这个文件里有
kclau:你好,
我想請問以下,如何知道每一個thread用多少registers呢?
Gemin:呵呵 支持开勇
文章分类
收藏
    相册
    相册
    自己
    参与的开源项目
    Scilab Robotics Toolbox
    常去的几个地方
    Robocup 机器人足球官方站点
    RTSJ
    感兴趣的开源项目
    Flash得开源代码
    Robocup server
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 CUDA硬件实现分析(一)------安营扎寨-----GPU的革命收藏

    新一篇: 《一个人的奥林匹克》 | 旧一篇: Monday, April,27,2008 心情日记

    CUDA硬件实现分析(一)------安营扎寨

    ------GPU的革命

    序言:有个不会写计算机程序的朋友看了blog,问我,这个GPU也能当故事写吗?我觉得或许GPU真的算是一场革命吧,他的发展或许在酝酿中,不过到08年底,09年初,一定会有一场轰轰烈烈的竞争。那个时候或许从OS层面都会给人带来震撼。如果把CPU的多core看成由几个特种兵组成的,每个特种兵都手里面都拿着8杆枪(SSE)。那么GPU可以看成农民起义……一上来就是成百上千的人,虽然单兵作战能力比不上CPU的单个core,但是毕竟人数众多。就现在GPU的性能,在并行运算上如果不考虑double硬件的成本,已经早早超过CPU的并行运算能力。这或许就是一场革命,这次革命不知是简简单单的GPUCPU的转变,而是并行算法和串行算法的竞争。并行算法虽然研究到现在已经有很多年,但是真正的实际运用,离我们普通大众还是差很远。但是GPU,并行计算的出现,一下子把我们和并行计算的距离拉近了好多。现在在学校里面学习计算机的时候都是从串行算法开始,养成了很多固定的串行思维。当遇到问题并行划分的时候,就还带着串行的思想,那就不好了:)

    正文:前面我们已经说到线程的一些概念,但是这些概念都是软环节的。我们常常会听到某某单位说他们的软硬件配置如何如何的好。软件再好,每个士兵都是可造之才,但是如果硬件条件跟不上,也没他们的勇武之地。就像国内做过一些跳槽原因的统计,很多人已经跳槽都是为了高工资,但实际统计结果表明,很多人都觉得在以前那个公司里面学不到东西,或者说得不到发挥自己长处的地方。那就得看公司有没有这样的机会让你发挥你的能力了。看到这里,扯远了~很多人都看得不耐烦了……书接上回 CUDA 线程执行模型分析(二)大军未动粮草先行------GPU的革命。已经讲到CUDA在线程模型是一个什么样子,经过几天的吸收,也应该在脑子里面有一些印象了。但是你会问一个问题,我们是不是可以开无数个线程来执行啦?或许招兵的人都想找到很多很多的人,但是你得也考虑一下你的粮食有多少,军营有多大。在这么我们得讨论一下现在的支持CUDAnvidia的显卡现在的硬件情况。

    空洞的讲解或许还是没怎么又说服力,下面以G80为例子。
    1. G80
    里面有16Multiprocessor.
    2.
    每个Multiprocessor都有一组(G80里面是8个)32位的Processor(每个Processor都是SIMD架构,什么叫SIMD架构:军训的时候,大家都到了食堂,不是像在学校里面,每个人那自己的碗筷就三三俩俩的去吃饭,那可要讲究纪律,啥叫纪律,一群人站在桌子面前,连长没发话,谁也不敢坐下来……连长一声令下:“坐下”。所有的人才按照敢坐下来,也是同时坐下来- -!要是谁没有同步坐下来,那就惨了- -!再来一次,一定要是同步坐下去的,都能听到声的,咵!恨不得把板凳给坐碎了------还是部队的东西结实,兄弟们怎么坐到军训结束只有坐坏屁股的,没有听说凳子坐坏的- -!所以啊,爱惜公物就是爱惜自己。记住了吧,这就是SIMDSingle Instruction Multiple Data )还有共用的Instruction Unit(这玩儿就不用翻译是啥了吧~看SIMD,自己理解去)。在G80里面有两个SFU模块。
    3.
    每一个时钟周期内,按照warp(这玩儿咋翻译啦?就理解为运行的时候,一个block里面一起运行的thread,例如block里面有512thread,但是每次只有32thread在运行,那么这32thread就是一个运行的warp- -! 还好不是rap- -!俺就真没法解释了)
    4.
    每一个warp里面包含的thread数量是有限的,现在的规定是32个。将来不知道会不会有变化?不知道,这个只有CUDA开发人员知道了。

    我们还是按照我们的既定方式学习吧~看图说话- -!接下来又是一张图:
    刚才我们已经说到了硬件上的处理器的模型,现在我们来看看内存吧。前面的章节我们已经讲到了内存的registerlocalsharedconstanttextureglobal,现在看到对应的硬件的位置了吧?哦,对了,有人会问,localglobal跑那里去了,你看看,是不是多了一个Device Memory嘛。LocalGlobal 都是在Device Memory上的。只是在线程模型运行的时候,为了方便说明线程的模型,把它单独划分出来好说明。其实ConstantTexture都是在Device Memory里面的,但是人家是只读的Cache,所以比Globallocal要快一些。不过Cacheshared Memory比起来,又显得慢一些了。

    硬件的架构差不多就是这么多。如果还不是很清楚,我们再讲讲军营的生活。还是讲吃食堂吃饭吧(回想起大学的时候和几个好朋友一起成立了一个编程爱好者协会……结果后来变成了好吃协会- -!)。由于我们现在的连队人数众多,一个grid里面就可以有65535thread,所以一下子让这么多人一起吃饭,是不可能的。我们有好多个grid怎么办?所以每次Device(就是显卡)只处理一个grid。但是每个grid里面又有那么多人。一来是咱们地方小,不能容纳那么多人一起吃饭,而来是也没必要再建立那么多食堂。大家可以轮流吃,早吃的早走,晚来的也晚不了多久。

    这次是Grid1先到达食堂,然后他把士兵分成了几个block,(我们上次已经讲过的,blockgrid的关系,应该还记得把)但是现在桌子还是少,为了大家不乱起来,每个block的人就指定到某一个multiprocessor(一个周期只能容纳32个人一起用餐)哪里。

    这个block1的人就围着multiprocessor1这张桌子坐,但是这张桌子也不是太大,所以block里面的人又分成32个人一组(warp)来吃饭。那如果这个block没有32个人,就占不完这张桌子,所以一个multiprocessor又可以让别的blockthread一起来用餐。

    因为一次就把所有的registershared memory分配给了所有的block的所有的thread。所以怎么样合理的少用registershared memory就可以同时让更多的thread得到处理。

    讲了这么多,怎么来看自己的显卡那片军营如何拉?下面给出两种方法,一种是用一个小软件,GPU-Z的工具,这个工具可以得到很多显卡的参数,这个可以上网搜索到。

    第二种方法是用CUDA的命令,这个只是针对支持CUDA的显卡的,下面给一段代码:

    /********************************************************************

    *  InitCUDA.cu

    *  This is a init CUDA of the CUDA program.

    *********************************************************************/

    #include <stdio.h>

    #include <stdlib.h>

    #include <cuda_runtime.h>

     

    /************************************************************************/

    /* Init CUDA                                                            */

    /************************************************************************/

    bool InitCUDA(void)

    {

      int count = 0;

      int i = 0;

     

      cudaGetDeviceCount(&count);

      if(count == 0) {

            fprintf(stderr, "There is no device.\n");

            return false;

      }

     

      for(i = 0; i < count; i++) {

            cudaDeviceProp prop;

            if(cudaGetDeviceProperties(&prop, i) == cudaSuccess)

            {                

                  printf("name:%s\n",                                         prop.name);

                  printf("totalGlobalMem:%u\n",                   prop.totalGlobalMem);

                  printf("sharedMemPerBlock:%u\n",                prop.sharedMemPerBlock);

                  printf("regsPerBlock:%d\n",                           prop.regsPerBlock);

                  printf("warpSize:%d\n",                               prop.warpSize);

                  printf("memPitch:%u\n",                               prop.memPitch);

                  printf("maxThreadsPerBlock:%d\n",               prop.maxThreadsPerBlock);

                  printf("maxThreadsDim:x %d, y %d, z %d\n",      prop.maxThreadsDim[0],prop.maxThreadsDim[1],prop.maxThreadsDim[2]);

                  printf("maxGridSize:x %d, y %d, z %d\n",      prop.maxGridSize[0],prop.maxGridSize[0],prop.maxGridSize[0]);

                  printf("totalConstMem:%u\n",                    prop.totalConstMem);

                  printf("major:%d\n",                                  prop.major);

                  printf("minor:%d\n",                                  prop.minor);

                  printf("clockRate:%d\n",                              prop.clockRate);

                  printf("textureAlignment:%u\n",                       prop.textureAlignment);

     

                  if(prop.major >= 1) {

                        break;

                  }

     

            }

      }

      if(i == count) {

            fprintf(stderr, "There is no device supporting CUDA 1.x.\n");

            return false;

      }

      cudaSetDevice(i);

           

      printf("CUDA initialized.\n");

      return true;

    }

    发表于 @ 2008年04月30日 15:33:00|评论(loading...)|编辑

    新一篇: 《一个人的奥林匹克》 | 旧一篇: Monday, April,27,2008 心情日记

    评论

    #huzhongyi1985 发表于2008-04-30 16:15:29  IP: 218.104.96.*
    勇哥!辛苦啦!
    比喻的很形象!我是思绪飞扬!呵呵!
    我在看指南中有些代码,看的不是很明白!好象和c语言有点不一样,请勇哥以后有时间给我们讲讲!谢谢啦!
    #huzhongyi1985 发表于2008-04-30 16:15:58  IP: 218.104.96.*
    勇哥!辛苦啦!
    比喻的很形象!我是思绪飞扬!呵呵!
    我在看指南中有些代码,看的不是很明白!好象和c语言有点不一样,请勇哥以后有时间给我们讲讲!谢谢啦!
    #utada776 发表于2008-05-01 21:44:35  IP: 221.221.181.*
    支持
    #yao1ying 发表于2008-07-01 10:25:30  IP: 221.224.163.*
    支持,比编程手册形象多了。
    2008-07-01 12:14:51作者回复
    谢谢
    #jun 发表于2008-07-07 14:55:41  IP: 123.112.81.*
    support
    #kclau 发表于2008-07-16 16:32:22  IP: 210.177.238.*
    你好,
    我想請問以下,如何知道每一個thread用多少registers呢?
    2008-07-16 19:21:12作者回复
    和c语言的一样~
    #wgbljl 发表于2008-07-22 12:59:53  IP: 172.26.10.*
    加-keep选项生成.cubin文件,这个文件里有
    2008-07-22 19:28:58作者回复
    可以看看doc里面的ptx的结构,然后在ptx层面进行优化
    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © OpenHero 开勇