基本 CUDA 指针/数组内存分配和使用
Posted
技术标签:
【中文标题】基本 CUDA 指针/数组内存分配和使用【英文标题】:Basic CUDA pointer/array memory allocation and use 【发布时间】:2013-07-02 15:29:07 【问题描述】:我上周开始使用 CUDA,因为我必须将现有的 c++ 程序转换为 cuda 以进行研究。
这是 CUDA by Example 一书中的一个基本示例,我推荐给任何想学习 CUDA 的人!
有人能解释一下如何使用空指针“dev_c”分配 GPU 内存吗?
HANDLE_ERROR( cudaMalloc( (void**)&dev_c, N * sizeof(int) ) );
那么,在调用函数'add'时不传递任何'dev_c'值,而是将*c视为全局函数中的一个数组并从函数内部写入?为什么在任何地方都没有将其定义为数组时这可能?
add<<<N,1>>>( dev_a, dev_b, dev_c );
最后,在执行以下加法时,术语 c[0]、c[1] 等到底保存在哪里?
c[tid] = a[tid] + b[tid];
我希望我能很好地解释自己,但请随时提出任何后续问题。对 C 和 CUDA 都是新手,所以要友好:D
完整代码如下:
#include "book.h"
#define N 1000
__global__ void add( int *a, int *b, int *c )
int tid = blockIdx.x; // this thread handles the data at its thread id
if (tid < N)
c[tid] = a[tid] + b[tid];
int main( void )
int a[N], b[N], c[N];
int *dev_a, *dev_b, *dev_c;
// allocate the memory on the GPU
HANDLE_ERROR( cudaMalloc( (void**)&dev_a, N * sizeof(int) ) );
HANDLE_ERROR( cudaMalloc( (void**)&dev_b, N * sizeof(int) ) );
HANDLE_ERROR( cudaMalloc( (void**)&dev_c, N * sizeof(int) ) );
// fill the arrays 'a' and 'b' on the CPU
for (int i=0; i<N; i++)
a[i] = -i;
b[i] = i * i;
// copy the arrays 'a' and 'b' to the GPU
HANDLE_ERROR( cudaMemcpy( dev_a, a, N * sizeof(int),
cudaMemcpyHostToDevice ) );
HANDLE_ERROR( cudaMemcpy( dev_b, b, N * sizeof(int),
cudaMemcpyHostToDevice ) );
add<<<N,1>>>( dev_a, dev_b, dev_c );
// copy the array 'c' back from the GPU to the CPU
HANDLE_ERROR( cudaMemcpy( c, dev_c, N * sizeof(int),
cudaMemcpyDeviceToHost ) );
// display the results
for (int i=0; i<N; i++)
printf( "%d + %d = %d\n", a[i], b[i], c[i] );
// free the memory allocated on the GPU
HANDLE_ERROR( cudaFree( dev_a ) );
HANDLE_ERROR( cudaFree( dev_b ) );
HANDLE_ERROR( cudaFree( dev_c ) );
return 0;
谢谢!
【问题讨论】:
【参考方案1】:不可能在 SO 问题的空间中教授 CUDA。我将尝试回答您的问题,但您可能应该利用一些资源。如果您不了解 C 或 C++,这将特别困难,因为典型的 CUDA 编程依赖于这些。
您可能想参加一些介绍性网络研讨会here,例如:
使用 CUDA C 进行 GPU 计算 - 简介 (2010) 介绍使用 CUDA C 进行 GPU 计算的基础知识。概念将通过代码示例的演练进行说明。无需先前的 GPU 计算经验
使用 CUDA C 的 GPU 计算 – 高级 1 (2010) 一级优化技术,例如全局内存优化和处理器利用率。将使用真实的代码示例来说明概念
现在回答你的问题:
有人能解释一下如何使用空指针“dev_c”分配 GPU 内存吗?
dev_c
一开始是一个空指针。但是cudaMalloc
函数allocates GPU memory 根据传递给它的大小,建立一个指向该分配的指针,并将该指针存储到dev_c
指针中。它可以这样做,因为我们是 passing the address of dev_c
,而不是实际的指针本身。
那么,在调用函数'add'时不传递任何'dev_c'值,而是将*c视为全局函数中的数组并从函数内部写入?为什么在任何地方都没有将其定义为数组时这可能?
在 C 中,指针(dev_c
就是这样)可以指向单个值或值数组。指针本身不包含有关它指向多少数据的信息。由于dev_c
是存储结果的,并且它已经被前面的cudaMalloc
函数正确初始化,我们可以使用它来将操作的结果存储在内核中。 dev_c
实际上指向int
(一个数组)的存储区域,其大小由N * sizeof(int)
给出,传递给前面的cudaMalloc
函数。
最后,在执行以下加法时,术语 c[0]、c[1] 等到底保存在哪里?
在c中,当我们有这样的函数定义时:
void my_function(int *c)...
这表示函数中的语句可以引用名为 c
的变量,就好像它是指向一个或多个 int
值的指针(单个值或值数组,从指向的位置开始存储) c
)。
当我们调用该函数时,我们可以使用一些其他变量作为 argument,函数 parameter 称为 c
,如下所示:
int my_ints[32];
my_function(my_ints);
现在,在my_function
内部,无论参数 c
被引用,它将使用(指针)my_ints
给出的参数 值。
相同的概念适用于 cuda 函数(内核)及其参数和参数。
【讨论】:
谢谢,现在这更有意义了!那么这是否意味着 (array) c 中的值被保存在先前在 cudaMalloc( (void**)&dev_c, N * sizeof(int) ) 中分配的 GPU 全局内存中? 是的。c
的内核用法存储在为c
参数传递的参数 中,在本例中为dev_c
。并且dev_c
之前已在设备全局内存中设置了分配的大小。这本质上是 C 行为,几乎与 CUDA 无关。
知道了!再次感谢您的详细回复,非常感谢!以上是关于基本 CUDA 指针/数组内存分配和使用的主要内容,如果未能解决你的问题,请参考以下文章