为啥允许我运行块数超过 GPU 的 CUDA 核心数的 CUDA 内核?
Posted
技术标签:
【中文标题】为啥允许我运行块数超过 GPU 的 CUDA 核心数的 CUDA 内核?【英文标题】:Why am I allowed to run a CUDA kernel with more blocks than my GPU's CUDA core count?为什么允许我运行块数超过 GPU 的 CUDA 核心数的 CUDA 内核? 【发布时间】:2016-01-16 20:28:35 【问题描述】:评论/注释
线程块是否可以超过 CUDA 内核的最大数量? 经纱尺寸与我正在做什么有什么关系?开始
我正在使用以下代码运行一个 cuda 程序来启动 cuda 内核:
cuda_kernel_func<<<960, 1>>> (... arguments ...)
我认为这将是我被允许做的事情的限制,因为我的笔记本电脑上有一个 GTX670MX 图形处理器,根据 Nvidia 的网站,它有 960 个 CUDA 内核。
所以我尝试将960
更改为961
,假设程序会崩溃。它没有……
这是怎么回事?
这是deviceQuery
的输出:
./deviceQuery Starting...
CUDA Device Query (Runtime API) version (CUDART static linking)
Detected 1 CUDA Capable device(s)
Device 0: "GeForce GTX 670MX"
CUDA Driver Version / Runtime Version 7.5 / 7.5
CUDA Capability Major/Minor version number: 3.0
Total amount of global memory: 3072 MBytes (3221028864 bytes)
( 5) Multiprocessors, (192) CUDA Cores/MP: 960 CUDA Cores
GPU Max Clock rate: 601 MHz (0.60 GHz)
Memory Clock rate: 1400 Mhz
Memory Bus Width: 192-bit
L2 Cache Size: 393216 bytes
Maximum Texture Dimension Size (x,y,z) 1D=(65536), 2D=(65536, 65536), 3D=(4096, 4096, 4096)
Maximum Layered 1D Texture Size, (num) layers 1D=(16384), 2048 layers
Maximum Layered 2D Texture Size, (num) layers 2D=(16384, 16384), 2048 layers
Total amount of constant memory: 65536 bytes
Total amount of shared memory per block: 49152 bytes
Total number of registers available per block: 65536
Warp size: 32
Maximum number of threads per multiprocessor: 2048
Maximum number of threads per block: 1024
Max dimension size of a thread block (x,y,z): (1024, 1024, 64)
Max dimension size of a grid size (x,y,z): (2147483647, 65535, 65535)
Maximum memory pitch: 2147483647 bytes
Texture alignment: 512 bytes
Concurrent copy and kernel execution: Yes with 1 copy engine(s)
Run time limit on kernels: Yes
Integrated GPU sharing Host Memory: No
Support host page-locked memory mapping: Yes
Alignment requirement for Surfaces: Yes
Device has ECC support: Disabled
Device supports Unified Addressing (UVA): Yes
Device PCI Domain ID / Bus ID / location ID: 0 / 1 / 0
Compute Mode:
< Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) >
deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 7.5, CUDA Runtime Version = 7.5, NumDevs = 1, Device0 = GeForce GTX 670MX
Result = PASS
我不知道如何解释这些信息。这里说“960 个 CUDA 内核”,然后是“每个多处理器 2048 个线程”和“每个块 1024 个线程”。
我对这些东西的含义有些困惑,因此 cuda_kernel_func>> 参数的局限性是什么。 (以及如何让我的设备发挥最大性能。)
我想您也可以将此问题解释为“关于我的设备的所有统计信息是什么意思”。例如,CUDA 核心/线程/多处理器/纹理维度大小究竟是多少?
【问题讨论】:
阅读 CUDA 编程指南的first five pages 可以很容易地回答这个问题 谢谢,这不是一个有用的评论,我当然读过这个文件。 @talonmies 无论如何,它的所有副本都应该从互联网上删除——它不是无用的资源。 说真的,请看图 5。它是您问题的准确答案。你甚至不需要阅读。看看就好 @user3728501:您问“我的线程块可以超过 CUDA 内核的最大数量吗?”。图 5 是该问题的答案。 【参考方案1】:它没有崩溃,因为“CUDA 核心”的数量与块的数量无关。并非所有块都必须并行执行。 CUDA 只是将你的一些块安排在其他块之后,在所有块执行完成后返回。
您知道,NVIDIA 错误地说明了其 GPU 中的内核数量,以便与单线程非矢量化 CPU 执行进行更简单的比较。你的 GPU 实际上是 has 6 cores 在 proper sense of the word;但是它们中的每一个都可以在大量数据上并行执行大量指令。请注意,Kepler GPU 上的真正核心被称为“SMx”es(并在 here 简要描述)。
所以:
[实际核心数] x [单个核心可以并行执行的最大指令数] = [“CUDA 核心数”]
例如6 x 160 = 960 用于您的卡。
即使这是对事物的粗略描述,在 SMx 中发生的事情并不总是允许我们每个周期并行执行 160 条指令。例如,当每个块只有 1 个线程时,该数字会下降 32 倍(!)
因此,即使您使用 960 而不是 961 块,您的执行也不会像您希望的那样并行化。并且 - 你真的应该在每个块中使用更多线程来利用 GPU 的并行执行功能。更重要的是,你应该找到一本关于 CUDA/GPU 编程的好书。
【讨论】:
@user3728501:答案重写,我希望这更清楚。 好的,谢谢 - 我明白这一点......除了我认为我有“5 * 192 CUDA 核心” - 但这只是一个细节问题。 顺便说一句,我进行了编辑,因为我认为您漏掉了一个字 - 如果我编辑不正确,请随时再次更改。【参考方案2】:一个更简单的答案:
块不会同时执行。有些块可能在其他块开始之前就完成了。 GPU 一次执行 X 个块,完成这些块,抓取更多块,然后继续,直到所有块都完成。
旁白:这就是为什么 thread_sync 只同步块内的线程,而不是整个内核内的线程。
【讨论】:
以上是关于为啥允许我运行块数超过 GPU 的 CUDA 核心数的 CUDA 内核?的主要内容,如果未能解决你的问题,请参考以下文章
GPU/CUDA:网格的最大块数和每个多处理器的最大驻留块数
为啥在使用 cudaMallocManaged 时 NVIDIA Pascal GPU 运行 CUDA 内核速度很慢