cuda - CUDA内存是如何管理的?

标签 cuda nvidia gpu

当我运行仅分配少量全局内存(低于 20 M)的 CUDA 程序时,出现“内存不足”错误。 (从其他人的帖子来看,我认为问题与内存碎片有关)我试图理解这个问题,并意识到我有几个与 CUDA 内存管理相关的问题。

  1. CUDA中有虚拟内存的概念吗?

  2. 如果只允许一个内核同时在 CUDA 上运行,那么在它终止后,它使用或分配的所有内存都会被释放吗?如果没有,这些内存何时释放?

  3. 如果允许多个内核在 CUDA 上运行,它们如何确保它们使用的内存不重叠?

谁能帮我回答这些问题?谢谢

编辑 1:操作系统:x86_64 GNU/Linux CUDA版本:4.0 设备:Geforce 200,是机器自带的GPU之一,我觉得不是显示设备。

编辑 2:以下是我经过一番研究后得到的结果。请随时纠正我。

  1. CUDA 将为每个主机线程创建一个上下文。此上下文将保留诸如内存的哪一部分(预分配内存或动态分配内存)已为此应用程序保留的信息,以便其他应用程序无法写入它。当此应用程序(不是内核)终止时,这部分内存将被释放。

  2. CUDA 内存由链接列表维护。当一个应用程序需要分配内存时,它会遍历这个链表,看看是否有连续的内存块可供分配。如果找不到这样的 block ,即使总可用内存大小大于请求的内存,也会向用户报告“内存不足”错误。这就是与内存碎片相关的问题。

  3. cuMemGetInfo 会告诉您有多少内存可用,但不一定会告诉您由于内存碎片,您可以在最大分配中分配多少内存。

  4. 在 Vista 平台 (WDDM) 上,GPU 内存虚拟化是可能的。也就是说,多个应用程序几乎可以分配整个 GPU 内存,而 WDDM 将管理将数据交换回主内存。

新问题: 1、如果context中预留的内存在应用终止后会被完全释放,内存碎片应该不存在。一定有某种数据留在内存中。 2.有什么办法可以重构GPU显存?

最佳答案

您的代码在运行时可用的设备内存基本上计算为

Free memory =   total memory 
              - display driver reservations 
              - CUDA driver reservations
              - CUDA context static allocations (local memory, constant memory, device code)
              - CUDA context runtime heap (in kernel allocations, recursive call stack, printf buffer, only on Fermi and newer GPUs)
              - CUDA context user allocations (global memory, textures)

如果您收到内存不足消息,则可能是前三项中的一项或多项在您的用户代码尝试获取 GPU 内存之前占用了大部分 GPU 内存。如果正如您所指出的那样,您没有在显示 GPU 上运行,那么上下文静态分配最有可能是问题的根源。 CUDA 通过在设备上建立上下文时预先分配上下文所需的所有内存来工作。有很多东西被分配来支持上下文,但上下文中最大的单一消费者是本地内存。对于设备上的每个多进程,运行时必须保留上下文中的任何内核将为每个多处理器可以同时运行的最大线程数消耗的最大本地内存量。如果在具有大量多处理器的设备上加载本地内存繁重的内核,这可能会占用数百 Mb 的内存。

查看可能发生的情况的最佳方法是编写一个没有设备代码的主机程序,它建立上下文并调用 cudaMemGetInfo。这将向您显示设备在最小上下文开销的情况下有多少内存。然后运行有问题的代码,在第一个 cudaMalloc 调用之前添加相同的 cudaMemGetInfo 调用,这将为您提供上下文正在使用的内存量。这可能会让您了解内存的去向。如果您在第一次 cudaMalloc 调用时失败,则碎片问题不太可能。

关于cuda - CUDA内存是如何管理的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13128159/

相关文章:

c++ - 在 cuda __device__ 函数中分配 (malloc) double**

functional-programming - 对GPU的纯函数式编程

c++ - CUDA __global__ 函数中的 printf

cuda - 如何使用 cuSparse 将两个稀疏矩阵相乘?

cuda - block 中的线程和经线(32 个线程)有什么区别?

opencv - 如何在没有CMake的情况下在opencv v2.4.4和VC10中启用CUDA 5.0并解决错误 'missing cudart32_42_9.dll'?

cuda - 在哪个设备上创建流与在哪个设备上执行代码之间是否存在关系?

caching - 英伟达 CUDA : cache L2 and multiple kernel invocations

cuda - CUDA 中有多少个网格

tensorflow - 如何在 gpu 支持下安装 Keras?