2013-07-29 11 views
0

我测试的动态分配,即cudaMemGetInfo不是常量?

__device__ double *temp; 
__global__ 
void test(){ 
    temp = new double[125000]; //1MB 
} 

调用此函数100次,看看内存正在减少:

size_t free, total; 
CUDA_CHECK(cudaMemGetInfo(&free, &total)); 
fprintf(stdout,"\t### Available VRAM : %g Mo/ %g Mo(total)\n\n", free/pow(10., 6), total/pow(10., 6)); 

for(int t=0;t<100;t++){ 
     test<<<1, 1>>>(); 
     CUDA_CHECK(cudaDeviceSynchronize()); 
     fprintf(stdout,"\t### Available VRAM : %g Mo/ %g Mo(total)\n\n", free/pow(10., 6), total/pow(10., 6)); 
    } 
CUDA_CHECK(cudaMemGetInfo(&free, &total)); 
fprintf(stdout,"\t### Available VRAM : %g Mo/ %g Mo(total)\n\n", free/pow(10., 6), total/pow(10., 6)); 

,它实际上是。

  1. 注:当试图而不调用函数和 cudaMemGetInfo内循环,这是减少从800到650 莫,我得出的结论是到控制台输出了〜150密苏里州 事实上,当尝试像上面写的代码,结果不会 更改。但它是巨大的!
  2. 循环后我得到约50Mo的可用内存减少(我没有通过给内核发出有用的评论来减少)。当我在内核中添加一个删除(temp)时,似乎不会减少浪费的内存量,我仍然会减少~30Mo。为什么?
  3. 循环后使用cudaFree(temp)或cudadeviceReset()也没有多大帮助。为什么?以及如何释放内存?

回答

3

这真的听起来像你需要阅读这questionanswer对,然后再进一步。

您在内核中分配的内存来自内核中的静态运行时堆,该静态运行时堆作为CUDA运行时在程序运行时启动的“延迟”上下文建立的一部分进行分配。建立上下文的第一个CUDA调用还将加载包含内核代码的模块,并为随后的内核调用保留本地内存,运行时缓冲区和运行时堆。这就是你观察到的大部分内存消耗来自哪里。运行时API包含一个允许用户控制分配大小的call

你会发现,做这样的事情上CUDA版本4或5:

size_t free, total; 
CUDA_CHECK(cudaMemGetInfo(&free, &total)); 
fprintf(stdout,"\t### Available VRAM : %g Mo/ %g Mo(total)\n\n", 
        free/1e6, total/1e6); 

cudaFree(0); 

CUDA_CHECK(cudaMemGetInfo(&free, &total)); 
fprintf(stdout,"\t### Available VRAM : %g Mo/ %g Mo(total)\n\n", 
        free/1e6, total/1e6); 

// Kernel loop follows 

[免责声明:写在浏览器中,使用风险自担]

应显示后的可用内存下降调用cudaFree(0),因为这会启动上下文初始化序列,这会消耗GPU上的内存。

+0

好的,谢谢!我对cuda环境的概念仍然有困难,但我正在阅读文档。 –

+0

@FrançoisLaenen:上下文是给定GPU上的主机进程/线程特定的“会话”。每个上下文在GPU上都有自己的虚拟地址空间,CUDA运行时支持,代码和数据将加载到该空间中。在运行时API中,这大部分是隐藏的,但如果您查看驱动程序API文档,则可以看到显式调用管理上下文。 – talonmies

+0

好吧,我现在好了。举例来说,cudaMalloc从主机返回的指针将不会被另一个上下文使用,因为它将被加载到第一个上下文的VAS中? –