2012-09-12 46 views
14

我想了解手写内核的每个CUDA线程的资源使用情况。解释--ptxas选项的输出= -v

我编译kernel.cu文件到kernel.o文件,nvcc -arch=sm_20 -ptxas-options=-v

,我得到了下面的输出

ptxas info : Compiling entry function '_Z12searchkernel6octreePidiPdS1_S1_' for 'sm_20' 
ptxas info : Function properties for _Z12searchkernel6octreePidiPdS1_S1_ 
    72 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads 
ptxas info : Used 46 registers, 176 bytes cmem[0], 16 bytes cmem[14] 

看着上面的输出,是正确地说,

  • 每个CUDA线程使用46个寄存器?
  • 有没有注册泄漏到本地内存?

我对理解输出也有一些问题。

  • 我的内核调用了一大堆__device__函数。 IS为72个字节的__global____device__函数的堆栈帧的内存总和为 ?

  • 是什么0 byte spill stores0 bytes spill loads

  • 之间的差异为什么是cmem的信息(我假设是恒定的内存),重复两次用不同的数字?在内核中,我没有使用任何常量的内存。这是否意味着编译器正在引擎盖下,告诉GPU使用一些常量内存?

+0

“用于46个寄存器”表示编译器已经保留了每个线程46个寄存器进行编译的内核和其它寄存器溢出。您可以通过从内核PTX中使用的寄存器总数中减去此数字(46)来查找溢出寄存器的数量。 – ahmad

+2

@Ahmad:你的第一句话是正确的,但第二句话是不正确的。内核可以使用少于每个线程的最大允许寄存器数量,并且没有溢出到本地内存。 – talonmies

+1

为了详细说明talonmies的回复,PTX是一个具有无限寄存器的高级抽象。这是因为它可以编译多代GPU,并且寄存器的数量可以不同。只有当你编译到机器特定的代码时,你才能真正看到注册使用。无论如何,ptxas(将PTX编译为机器特定的代码)会告诉您溢出的数量。 – Tom

回答

13
  • 每个CUDA线程使用寄存器46? 是的,正确
  • 有没有注册泄漏到本地内存? 是,正确
  • 72字节是__global____device__函数堆栈帧的内存总和? 是的,正确
  • 0字节溢出存储和0字节溢出负载有什么区别?
    • 公平的问题,由于您可以泄漏计算值,加载一次,放弃它(即将其他东西存储到该寄存器中)然后重新加载(即重新使用它),加载可能会比商店更大。 更新:还要注意溢出加载/存储计数是基于静态分析的评论下面
  • 为什么是CMEM的信息由@njuffa描述(这我假设是恒定的内存)重复两次有不同的数字?在内核中,我没有使用任何常量内存。这是否意味着编译器正在引导GPU告诉GPU使用一些常量内存?
    • 常量内存用于几个目的,包括__constant__变量和内核参数,使用不同的“银行”,它开始得到一点详细但只要你使用少于64KB的变量和小于4KB的变量对于内核参数你会没事的。
+2

请注意,溢出加载和存储是静态计数的,即本地加载和本地存储指令数乘以宽度访问每个加载/存储。它们被标准化为字节,因为如果编译器有足够的关于对齐和寄存器分配允许的信息,它可能能够矢量化溢出加载/存储。由于计数是静态的,因此溢出/填充可能在循环内部,因此这不是直接测量溢出的流量。如果重新使用溢出数据,溢出加载可能会超过溢出存储。这意味着溢出加载字节> =溢出存储字节。 – njuffa

+2

谢谢@njuffa - 优点。编译器无法知道循环的跳闸次数(除非编译时常量)。真正分析溢出/填充成本的最好方法是使用Nsight(或独立NVVP)等分析器,它会根据执行而不是编译为您提供数据。 – Tom

+0

同意分析。编制者的泄漏统计数据作为一线指标很有用。如果没有溢出,无需担心。如果数字很小(例如<32字节),则L1缓存应该在不影响性能的情况下处理它们(记住数字是每个线程,因为线程局部内存用于溢出)。如果这些数字在成千上万的情况下可能会对性能产生负面影响,那么可能需要进行更详细的分析。 – njuffa