zoukankan      html  css  js  c++  java
  • cuda计算的分块

    gpu的架构分为streaming multiprocessors

    每个streaming multiprocessors(SM)又能分步骤执行很多threads,单个SM内部能同时执行的threads叫做warp。一个warp能同时操作16个单精度浮点数/8个双精度(tesla),或者32个单精度浮点数/16个双精度浮点数(feimi)。

    单个SM内部有local memory和16kb大小的share memory,后者是在做计算的时候要尽量利用好的东西。

    根据gpu的架构,做cuda计算的时候基本上是这么一个流程

    先把目标矩阵分块,8*8或者16*16等,具体多大要看所用gpu的配置

    分块完以后,gpu会把每个块调度到每个SM上去执行。SM执行的时候按照warp大小起线程,直到运算完成。

    资源限制:

    每个GPU必须有16个以上的block(对应16个SM)。而每个SM最多只能有8个block(对应8个flag位)。

    算法举例

    拿矩阵乘法C=A*B举例,

    在不使用share memory的时候,每计算C中的一个值就需要2*N*N的数值。所以不使用BLOCK算法的时候,一个N*N的矩阵算一次就需要读2*N^4的数据,起了N^2的threads。每次要读2*N的数,这个操作数就是2N。带宽显然不够。这是非常慢的。在使用share memory的时候,每计算BLOCK_SIZE*BLOCK_SIZE中的值就需要读2*BLOCK_SIZE*BLOCK_SIZE的数据,当BLOCK_SIZE是16的时候,那就是2k,16kb的share memory能允许8个block。

    当BLOCK_SIZE是32的时候,大小是8k,就是2个block。

    那回顾一下刚才的数据,我们能知道,大小是32*32的block在16kbshare memory的时候对SM的利用率不高,(只能放2个block),而大小是16*16的block在16kb sharememory的时候对SM的利用率高(到了8个block,到顶了)。

    为什么不用2个block而是8个block呢?

    因为在从local memory读到share memory的是要时间的,gpu可以在这一个warp读取share memory的时候切换到别的warp 让他们也读share memory。还记得吗?一个warp是16个线程,SM能同时保存8个BLOCK的状态。对于32*32这个大小的block,对于SM的调度没有利用好,所有线程全都卡在读取内存上了。

    对于16*16的block,每次要读2*256=512个数,这256个数的操作是256*16*2=8192个浮点操作。这时带宽就足够了。

    对于feimi架构来说,share memory翻了3倍成了48kb

    BLOCK_SIZE等于16的时候,就是24个block,BLOCK_SIZE=32的时候就是6个block。gpu读取share memory大概要20个cycle。一个32*32的block有1024个线程,一个warp 32个线程。这样就至少32个cycle过去了,足够前面的线程读完。

    而对于BLOCK_SIZE等于16的时候,24个block对于一个SM来说太多了(同时只能调度8个).

    ps:

    在调试矩阵乘法的时候掉进坑里了……给每个矩阵赋值10.0*i+j,两个矩阵互相乘。当矩阵比较小的时候100*100及以下,一点问题都没有。大到1000*1000的开始出现计算错误。找了大半天都没找出个所以然来。突然发现结果比较长,一数位数,都快7-8位了,原来是过了单精度浮点数的有效位数了。

  • 相关阅读:
    一些点子的梳理
    网络安全解决方案
    流量劫持技术
    运营商DNS系统安全解决方案
    安卓工作室 设置每次启动 选择项目,不直接打开项目
    多臂机测试, AB测试
    vue 入门
    web开发 入门
    C# .NET 使用第三方类库DotNetZip解压/压缩Zip文件
    Linq 101 工具和源码
  • 原文地址:https://www.cnblogs.com/sickboy/p/4390056.html
Copyright © 2011-2022 走看看