cuda中如何选择block尺寸

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cuda中如何选择block尺寸相关的知识,希望对你有一定的参考价值。

参考技术A 64*16=1024
个线程,此时
SM
上还有
1024
个线程空闲,显然这种设置
无法有效利用
GPU


l

如果设置
block
尺寸为
16*16=256

根据
Threads Per Multiprocessor
的限
制每个
SM
可容纳
2048/256=8

block
,小于
Thread
Blocks
Per
Multiprocessor
的限制;此时
SM
每次运行
8

block

2048
个线程,
能够占满整个
SM


l

如果设置
block
尺寸为
32*32=1024
,根据
Threads Per Multiprocessor

限制每个
SM
可运行
2048/1024=2

block
,小于
Thread
Blocks
Per
Multiprocessor
的限制;此时
SM
每次运行
2

block

2048
个线程,
能够占满整个
SM


注意事项
A
:根据
Max Thread Block Size
的限制,
block
中线程个数上限为
1024


注意事项
B


CUDA
中,
线程调度单位称作
Warp

根据
Threads Per Warp
这个规格,每次以
32
个线程为单位进行调度,因此
Block
中的
Thread
数目应当

32
的倍数。

注意事项
C

Block
如果是多维的,每个维度也都有大小限制,图
5
中的
Threads
Dimensions







Block
Dimension
Limit





1024*1024*64
,也就是
Block
的第一维不能超过
1024
,第二维不能超过
1024

第三位不能超过
64


综上所述,我们的初步设计结果是:在无需考虑向下兼容的情况下,对
GTX650
显卡将
block
尺寸设置为
32*32=1024
应该是比较恰当的(哦,忘了说,
我主要用
CUDA
做图像处理,因此
block
尺寸都习惯设为二维)


2.

SM
资源对
Block
尺寸设计的影响

制约
block
尺寸分配的还有其他资源的限制,例如
shared
memory

register
等。在每一个
SM
上这些资源都是有限的,如果所有线程要求的资源总和过多,
CUDA
只能通过强制减少
Block
数来保证资源供应。

顺便提一下,
Shared Memory

Register
都位于
GPU
片上(相对的,
Global
Memory

Local Memory
位于显存)

速度超快的,
想要
CUDA
程序跑得快,

Shared Memory

Register
的细心设计是必不可少的。

2.1

Register

Block
尺寸设计的影响

根据
Register File Size
的限制(
CUDA-Z
描述为
Regs Per Block
,不准确,
应该是
Regs Per Multiprocessor

,每个
SM
上只能供应
65536

Register


根据
Max Registers Per Thread
的限制,
每个线程不能使用超过
63

Register


计算示例:

l

假设
Block
尺寸设计为
32*32=1024

每个
Thread
需要使用
32

Register

则一个
SM
上能承担的
Thread
数量为
65536/32=2048
,刚好可以满足需
求。

l

Block
尺寸同上,每个
Thread
需要使用
33

Register
,则一个
SM
上能
承担的
Thread
数量为
65536/33

1985.94
。但是,前面说过,如果请求
资源过多,
CUDA
将会通过强制减少
Block

(而不是
Thread
数)
来保
证资源供应。本示例中的情况可以满足
1

Block

1024

Thread
)的
需求,不能满足
2

Block

2048

Thread
)的需求,因此实际只有
1

Block

1024
个线程在运行。和上个示例相对比,因为多请求了
1

Register
,就灭掉了其他
1024

Thread
的生存机会,不划算啊。

2.2

Shared Memory

Block
尺寸设计的影响


2.1
基本类似。

根据
Max
Shared
Memory
Per
Multiprocessor
的限制,每个
SM
上只能供应
49152 Byte

Shared Memory


首先需要明确一点:
Shared Memory
是分配给
Block
而不是
Thread
的,
被每

Block
内的所有
Thread
共享(所以才叫做
”Shared”


Block
中的
Thread
能够
合作运行也是基于这一点。

计算示例:

l

假设每个
Block
使用了
20000 Byte

Shared Memory
,则一个
SM
上能
承担的
Block
数量为
49152/20000=2.4576
,可以满足需求。

l

假设每个
Block
使用了
30000 Byte

Shared Memory
,则一个
SM
上能
承担的
Block
数量为
49152/30000=1.6384
。本示例中的情况只能满足
1

Block
的需求,因此实际只有
1

Block
在运行。如果这里
Block

尺寸为
32*32=1024
,则
SM
中另外
1024
个线程容量都被浪费了。

2.3

占用率计算器的使用

上面的计算乍一看比较复杂,所幸
nVidia
已经提供了一个很好的计算工具,
这就是刚才提到
CUDA_Occupancy_Calculator.xls
,如图
8
所示。

这个工具的使用非常简单,
只要遵循
3
个步骤即可。
1)

2)
是需要用户使用
下拉菜单进行选择的项目,
3)
是占用率计算结果。下面我们分别进行介绍。

1.)
是选择
GPU
的计算能力,
前面说过可以使用
CUDA-Z
软件查询,
GTX650
显卡选择
3.0


1.b)
在表
1
中已经给出了,数值为
49152


2.)
中的
Threads Per Block
就设为前面计算得到的
32*32=1024


那么一个程序使用的
Register

Shared Memory
如何得到呢?这时可以使用
--ptxas-options=-v
编译指令。

S
U
M
E

C
O
L
L
E
C
T
I
O
N


8 CUDA GPU
占用率计算器


VS2008
中可以如下操作:

a.

打开
Project
属性;


9

b.

将属性中
CUDA
Runtime
API\GPU
中的
Verbose
PTXAS
Output
设置为
Yes



10

c.

重新编译程序后,即可在
Output
窗口中看到类似下面的信息

ptxas info

: Compiling entry function '_Z8my_kernelPf' for 'sm_10'
ptxas info

: Used 5 registers, 8+16 bytes smem
可以看出本程序使用了
5

Register

8+16

Byte

Shared Memory

但是如果程序在运行时还定义了
2048 Byte

external shared memory array

则总的
Shared
Memory
占用应当是
2048+8+16=2072
。将
Register

Shared
Memory
信息填入图
5
中的
2.)
后即可看到计算器的计算结果,
如图
11
所示。


11

3.)
中显示的就是资源占用情况,可见
SM
的占用率是
100%
,没有计算能力
被浪费,说明这种配置是合理的。

S
U
M
E

C
O
L
L
E
C
T
I
O
N

至此,
Block
尺寸的设计基本完成。

3.

Block
尺寸的合理性

资源(
Register

Shared Memory
)是稀缺的,一定要分配给最重要的语句。
虽然
Thread
越多就越能隐藏访问延迟,但同时每个
Thread
能够使用的资源也就
相对减少了,如何在这两者之间找到平衡,只有程序实际运行时才能得到检验。
现实和理论总是有差别,
但如果能够把握基本的原理,
肯定不会在通往最终目标
的路上偏离太多。

新行上第一个和最后一个 inline-block 元素的选择器

【中文标题】新行上第一个和最后一个 inline-block 元素的选择器【英文标题】:Selector for the first and last inline-block element on a new line 【发布时间】:2015-02-16 19:12:41 【问题描述】:

我正在尝试使用动态元素构建导航,这些元素可能会在小屏幕尺寸下分成两行,我希望能够为每行的第一个和最后一个元素设置样式。

这里有一些在小屏幕尺寸下会中断的示例 scss(圆角应该在每行的第一个和最后一个元素上):

<ul>
    <li>First page</li>
    <li>Second page</li>
    <li>Third page</li>
    <li>Fourth page</li>
    <li>Another example page</li>
    <li>This could be the last page</li>
    <li>But its not</li>
    <li>This is actually the last page</li> 
</ul>

ul 
    list-style:none;
    font-size:0px;
    li 
        font-size:18px;
        display:inline-block;
        padding:10px 30px;
        border:1px solid black;
        margin:10px -1px 10px 0;
        &:first-child 
            border-top-left-radius:5px;
            border-bottom-left-radius:5px;
        
        &:last-child 
            border-top-right-radius:5px;
            border-bottom-right-radius:5px;
        
            

与相关jsfiddle:http://jsfiddle.net/tbw4f23g/1/

是否可以为运行到新行的第一个和最后一个 inline-block 元素获取选择器,或者是否有任何其他(非 JavaScript)方法可以实现此效果?

【问题讨论】:

为什么不能使用您提供的示例? 您能否包含您的 HTML 以便人们可以看到您的语法?谢谢:) @AdityaPonkshe 因为:first-child:last-child 指的是DOM 中的位置,而不是行上的位置。 @torazaburo 不好意思,我没听懂这个问题。 【参考方案1】:

没有纯 CSS 的方法。我添加了the JavaScript solution in your fiddle。

作为一种解决方法,您可以为列表项分配固定的百分比宽度,并使用 CSS 媒体查询根据屏幕大小增加/减少宽度。通过这种方式,您将准确地知道一行中有多少项目,这反过来又允许您设置特定元素的样式。 SASS 可以使编写重复的 CSS 变得更容易。粗略的轮廓(打开整页并调整浏览器大小):

ul 
  margin: 0;
  padding: 0;
  list-style-type: none;

li 
  float: left;
  box-sizing: border-box;
  margin-bottom: .5em;
  border: thin solid #EEE;
  padding: 1em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  background-color: #CEF;

li:first-child 
  border-top-left-radius: 1em;
  border-bottom-left-radius: 1em;

li:last-child 
  border-top-right-radius: 1em;
  border-bottom-right-radius: 1em;

@media (min-width: 600px) and (max-width: 799px) 
  /* 4 items per row */
  li 
    width: 25%;
  
  /* match 4, 8, 12, ...*/
  li:nth-child(4n+4) 
    border-top-right-radius: 1em;
    border-bottom-right-radius: 1em;
  
  /* match 5, 9, 13, ... */
  li:nth-child(4n+5) 
    border-top-left-radius: 1em;
    border-bottom-left-radius: 1em;
  

@media (max-width: 599px) 
  /* 3 items per row */
  li 
    width: 33.3333%;
  
  /* match 3, 6, 9, ... */
  li:nth-child(3n+3) 
    border-top-right-radius: 1em;
    border-bottom-right-radius: 1em;
  
  /* match 4, 7, 10, ... */
  li:nth-child(3n+4) 
    border-top-left-radius: 1em;
    border-bottom-left-radius: 1em;
  
<ul>
  <li>Praesent ultricies libero</li>
  <li>Aenean in velit vel</li>
  <li>Ut consequat odio</li>
  <li>Integer convallis sapien</li>
  <li>Fusce placerat augue</li>
  <li>Vestibulum finibus nunc</li>
  <li>Nulla consectetur mi</li>
  <li>Ut sollicitudin metus</li>
  <li>Maecenas quis nisl sit</li>
  <li>Vivamus eleifend justo</li>
  <li>Duis ut libero pharetra</li>
</ul>

【讨论】:

今天(2017 年)有办法吗?【参考方案2】:

是否可以为运行到新行的第一个和最后一个 inline-block 元素获取选择器,或者是否有任何其他(非 JavaScript)方法可以实现此效果?

不,没有这样的选择器。 CSS 无法访问有关换行位置的信息(:first-line 伪元素除外)。不,没有其他非 JavaScript 方法可以实现这种效果。

如果你愿意使用 JS,你可以在布局可能发生变化时对元素进行迭代,检查每个元素相对于其父容器的位置,判断它是靠左还是靠右,然后应用您的边界半径。

另一种可能的 JS 解决方案是通过累积宽度并找出必须发生中断的位置来执行您自己的换行计算。

您可能需要检查诸如 Masonry 之类的库,看看它们是否提供允许您访问内部布局配置的钩子,这可以使这更容易。

【讨论】:

以上是关于cuda中如何选择block尺寸的主要内容,如果未能解决你的问题,请参考以下文章

CUDA:关于活动扭曲(活动块)以及如何选择块大小的问题

如何选择指定的GPU来运行CUDA程序?

如何设置CUDA Kernel中的grid_size和block_size?

CUDA编程之线程模型

如何在OpenGL中自动选择屏幕尺寸

按位置选择的CUDA GPU,但如何将默认设置为设备0以外的东西?