1

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

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

4

1 回答 1

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 上的内存管理并不像您想象的那样可预测,并且在仅根据设备在任何给定情况下报告的可用内存量来诊断内存泄漏时需要小心立即的。有关更多详细信息,请参阅此问题。

于 2016-12-29T10:42:05.367 回答