检查 GPU 内存中当前驻留的实体

Checking currently residing entities in GPU memory

检查哪些(及其大小)已使用 cudaMalloc () 分配的实体当前驻留在 GPU 设备上的最简单方法是什么?我想找到一个函数内部的内存泄漏,如果它只调用一次并退出,则没有内存泄漏(通过cuda-memcheck检查),但如果调用多次内存占用越来越大。

Nsight Visual Profiler 对于我的要求来说似乎太复杂了,而且 cuda-memcheck 没有发现泄漏!

无法使用 CUDA API 执行此操作。如果您确实想这样做,则需要制作自己的检测系统来包装您的代码调用的 CUDA 内存 allocation/deallocation API。最简单的实现可能如下所示:

#include <iostream>
#include <vector>
#include <algorithm>

typedef std::pair<void*, size_t> mrecord;
struct mymemory
{
    std::vector<mrecord> mstack;

    mymemory() {};

    cudaError_t cudaMalloc(void** p, size_t sz);
    cudaError_t cudaFree(void* p);
    void print_stack();

};

cudaError_t mymemory::cudaMalloc(void** p, size_t sz)
{
    cudaError_t ret = ::cudaMalloc(p, sz);

    if (ret == cudaSuccess) {
       mstack.push_back(mrecord(*p,sz));
    }
    return ret;
};


cudaError_t mymemory::cudaFree(void* p)
{
    cudaError_t ret = ::cudaFree(p);

    if (ret == cudaSuccess) {
        auto rit = std::find_if( mstack.begin(), mstack.end(),
                                 [&](const mrecord& r){ return r.first == p; } );
        if (rit != mstack.end()) {
            mstack.erase(rit);
        }
    }
    return ret;
};

void mymemory::print_stack()
{
    auto it = mstack.begin();
    for(; it != mstack.end(); ++it) {
        mrecord rec = *it;
        std::cout << rec.first << " : " << rec.second << std::endl;
    }
}


int main(void) 
{
    const int nallocs = 10;
    void* pointers[nallocs];

    mymemory mdebug;
    for(int i=0; i<nallocs; ++i) {
        mdebug.cudaMalloc(&pointers[i], 4<<i);
    }
    std::cout << "After Allocation" << std::endl;
    mdebug.print_stack();

    mdebug.cudaFree(pointers[1]);
    mdebug.cudaFree(pointers[7]);
    mdebug.cudaFree(pointers[8]);
    mdebug.cudaFree(0);

    std::cout << "After Deallocation" << std::endl;
    mdebug.print_stack();

    return 0;
}

[警告:仅非常经过轻微测试并需要 C++11 编译器支持]

哪个会这样做:

~/SO$ nvcc -std=c++11 -g -arch=sm_52 instrumentation.cu 
~/SO$ ./a.out 
After Allocation
0x705e40000 : 4
0x705e40200 : 8
0x705e40400 : 16
0x705e40600 : 32
0x705e40800 : 64
0x705e40a00 : 128
0x705e40c00 : 256
0x705e40e00 : 512
0x705e41000 : 1024
0x705f40000 : 2048
After Deallocation
0x705e40000 : 4
0x705e40400 : 16
0x705e40600 : 32
0x705e40800 : 64
0x705e40a00 : 128
0x705e40c00 : 256
0x705f40000 : 2048

这可能足以了解哪些内存分配正在泄漏。但是请注意,GPU 上的内存管理并不像您认为的那样可预测,并且在仅根据设备在任何给定情况下报告的可用内存量来诊断内存泄漏时需要小心立即的。有关详细信息,请参阅 this question