CUDA:堆叠和堆

CUDA: stack and heap

本文关键字:CUDA      更新时间:2023-10-16

就像标题一样,有人能为我提供更多关于 CUDA 中的堆和堆栈吗?它与 CPU 内存中的原始堆和堆栈有什么不同吗?

当我在 CUDA 中增加堆栈大小时遇到了问题,它似乎有其局限性,因为当我将堆栈大小设置为 1024*300(Tesla M2090)时 cudaDeviceSetLimit ,我得到一个错误:argument invalid .

我想问的另一个问题是:当我将堆大小设置为非常大的数字(大约 2GB)以分配包含 2000 个元素的 RTree(数据结构)时,我在运行时出现错误:too many resources requested to launch

知道吗?

P/s:我只用单线程启动(kernel<<<1,1>>>

关于堆栈和堆

堆栈是按线程分配的,并且具有硬件限制(见下文)。驻留在全局内存中,可以使用 malloc() 进行分配,并且必须使用 free()(CUDA 文档)显式释放。

此设备的功能:

void* malloc(size_t size);
void free(void* ptr);

可能很有用,但我建议仅在真正需要时才使用它们。重新考虑使用主机端函数分配内存的代码会是一种更好的方法(如cudaMalloc)。


堆栈大小有一个硬件限制,可以通过以下最小值来计算(根据@njuffa的答案):

  • 每个线程的本地内存量
  • 可用 GPU 内存/SM 数/每个 SM 的最大驻留线程数

当您增加大小并且只运行一个线程时,我想您的问题是第二个限制,在您的情况下(TESLA M2090)应该是:6144/16/512 = 750KB


具有固定大小(默认为 8MB),必须在使用函数 cudaDeviceSetLimit 调用 malloc() 之前指定该大小。请注意,由于某些分配开销,分配的内存将至少是请求的大小。还值得一提的是,内存限制不是按线程限制的,而是具有 CUDA 上下文的生命周期(直到通过调用 free()释放),并且可以在后续内核启动中由线程使用。

堆栈上的相关文章: ...内核的堆栈框架,...每个 CUDA 线程的本地内存

堆的相关帖子: ...堆内存..., ...每个线程的堆内存限制

堆栈和堆是不同的东西。堆栈表示每个线程堆栈,堆表示设备 malloc/new 用于分配内存的每个上下文运行时堆。您可以使用 cudaLimitStackSize 标志设置堆栈大小,并使用 cudaLimitMallocHeapSize 标志设置运行时堆,两者都传递给 cudaDeviceSetLimit API。

听起来您想增加堆大小,但试图通过更改堆栈大小来做到这一点。另一方面,如果您需要较大的堆栈大小,则可能必须减少使用的每个块的线程数,以避免内核启动失败。