CUDA在哪里为内核分配堆栈帧?

8
我的内核调用失败并显示“内存不足”。它在栈帧中使用了大量的空间,我想知道这是否是导致其失败的原因。
当使用--ptxas-options=-v调用nvcc时,它会打印以下配置文件信息:
    150352 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info    : Used 59 registers, 40 bytes cmem[0]

硬件信息:GTX480, sm20, 1.5GB设备内存,每个多处理器48KB共享内存。
我的问题是堆栈帧在哪里分配:共享内存、全局内存、常量内存等?
我尝试使用每个块1个线程以及每个块32个线程。都出现了“内存不足”的错误。
另一个问题是:只有当寄存器总数不超过多处理器可用寄存器数(32k对于我的卡)时,才能增加驻留到一个多处理器的线程数。堆栈帧大小是否也适用类似的原则?
2个回答

8

栈是在本地内存中分配的。分配是每个物理线程(GTX480: 15 SM * 1536个线程/SM = 23040个线程)进行的。您正在请求每个线程150,352字节 =>大约需要3.4 GB的堆栈空间。如果大小超过此限制,CUDA可能会减少每个启动的最大物理线程数。CUDA语言不设计具有每个线程堆栈。

就寄存器而言,GTX480每个线程限制为63个寄存器,每个SM限制为32K寄存器。


3
栈帧确实是分配在本地内存中的。本地内存位于芯片外的设备内存中,如果未缓存,则访问速度较慢。 然而,在此情况下引用“每个SM有1536个线程”这个数字是不正确且误导性的。 内核启动所需的总本地内存量取决于网格中线程的总数,而不是每个SM允许的最大线程数,因此它是与运行时有关的。 - ritter
@wpunkt 引用gf100(gtx480)确实是正确的,每个SM有1536个线程,并且本地内存绝对是基于总驻留线程而不是启动中的总线程分配的。非驻留线程不需要本地内存。退役线程不需要本地内存。本地内存在运行时取决于CUDA驱动程序推迟对本地内存分配的更改直到启动。 - Greg Smith

0

堆栈帧很可能在本地内存中。

我相信本地内存使用存在一定限制,但即使没有这个限制,我认为CUDA驱动程序可能会分配比您的<<<1,1>>>启动配置中一个线程所需的更多本地内存。

无论如何,即使您设法实际运行您的代码,我担心由于所有这些堆栈操作,它实际上可能会非常慢。尝试减少函数调用次数(例如通过内联这些函数)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接