VideoCard 板


LINE

感谢大家的支持,这礼拜让我们来谈谈 CUDA 多执行绪的程式模型(SIMT),好让大家 对这个平行化的 C++ 有更清楚的轮廓。 ※ 第二章 SIMT 概观 ※ 所谓 SIMT (single instruction multi threads) 指的是单一指令对应多执行绪的 计算机架构,利用硬体的 thread 来隐藏 I/O 的延迟 (效果有点类似之前 Intel 的 hyper-threading,不过那不是 single instruction),nVidia 进一步地让这些执行绪 可由程式控制,用群组的方式让一堆执行绪执行相同的指令,并利用超多核心来强化它 (例如 8800 GTX 有 128 颗、GTX280 有 240 颗)。 简而言之,它是把超级电脑的平行架构,浓缩到单晶片中,所以产生这样的效能 (例如我实验室里的 kernel,在 GTX280上跑的效能是 Intel Q9300 的 30 多倍, 这测量的时间是实际跑完的时间,用 CPU 的高精度 timer 测量出来的,对照的是用 intel 自家的 compiler 进行 SSE3 最佳化过的)。 不过刚开始进入这多执行绪的模型,还真的有点不太习惯哩。 ◆ CUDA 的平行化程式设计模型 名词定义 网格(Grid) :包含数个区块的执行单元 区块(Block) :包含数个执行绪的执行单元 执行绪(Thread):最小的处理单元 (实际写程式的环境) CUDA 的平行化模型是将核心交由一组网格执行,再将网格切成数个区块,然後每个区块 再分成数个执行绪,依次分发进行平行运算,如果用军队来比喻,将核心视为连任务, 那网格就是连队,区块就是排或班,执行绪就是小兵。 任务(kernel) | | +--> 区块(排or班) +--> 执行绪(小兵) | | +--> 执行绪(小兵) | | +--> 执行绪(小兵) | | +--> 执行绪(小兵) | | +--> 网格(连队) +--> 区块(排or班) +--> 执行绪(小兵) | +--> 执行绪(小兵) | +--> 执行绪(小兵) | +--> 执行绪(小兵) | +--> 区块(排or班) +--> 执行绪(小兵) +--> 执行绪(小兵) +--> 执行绪(小兵) +--> 执行绪(小兵) (图一) kernel、网格、区块、执行绪和军队的类比 ◆ 内建变数 我们可以透过内建变数来辨识每个执行绪,让每个小兵弄清楚要执行那一部份的任务, 基本的内建变数如下,它们只可以使用在 kernel 的程式码中: uint3 gridDim :网格大小 (网格包含的区块数目) uint3 blockIdx :区块索引 (区块的ID) uint3 blockDim :区块大小 (每个区块包含的执行绪数目) uint3 threadIdx:执行绪索引 (执行绪的ID) 其中 uint3 为 3D 的正整数型态 struct uint3{ unsigned int x,y,z; }; 可以运用它来实做更高层次的平行运算结构,不过现阶段,先不要管这种复杂的结构, 把它当成单一正整数即可,也就是 y 和 z 都当成是 1,只用 uint3 的 x。 ps. 其实我平常在写的时候,也很少用到3D结构,因为我们的研究是4D或5D的 ~>_<~ 只好用1D载入kernel再自已去切。 ◆ 网格 & 区块大小 (gridDim, blockDim) CUDA 透过指定网格和区块的大小形成平行化的程式阵列,总执行绪数目为网格大小和 区块大小的乘积,而 gridDim, blockDim 这两个变数在 kernel 函式中为内建的唯读 变数,可直接读取 总执行绪数目 = 网格大小(gridDim) x 区块大小(blockDim) 例如下图为 (网格大小=3, 区块大小=4) 所形成的核心,它具有 12 个独立的执行绪 +-----------+-----------+--------------------+ | | | thread 0 (id 0) | | | +--------------------+ | | | thread 1 (id 1) | | | block 0 +--------------------+ | | | thread 2 (id 2) | | | +--------------------+ | | | thread 3 (id 3) | | +-----------+--------------------+ | | | thread 0 (id 4) | | | +--------------------+ | | | thread 1 (id 5) | | grid | block 1 +--------------------+ | (kernel) | | thread 2 (id 6) | | | +--------------------+ | | | thread 3 (id 7) | | +-----------+--------------------+ | | | thread 0 (id 8) | | | +--------------------+ | | | thread 1 (id 9) | | | block 2 +--------------------+ | | | thread 2 (id 10) | | | +--------------------+ | | | thread 3 (id 11) | +-----------+-----------+--------------------+ (图二) 网格、区块、执行绪 ID 的划分 ◆ 呼叫 kernel 的语法 在 CUDA 中呼叫 kernel 函式的语法和呼叫一般 C 函式并没什麽太大的差异, 只是多了延伸的语法来指定网格和区块大小而已: kernel_name <<<gridDim,blockDim>>> (arg1, arg2, ...); ^^^^^^^^^^^ ^^^^^ ^^^^^^ ^^^^^^^^^^^^^^^ 核心函式名 网格大小 区块大小 函式要传的引数(和C相同) 所以只是多了 <<<gridDim,blockDim>>> 指定大小而已 ^^y 其中 gridDim 和 blockDim 可以是固定数字或动态变数,例如 (1) 固定数字 ooxx_kernel<<<123,32>>>(result, in1, in2); (2) 动态变数 int grid = some_function_g(); //计算网格大小 int block = some_function_b(); //计算区块大小 ooxx_kernel<<<grid,block>>>(result, in1, in2); ◆ 区块 & 执行绪索引 (blockIdx, threadIdx) 我们可以用区块和执行绪索引来定出正在执行的程式位置,以决定该载入什麽样的资料, 而 blockIdx, threadIdx 这两个变数和 gridDim, blockDim 一样,在 kernel 中也是 内建的唯读变数,可直接读取 例如在(图二)中,我们要定出每一个小兵的唯一的 ID,可用下面这段程式码 int id = blockIdx.x*blockDim.x + threadIdx.x; 要产生(图二)配置的 kernel 呼叫为 kernel<<<3,4>>>(arguments); 其行为如下 (1) 传入的网格和区块大小为 1D 正整数,所以 uint3 中只有 x 有用到,其它 y=z=1 (2) 网格大小 gridDim.x = 3 (每个网格包含 3 个区块) (3) 区块大小 blockDim.x = 4 (每个区块包含 4 个执行绪) (4) 区块索引 blockIdx.x = 0,1,2 (每个 thread 看到的不一样) (5) 执行绪索引 threadIdx.x = 0,1,2,3 (每个 thread 看到的不一样) (6) 区块基底 blockIdx.x*blockDim.x = 0,4,8 (7) 区块基底加上执行绪索引 id = blockIdx.x*blockDim.x + threadIdx.x = 0,1,2,3, 4,5,6,7, 8,9,10,11 所以我们便可得到一个全域的索引,即每一个小兵的唯一的 ID (图二中的 id 栏)。 ◆ kernel 函式的语法 用 CUDA 写 kernel 函式写一般 C 函式也是没什麽太大的差异,只是多了延伸语法来 加入一些特殊功能,并且标明这个函式是 kernel 而已: __global__ void kernel_name(type1 arg1, type2 arg2, ...){ ...函式内容... }; 其中 (1) __global__ : 标明这是 kernel 的延伸语法 (2) void : kernel 传回值只能是 void (要传东西出来请透过引数) (3) kernel_name : 函式名称 (4) type1 arg1, type2 arg2, ... : 函式引数 (和 C 完全相同) (5) 函式内容 : 跟写 C 或 C++ 一样 (但不能够呼叫主机函式) (6) global 函式只能在 host 函式中呼叫,不能在其它 global 中呼叫。 ◆ 小结 以上是 CUDA 平行化程式设计的概观,和传统 C/C++ 的差异便是它这种的 SIMT 结构, 也许你会觉得奇怪,为什麽要分成两层的 grid/block 结构,直接一层就配多个 thread 不是更简单,这牵涉到它硬体上的细节以及成本问题(後面章节会解释),再者单层结构 不见得有效率,会增加同步化时执行绪等待的问题,使用两层结构,可以使 block 单元 弹性的选择同时或者循序执行,增加往後硬体发展和软体重用的弹性。 ※ 後续章节 ※ CUDA 安装 简易 kernel 范例 CUDA 的记忆体分类 CUDA 的函式种类 CUDA API介绍 GPGPU 的硬体介绍 (顺序还在研究中... >_<) ※ 名词解释 ※ (1)SIMT(single instruction multi threads):单一指令对应多执行绪的架构。 (2)网格 (Grid) :包含数个区块的执行单元。 (3)区块 (Block) :包含数个执行绪的执行单元。 (4)执行绪(Thread):最小的处理单元 (实际写程式的环境)。 (5)核心 (Kernal):并非执行单元,比较像是要执行某种任务的抽象归类。 (6)网格大小(gridDim, grid dimension):网格包含的区块数目。 (7)区块大小(blockDim, block dimension):区块包含的执行绪数目。 (8)区块索引(blockIdx, block index) :区块在网格中的位置。 (9)执行绪索引(threadIdx, thread index):执行绪在区块中的位置。 (10)唯读变数(read-only variable):只可读取,不可写入的变数。 (11)延伸语法(extension):在标准C/C++语法之外,外加的功能性语法。 (12)函式引数(arguments):函式呼叫时传递的变数。 (13)基底(base) :计算位址时的基准点,就像座标的原点一样。 (14)索引(index):位址相对於基准点的偏移。 (15)同步化(synchronize):使多执行单元的进度在某点上对齐(先到的要等待还没到的, 等全部到齐後才继续前进),通常是为了交换共用资料,避免读写顺序错乱导致的 资料错误。 --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 114.45.208.87
1F:推 levine21:先抢头推再来看!! 10/02 01:27
2F:推 Luciferspear:虽然我看不懂还是推认真分享文 10/02 01:30
3F:推 CDavid:推 10/02 01:30
※ 编辑: a5000ml 来自: 114.45.208.87 (10/02 02:06)
4F:推 l23456:快推...不然别人以为我看不懂... 10/02 02:21
5F:推 nanie:真的是做研究才有机会用到 XDD 大学的话 几乎没机会用到 10/02 03:05
6F:推 lavatar:推一下... 10/02 09:31
7F:推 yayax:推推~看了颇久,真用心 10/02 09:53
8F:推 b24333666:专业推 10/02 10:33
9F:推 brighton16:大推心得分享文 10/02 10:59
10F:→ b24333666:如果有大学做出来就有一台超级电脑了XDD 10/02 11:08
11F:推 b24333666:sdk:另外要cuda在windows上有5秒的限制 建议用linux会 10/02 11:10
12F:→ b24333666:比较好 有5秒限制是啥意思? 10/02 11:11
13F:推 sdk:windows/xwinow每5秒watchdog会check显卡有没有死掉..如果这5 10/02 12:14
14F:→ sdk:秒内你的程式一直在跑..他会判定GPU挂了而reset GPU... 10/02 12:15
15F:→ sdk:windows上不能把window manager关掉..但linux上可以XD 10/02 12:15
16F:→ sdk:其实不管是N社还是A社就是想搞HPC on desktop啊... 10/02 12:16
17F:→ sdk:另外补充一下不管grid/block...基本单元就是thread..在GPU上 10/02 12:17
18F:→ sdk:他们使用massive threaded architecture..也就是说一次可以执 10/02 12:18
19F:→ sdk:行上万个thread...才是最有效率的...(既使只有240个core..但是 10/02 12:18
20F:→ sdk:GPU上的context switch overhead几乎是0..)..这样的设计是为了 10/02 12:19
21F:→ sdk:hide global memory access latency.. 10/02 12:19
22F:→ sdk:(早知道就回文了...= =) 10/02 12:20
23F:推 finalhaven:可以用这个做电路的Place&Route的EDA TOOL吗? 10/02 13:14
24F:推 sdk:回页上..应该ok..只是国外已经有start-up在做这个了XD 10/02 13:25
25F:→ sdk:另外我也做过floorplan的部份..虽然只optimize area... 10/02 13:26
26F:推 VictorTom:推文一起推:) 10/02 15:58
27F:推 powertodream:推!!!!! 10/02 16:18
28F:推 markfang:推 专业文 受教 10/03 11:23
29F:推 airwin:原PO真强者阿 10/03 12:42
30F:推 amd3dnow:从网路上看到cuda执行以warp为单位,那warp指的是?? 10/03 22:05
31F:推 netsphere:要是有范例会更好 : ) 10/04 11:09
32F:→ a5000ml:warp 之後会介绍哦, 它和硬体组成有关, 是 32 threads 10/04 11:50
33F:→ a5000ml:并起来执行的单位, 用 8 个执行单元管线以 4 个周期执行 10/04 11:52
34F:→ a5000ml:所以达成平均 1 个周期 1 个指令的效果 10/04 11:53
35F:→ a5000ml:至於范例後面就会有, 因为现在只是刚开始而己, 介绍的 10/04 11:55
36F:→ a5000ml:比较倾向於概念部份, 等写完安装部份後, 开始进入 10/04 11:57
37F:→ a5000ml:写程式的正题, 就会有很多范例 =^.^= 10/04 11:58
AE2001:转录至看板 NTUT_MMRE86 10/05 01:05 a5000ml:转录至看板 C_and_CPP 10/15 20:59 uf2000uf:转录至某隐形看板 10/16 21:48







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:WOW站内搜寻

TOP