1

cudaMalloc() で割り当てられたエンティティ (およびそのサイズ) が現在 GPU デバイスに存在することを確認する最も簡単な方法は何でしょうか? 関数内のメモリ リークを見つけたいのですが、関数が 1 回だけ呼び出されて終了した場合はメモリ リークはありませんが (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 に答える