Memory management cudaMemGetInfo不是常数?

Memory management cudaMemGetInfo不是常数?,memory-management,cuda,Memory Management,Cuda,我在测试动态分配,即 __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(tota

我在测试动态分配,即

__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));
无尺寸,总计;
CUDA_支票(cudaMemGetInfo(&免费,&总计));
fprintf(标准输出,“\t####可用VRAM:%g Mo/%g Mo(总计)\n\n”,自由/功率(10,6),总/功率(10,6));

对于(int t=0;t来说,听起来您确实需要先阅读这篇文章,然后再进一步进行配对

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

您应该发现在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上的内存。

听起来您确实需要先阅读此内容,然后再进行配对

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

您应该发现在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上的内存。

好的,谢谢!我对cuda上下文的概念仍然有困难,但我正在阅读文档。@FrançoisLaenen:上下文是主机进程/线程特定的“会话”在给定的GPU上。每个上下文在GPU上都有自己的虚拟地址空间,CUDA运行时支持、代码和数据都加载到其中。在运行时API中,这大部分是隐藏的,但如果您查看驱动程序API文档,您可以看到管理上下文的显式调用。好的,我现在理解得更好了。例如,cudaMallo返回的指针来自主机的c不会被另一个上下文使用,因为它将被加载到第一个上下文的VAS中?@FrançoisLaenen:这基本上是正确的,是的。CUDA API实际上有两个特殊的API功能,允许进程之间的指针可移植性和上下文共享,但“标准”模型按照您描述的方式工作。好的。我将发布另一个关于堆大小的问题,我找不到答案。好的,谢谢!我对cuda上下文的概念仍然有困难,但我正在阅读文档。@FrançoisLaenen:上下文是主机进程/线程特定的“会话”在给定的GPU上。每个上下文在GPU上都有自己的虚拟地址空间,CUDA运行时支持、代码和数据都加载到其中。在运行时API中,这大部分是隐藏的,但如果您查看驱动程序API文档,您可以看到管理上下文的显式调用。好的,我现在理解得更好了。例如,cudaMallo返回的指针来自主机的c不会被另一个上下文使用,因为它将被加载到第一个上下文的VAS中?@FrançoisLaenen:这基本上是正确的,是的。CUDA API实际上有两个特殊的API功能,允许进程之间的指针可移植性和上下文共享,但“标准”模型按照您描述的方式工作。好的。我将发布另一个关于堆大小的问题,我找不到答案。