CUDA中的持久缓冲区
我有一个应用程序,我需要分配和维护一个持久缓冲区,该缓冲区可由CUDA中连续启动的多个内核使用。我最终需要将这个缓冲区的内容复制回主机 我的想法是声明一个全局范围设备符号,它可以直接在不同的内核中使用,而无需作为显式内核参数传递,比如CUDA中的持久缓冲区,cuda,Cuda,我有一个应用程序,我需要分配和维护一个持久缓冲区,该缓冲区可由CUDA中连续启动的多个内核使用。我最终需要将这个缓冲区的内容复制回主机 我的想法是声明一个全局范围设备符号,它可以直接在不同的内核中使用,而无需作为显式内核参数传递,比如 __device__ char* buffer; 但是,我不确定应该如何分配内存并将地址分配给这个设备指针,以便内存具有我需要的持久作用域。所以我的问题实际上分为两部分: 分配全局内存的各种方法的生存期是多少 如何分配内存并为全局范围指针赋值?是否有必要使用设备
__device__ char* buffer;
但是,我不确定应该如何分配内存并将地址分配给这个设备指针,以便内存具有我需要的持久作用域。所以我的问题实际上分为两部分:
malloc
并运行一个安装内核来实现这一点,或者我可以使用主机端API的一些组合来实现这一点malloc
并运行安装程序
内核,或者我可以使用一些主机端API的组合来
实现这一目标
这两种方法都可以根据需要工作,尽管主机API的使用要简单得多。这两种方法之间也有一些重要的区别
在设备代码中使用malloc
或new
的内存分配在设备运行时堆上分配。在设备代码中运行malloc
之前,必须使用适当大小的堆,否则调用可能会失败。而且主机端内存管理API无法访问设备堆,因此您还需要一个复制内核将内存内容传输到主机API可访问内存,然后才能将内容传输回主机
另一方面,主机API案例非常简单,没有设备端malloc
的限制。一个简单的例子如下所示:
__device__ char* buffer;
int main()
{
char* d_buffer;
const size_t buffer_sz = 800 * 600 * sizeof(char);
// Allocate memory
cudaMalloc(&d_buffer, buffer_sz);
// Zero memory and assign to global device symbol
cudaMemset(d_buffer, 0, buffer_sz);
cudaMemcpyToSymbol(buffer, &d_buffer, sizeof(char*));
// Kernels go here using buffer
// copy to host
std::vector<char> results(800*600);
cudaMemcpy(&results[0], d_buffer, buffer_sz, cudaMemcpyDeviceToHost);
// buffer has lifespan until free'd here
cudaFree(d_buffer);
return 0;
};
\uuuu设备\uuuuu字符*缓冲区;
int main()
{
char*d_缓冲区;
常量大小缓冲区大小=800*600*sizeof(字符);
//分配内存
Cudamaloc(d_缓冲区和d_sz缓冲区);
//零内存并分配给全局设备符号
cudaMemset(d_缓冲区,0,缓冲区_sz);
cudaMemcpyToSymbol(buffer,&d_buffer,sizeof(char*));
//内核在这里使用缓冲区
//复制到主机
标准:向量结果(800*600);
cudaMemcpy(&results[0],d_buffer,buffer_sz,cudamemcpydevicetoost);
//缓冲区在这里释放之前有使用寿命
cudaFree(d_缓冲区);
返回0;
};
[标准免责声明:在浏览器中编写的代码,未经编译或测试,使用风险自负]
因此,基本上您可以使用标准的主机端API实现您想要的功能:cudamaloc
、cudaMemcpyToSymbol
和cudaMemcpy
。不需要其他任何东西
分配全局内存的各种方法的生存期是多少
所有全局内存分配都有其分配上下文的生存期。这意味着您的应用程序分配的任何全局内存根据您的定义都是“持久的”,无论您是在GPU运行时堆上使用主机端API还是设备端分配
如何分配内存并为全局作用域赋值
指针?是否需要使用设备代码malloc
并运行安装程序
内核,或者我可以使用一些主机端API的组合来
实现这一目标
这两种方法都可以根据需要工作,尽管主机API的使用要简单得多。这两种方法之间也有一些重要的区别
在设备代码中使用malloc
或new
的内存分配在设备运行时堆上分配。在设备代码中运行malloc
之前,必须使用适当大小的堆,否则调用可能会失败。而且主机端内存管理API无法访问设备堆,因此您还需要一个复制内核将内存内容传输到主机API可访问内存,然后才能将内容传输回主机
另一方面,主机API案例非常简单,没有设备端malloc
的限制。一个简单的例子如下所示:
__device__ char* buffer;
int main()
{
char* d_buffer;
const size_t buffer_sz = 800 * 600 * sizeof(char);
// Allocate memory
cudaMalloc(&d_buffer, buffer_sz);
// Zero memory and assign to global device symbol
cudaMemset(d_buffer, 0, buffer_sz);
cudaMemcpyToSymbol(buffer, &d_buffer, sizeof(char*));
// Kernels go here using buffer
// copy to host
std::vector<char> results(800*600);
cudaMemcpy(&results[0], d_buffer, buffer_sz, cudaMemcpyDeviceToHost);
// buffer has lifespan until free'd here
cudaFree(d_buffer);
return 0;
};
\uuuu设备\uuuuu字符*缓冲区;
int main()
{
char*d_缓冲区;
常量大小缓冲区大小=800*600*sizeof(字符);
//分配内存
Cudamaloc(d_缓冲区和d_sz缓冲区);
//零内存并分配给全局设备符号
cudaMemset(d_缓冲区,0,缓冲区_sz);
cudaMemcpyToSymbol(buffer,&d_buffer,sizeof(char*));
//内核在这里使用缓冲区
//复制到主机
标准:向量结果(800*600);
cudaMemcpy(&results[0],d_buffer,buffer_sz,cudamemcpydevicetoost);
//缓冲区在这里释放之前有使用寿命
cudaFree(d_缓冲区);
返回0;
};
[标准免责声明:在浏览器中编写的代码,未经编译或测试,使用风险自负]
因此,基本上您可以使用标准的主机端API实现您想要的功能:cudamaloc
、cudaMemcpyToSymbol
和cudaMemcpy
。不需要其他任何东西