【问题标题】:Understanding memory usage in CUDA了解 CUDA 中的内存使用情况
【发布时间】:2012-09-04 23:58:32
【问题描述】:

我有一个 NVIDIA GTX 570 显卡,在 Ubuntu 10.10 系统 上运行 Cuda 4.0。

我知道,为了性能,我们需要有效地访问内存,并巧妙地使用设备上的注册共享内存。

但是我不明白如何计算,每个线程可用的寄存器数量,或者单个块可以使用多少共享内存以及针对特定内核配置的其他简单/重要计算。

我想通过一个显式的例子来理解这一点。 顺便说一句,我目前正在尝试编写一个粒子代码,其中一个内核应该如下所示。

每个块是一个一维线程集合,每个网格是一个一维块的集合。

  • 块数:16384
  • 每个块的线程数:32(=>线程总数 32*16384 = 524288
  • 每个线程块都有一个 32 x 32 共享内存的二维整数数组 一起工作。

在一个线程中,我想存储一些double 类型的数字。但我不确定 我可以存储多少这样的double 数字而没有任何寄存器溢出到本地内存(在设备上)。谁能告诉 我这个内核配置每个线程可以存储多少个双精度数?

上面提到的我的每个块的共享内存配置是否有效?

一个关于如何推断这些事情的示例计算将非常 说明性和有用的

这是关于我的 GTX 570 的信息:(使用来自 CUDA-SDK 的 deviceQuery)

[deviceQuery] starting...
./deviceQuery Starting...

 CUDA Device Query (Runtime API) version (CUDART static linking)

Found 1 CUDA Capable device(s)

    Device 0: "GeForce GTX 570"
      CUDA Driver Version / Runtime Version          4.0 / 4.0
      CUDA Capability Major/Minor version number:    2.0
      Total amount of global memory:                 1279 MBytes (1341325312 bytes)
      (15) Multiprocessors x (32) CUDA Cores/MP:     480 CUDA Cores
      GPU Clock Speed:                               1.46 GHz
      Memory Clock rate:                             1900.00 Mhz
      Memory Bus Width:                              320-bit
      L2 Cache Size:                                 655360 bytes
      Max Texture Dimension Size (x,y,z)             1D=(65536), 2D=(65536,65535), 3D=(2048,2048,2048)
      Max Layered Texture Size (dim) x layers        1D=(16384) x 2048, 2D=(16384,16384) x 2048
      Total amount of constant memory:               65536 bytes
      Total amount of shared memory per block:       49152 bytes
      Total number of registers available per block: 32768
      Warp size:                                     32
      Maximum number of threads per block:           1024
      Maximum sizes of each dimension of a block:    1024 x 1024 x 64
      Maximum sizes of each dimension of a grid:     65535 x 65535 x 65535
      Maximum memory pitch:                          2147483647 bytes
      Texture alignment:                             512 bytes
      Concurrent copy and 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
      Concurrent kernel execution:                   Yes
      Alignment requirement for Surfaces:            Yes
      Device has ECC support enabled:                No
      Device is using TCC driver mode:               No
      Device supports Unified Addressing (UVA):      Yes
      Device PCI Bus ID / PCI location ID:           2 / 0
      Compute Mode:
         < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) >

    deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 4.0, CUDA Runtime Version = 4.0, NumDevs = 1, Device = GeForce GTX 570
    [deviceQuery] test results...
    PASSED

    Press ENTER to exit...

【问题讨论】:

  • “商店”是什么意思?在标量变量中(将进入寄存器),还是在数组中(将进入片外本地存储器)?
  • 我的意思是标量变量或数组。从您的评论看来,如果我存储 8 个标量变量,它们将存储在一个线程中,但如果我存储一个 8 个双精度数组,那么该数组将存储在片外本地内存中?这似乎很奇怪。你能澄清一下吗?
  • This answer 应该说清楚。

标签: memory memory-management cuda


【解决方案1】:

所以,内核配置有点复杂。您应该使用CUDA OCCUPANCY CALCULATOR。另一方面,您必须研究经线的工作原理。一旦一个块被分配给一个 SM,它会被进一步划分为 32 个线程单元,称为 warp。可以说,warp 是 SM 中的线程调度单元。对于给定的块大小和分配给每个 SM 的给定块数,我们可以计算驻留在 SM 中的扭曲数。在您的情况下,一个经线包含 32 个线程,因此如果您有一个包含 256 个线程的块,那么您有 8 个经线。现在选择正确的内核设置取决于您的数据和操作,请记住您必须完全占用一个 SM,即:您必须在每个 SM 中获得完整的线程容量以及围绕长延迟操作进行调度的最大扭曲数.另一个重要的事情是不要超过每个块的最大线程数的限制,在你的情况下是 1024。

【讨论】:

  • CC 2.x 设备每个 SM 可以有 8 个块。 CC 3.x 设备每个 SM 可以有 16 个块。如果每个块只有 32 个线程,您将提前达到设备限制。您可以增加每个块的线程数和每个块的共享内存来解决这个问题。这将要求您更改每个线程和共享内存的索引计算,但您可能会看到性能大幅提升。
  • Double 需要 2 个相邻的 32 位寄存器。对于 GTX570 (CC2.0),每个 SM 有 32K 寄存器。每个块有 32 个线程,每个设备的块将限制为 256 个线程。您将只使用可用寄存器的 1/2。根据您拥有多少控制代码,假设每个线程有 63 个寄存器,您将能够在 RF 中容纳 20-30 个双精度。如果您按照@facunvd 链接到计算器并将设备设置为 2.0,您应该会看到此限制。你也会明白为什么我建议增加每个块的线程数。
  • 我想了解你@GregSmith。你是说我的回答是对的?如果是这样,那么您是在说我们不必只担心我们可以在 SM 中运行多少个 warp,还必须考虑每个 SM 的块数?
  • 是的,每个设备都有每个 SM 的块限制。如果您每个块仅启动 1 个 warp,那么您将限制自己的 CC 2.0 到每个 SM 8 个 warp 或 16.6% 的占用率 (8/48),这不足以隐藏延迟。此外,在这种占用情况下,您甚至无法充分利用寄存器文件,因为这需要 (32K/ MAX_REGISTER_THREAD) 至少 512 个线程(16 个线程)。
  • @GregSmith “...假设每个线程有 63 个寄存器,在 RF 中适合 20-30 双倍”。 RF 在这里是什么意思?
猜你喜欢
  • 1970-01-01
  • 2011-03-09
  • 2018-10-11
  • 2019-04-18
  • 1970-01-01
  • 1970-01-01
  • 2020-12-10
  • 2015-01-13
  • 2016-11-27
相关资源
最近更新 更多