c++ - cudaMemGetInfo 使用 vram 并返回错误值

标签 c++ cuda

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

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

我有两个问题:

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

  • 第二个问题是,一旦我使用该功能,就会分配显存。至少 40 兆字节,但在某些图形设备上可以达到 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,则调用该函数会消耗内存是完全正常的。

关于c++ - cudaMemGetInfo 使用 vram 并返回错误值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37410891/

相关文章:

c++ - 如何在 C++11 中正确初始化数据成员?

开源 CUDA IDE

cuda - GPU上的 float 除法与CPU上的 float 除法

c++ - 二维 CUDA 中值滤波器优化

cuda - GPU 上的静态和动态调度是什么?

c++ - 缩短条件以检查 x 是否不是四个数字中的任何一个

C++ 为什么这段代码可以编译?

c++ - 使用redis做日志缓存 : Is it possible to create an eviction policy that evicts to PostgreSQL?

python - ctypes自己的库加载但无法访问函数/方法

cuda - 我可以使用推力::host_vector 还是我必须使用 cudaHostAlloc 来使用推力进行零复制?