CUDA内存如何pipe理?

当我运行只分配less量全局内存(低于20 M)的CUDA程序时,出现“内存不足”错误。 (从别人的post来看,我觉得这个问题跟内存碎片有关)我试着去理解这个问题,并且意识到我有一些与CUDA内存pipe理有关的问题。

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

  2. 如果只允许一个内核在CUDA上同时运行,那么在其终止之后,它所使用或分配的所有内存是否会释放? 如果没有,当这些内存得到释放?

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

任何人都可以帮我回答这些问题吗? 谢谢

编辑1:操作系统:x86_64 GNU / Linux CUDA版本:4.0设备:Geforce 200,它是连接到机器的GPUS之一,我不认为它是一个显示设备。

编辑2:以下是我做了一些研究后得到的。 随时纠正我。

  1. CUDA将为每个主机线程创build一个上下文。 这个上下文将保留信息,比如为这个应用程序保留了哪部分内存(预分配的内存或dynamic分配的内存),以便其他应用程序不能写入。 当这个应用程序终止(而不是内核)时,这部分内存将被释放。

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

  3. cuMemGetInfo会告诉你有多less内存是空闲的,但是由于内存碎片,不一定能在最大分配中分配多less内存。

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

新问题:1.如果上下文中保留的内存将在应用程序终止后完全释放,则内存碎片不应存在。 内存中必须有某种数据。 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, only on Fermi GPUs) - CUDA context user allocations (global memory, textures) 

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

看看可能发生什么的最好方法是编写一个没有设置代码的主机程序来build立一个上下文并调用cudaMemGetInfo 。 这将显示设备有多less内存,最小的上下文开销。 然后运行有问题的代码,在第一个cudaMalloc调用之前添加相同的cudaMemGetInfo调用,然后再为您提供上下文正在使用的内存量。 这可能让你得到内存的去向。 如果您在第一次cudaMalloc调用失败,那么碎片就不太可能是问题。

  1. GPU片外存储器在全局,本地和常量内存中分开。 这三种内存types是虚拟内存的概念。 全局内存对于所有线程都是空闲的,本地仅仅用于一个线程(主要用于寄存器溢出)并且常量内存被高速caching的全局内存(只能从主机代码写入)。 看看CUDA C编程指南中的5.3.2。

  2. 编辑:删除

  3. 通过cudaMalloc分配的内存不会重叠。 对于在运行时分配的内存,应该有足够的可用内存。 如果你的内存不足,并试图启动一个内核(只有我猜),你应该得到“未知的错误”的错误信息。 该驱动程序比无法启动和/或执行内核。