cudaMemGetInfo使用vram并返回错误的值



我正在使用cudaMemGetInfo来获取系统当前使用的vram。

extern __host__ cudaError_t CUDARTAPI cudaMemGetInfo(size_t *free, size_t *total);

我有两个问题:

  • 最主要的是,仅当图形设备几乎没有可用内存进行分配时,返回的可用值才是正确的。否则,即使 GPU-Z 明确声明使用了大约 80% 的内存,它也会保持在大约 20% 的内存使用量。当我达到95%的内存使用时,cudaMemGetInfo突然返回了一个很好的值。请注意,总内存始终正确。

  • 第二个问题是,只要我使用该功能,就会分配视频内存。至少 40MB,但在某些图形设备上可以达到 400。

我的代码 :

#include <cuda_runtime.h>
size_t Profiler::GetGraphicDeviceVRamUsage(int _NumGPU)
{
    cudaSetDevice(_NumGPU);
    size_t l_free = 0;
    size_t l_Total = 0;
    cudaError_t error_id = cudaMemGetInfo(&l_free, &l_Total);
    return (l_Total - l_free);
}

我尝试了 5 种不同的 nvidia 图形设备。问题总是相同的。

知道吗?

关于你的第一点,我无法重现这一点。如果我将您的代码扩展为一个完整的示例:

#include <iostream>
size_t GetGraphicDeviceVRamUsage(int _NumGPU)
{
    cudaSetDevice(_NumGPU);
    size_t l_free = 0;
    size_t l_Total = 0;
    cudaError_t error_id = cudaMemGetInfo(&l_free, &l_Total);
    return (l_Total - l_free);
}
int main()
{
    const size_t sz = 1 << 20;
    for(int i=0; i<20; i++) {
        size_t before = GetGraphicDeviceVRamUsage(0);
        char *p;
        cudaMalloc((void **)&p, sz);
        size_t after = GetGraphicDeviceVRamUsage(0);
        std::cout << i << " " << before << "->" << after << std::endl;
   }
   return cudaDeviceReset();
}

我在 Linux 机器上得到这个:

$ ./meminfo 
0 82055168->83103744
1 83103744->84152320
2 84152320->85200896
3 85200896->86249472
4 86249472->87298048
5 87298048->88346624
6 88346624->89395200
7 89395200->90443776
8 90443776->91492352
9 91492352->92540928
10 92540928->93589504
11 93589504->94638080
12 94638080->95686656
13 95686656->96735232
14 96735232->97783808
15 97783808->98832384
16 98832384->99880960
17 99880960->100929536
18 100929536->101978112
19 101978112->103026688

我在Windows WDDM机器上得到这个:

>meminfo
0 64126976->65175552
1 65175552->66224128
2 66224128->67272704
3 67272704->68321280
4 68321280->69369856
5 69369856->70418432
6 70418432->71467008
7 71467008->72515584
8 72515584->73564160
9 73564160->74612736
10 74612736->75661312
11 75661312->76709888
12 76709888->77758464
13 77758464->78807040
14 78807040->79855616
15 79855616->80904192
16 80904192->81952768
17 81952768->83001344
18 83001344->84049920
19 84049920->85098496

在我看来,两者似乎是一致的。

关于您的第二点:如果不存在上下文,cudaSetDevice在您传递给它的设备编号上建立 CUDA 上下文。建立 CUDA 上下文将为运行 CUDA 代码所需的运行时组件保留内存。因此,如果它是您调用的第一个包含函数的 CUDA API,则调用该函数会消耗内存是完全正常的。

最新更新