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

时间:2016-10-27 08:30:09

标签: cuda cuda-gdb nvprof

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

Nsight Visual Profiler看起来太复杂了,而且cuda-memcheck发现没有泄漏!

1 个答案:

答案 0 :(得分:2)

使用CUDA API无法做到这一点。如果您确实想要这样做,则需要创建自己的检测系统,该系统包装代码调用的CUDA内存分配/释放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