【问题标题】:Determining shared memory usage in CUDA Fortran确定 CUDA Fortran 中的共享内存使用情况
【发布时间】:2014-11-27 00:44:01
【问题描述】:

我一直在编写一些基本的 CUDA Fortran 代码。我希望能够确定我的程序在每个线程块中使用的共享内存量(用于占用率计算)。我一直在使用 -Mcuda=ptxinfo 进行编译,希望能找到这些信息。编译输出以

结尾

ptxas 信息:device_procedures_main_kernel_ 的函数属性 432 字节堆栈帧,1128 字节溢出存储,604 字节溢出加载 ptxas info : 使用了 63 个寄存器,96 字节 smem,320 字节 cmem[0]

这是输出中唯一提到 smem 的地方。全局子程序 main_kernel 中有一个数组,它具有 shared 属性。如果我删除共享属性,那么我会得到

ptxas 信息:device_procedures_main_kernel_ 的函数属性 432 字节堆栈帧,1124 字节溢出存储,532 字节溢出加载 ptxas info : 使用了 63 个寄存器,320 字节 cmem[0]

smem 消失了。似乎只计算了 main_kernel 中的共享内存:我的代码中的设备子例程使用具有 shared 属性的变量,但输出中似乎没有提到这些,例如设备子例程 evalfuncs 包括共享变量声明,但相关输出是

ptxas 信息:device_procedures_evalfuncs_ 的函数属性 504 字节堆栈帧,1140 字节溢出存储,508 字节溢出加载

是否所有具有共享属性的变量都需要在全局子程序中声明?

【问题讨论】:

    标签: cuda fortran


    【解决方案1】:

    是否所有具有共享属性的变量都需要在全局子程序中声明?

    没有。

    您没有显示示例代码、编译命令,也没有确定您正在使用的 PGI 编译器工具的版本。但是,对于您所看到的情况,我能想到的最可能的解释是,从 PGI 14.x 开始,默认的 CUDA 编译选项是生成可重定位的设备代码。这记录在the current PGI release notes 的第 2.2.3 节中:

    2.2.3。可重定位设备代码 rdc 选项可用于指定生成的 –ta=tesla 和 –Mcuda 标志 可重定位设备代码。从 Linux 上的 PGI 14.1 和 Windows 上的 PGI 14.2 开始,默认 Tesla-target OpenACC 和 CUDA Fortran 的代码生成和链接模式是 rdc, 可重定位设备代码。 您可以通过指定禁用默认值并启用旧行为和不可重定位代码 以下任何一项:–ta=tesla:nordc、–Mcuda=nordc,或通过指定任何 1.x 计算 能力或任何 Radeon 目标。

    因此(禁用)启用此功能的特定选项是:

    –Mcuda=(no)rdc
    

    (注意-Mcuda=rdc是默认的,如果你不指定这个选项)

    CUDA Fortran 将 Fortran 主机代码与设备代码分开。对于设备代码,CUDA Fortran 编译器进行 CUDA Fortran->CUDA C 转换,并将自动生成的 CUDA C 代码传递给 CUDA C 编译器。因此,rdcptxinfo 等开关的行为和期望源自底层等效 CUDA 编译器选项(分别为 -rdc=true-Xptxas -v)的行为。

    当 CUDA 设备代码在没有rdc 选项的情况下编译时,编译器通常会尝试内联从内核调用的设备(子)例程到主内核代码中。因此,编译器在生成ptxinfo时,可以在编译(ptx汇编)内核代码时确定所有资源需求(例如共享内存、寄存器等)。

    但是,当指定 rdc 选项时,编译器可能(取决于其他一些开关和函数属性)将设备子例程保留为具有自己入口点的单独可调用例程(即不内联)。在那种情况下,当设备编译器编译内核代码时,对设备子例程的调用看起来就像一条调用指令,并且编译器(此时)无法看到设备子例程的资源使用要求。这并不意味着编译序列中存在潜在缺陷。这只是意味着ptxinfo 机制在那个时间点无法准确汇总内核的资源需求以及所有称为子例程的资源。

    ptxinfo 输出也不声明设备子例程在rdc 模式下编译该子例程时使用的共享内存总量。

    如果关闭rdc模式:

    –Mcuda=nordc
    

    我相信你会看到一个内核使用的共享内存以及它所有调用的子例程的准确计算,给出一些警告,其中之一是编译器能够成功内联你调用的子例程(很可能,并且会计应该仍然有效,即使它不能)另一个是您正在使用内核以及同一文件中的所有调用子例程(即翻译单元)。如果您的内核在不同的翻译单元中调用设备子例程,那么rdc 选项是使其工作的唯一方法。

    无论如何,在运行时仍会为您的代码适当分配共享内存(假设您没有超出可用的共享内存总量)。您还可以通过使用诸如nvvp or nvprof 之类的分析器分析您的代码来准确读取内核使用的共享内存。

    如果这个解释没有描述你所看到的,我建议提供一个完整的示例代码,以及你正在使用的确切编译命令,以及你正在使用的 PGI 工具的版本。 (我认为这对未来的问题也是一个很好的建议。)

    【讨论】:

      猜你喜欢
      • 2023-03-23
      • 2013-06-06
      • 2016-12-24
      • 2013-07-02
      • 2011-06-29
      • 2021-10-21
      • 1970-01-01
      • 1970-01-01
      • 2021-06-16
      相关资源
      最近更新 更多