cudaMemGetInfo使用vram并返回错误的值

时间:2016-05-24 10:27:06

标签: c++ cuda

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

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

我遇到两个问题:

  • 主要是当图形设备几乎没有可用于分配的内存时,返回的空闲值才正确。否则,即使GPU-Z清楚地表明使用了大约80%的内存,它仍然使用大约20%的内存。当我达到95%的内存时,cudaMemGetInfo会突然返回一个好的值。请注意,总内存始终是正确的。

  • 第二个问题是,只要我使用该功能,就会分配视频内存。至少40mbytes但在一些图形设备上可以达到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图形设备。问题总是一样的。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

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

#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,则调用该函数将消耗内存是完全正常的。