CUDA内存是如何管理的?

CUDA内存是如何管理的?,cuda,nvidia,gpu,Cuda,Nvidia,Gpu,当我运行只分配少量全局内存(低于20m)的CUDA程序时,出现了“内存不足”错误。(从其他人的帖子中,我认为问题与内存碎片有关)我试图理解这个问题,并意识到我有几个与CUDA内存管理相关的问题 CUDA中是否有虚拟内存概念 如果CUDA终止后,只允许一个内核同时在CUDA上运行,那么它使用或分配的所有内存都会释放吗?如果没有,这些内存何时释放 如果CUDA上允许运行多个内核,如何确保它们使用的内存不重叠 有人能帮我回答这些问题吗?谢谢 编辑1:操作系统:x86_64 GNU/Linux CUDA

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

  • CUDA中是否有虚拟内存概念

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

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

  • 有人能帮我回答这些问题吗?谢谢

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

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

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

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

  • cuMemGetInfo将告诉您有多少内存是可用的,但不一定是由于内存碎片,您可以在最大分配中分配多少内存

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

  • 新问题: 1.如果在应用程序终止后,上下文中保留的内存将完全释放,则内存碎片不应存在。内存中一定有某种数据。 2.有没有办法重组GPU内存

  • GPU片外存储器分为全局、局部和恒定存储器。这三种内存类型是虚拟内存的概念。全局内存对所有线程都是可用的,本地内存只对一个线程(主要用于寄存器溢出),常量内存是缓存的全局内存(只能从主机代码写入)。请参阅CUDA C编程指南中的5.3.2

  • 编辑:删除

  • 通过
    cudamaloc
    分配的内存从不重叠。对于内核在运行时分配的内存,应该有足够的可用内存。如果内存不足,尝试启动内核(我只是猜测一下),应该会收到“未知错误”错误消息。驱动程序无法启动和/或执行内核


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

    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
    。这将显示设备在最小上下文开销的情况下有多少内存。然后运行有问题的代码,在第一个
    cudamaloc
    调用之前添加相同的
    cudaMemGetInfo
    调用,该调用将为您提供上下文正在使用的内存量。这可能会让你了解内存的去向。如果您在第一次调用
    cudamaloc
    时出现故障,则碎片问题不太可能出现。

    您是否可以编辑该问题,以包括您使用的操作系统、GPU和cuda版本,以及GPU是显示设备还是非显示设备。这将关系到您问题的正确答案。为了回答额外的问题-用户可观察到的碎片发生在上下文中,没有办法更改GPU内的内存映射,这一切都由主机驱动程序处理。正如您所解释的,上下文分配由上下文静态分配组成,上下文用户分配和CUDA上下文运行时堆。我认为上下文静态分配和上下文用户分配的大小是预先决定的。因此,我认为内存碎片的唯一原因是上下文运行时堆,它仅在费米体系结构上。对吗?我猜系统将为上下文运行时堆预先分配一块内存,以便启用内核内的动态内存分配。你能把它编辑成只有最初的回溯,然后是一堆问题吗?谢谢你的回复