我目前正在浏览http://code.google.com/p/stanford-cs193g-sp2010/上的教程示例以学习CUDA.__global__
下面给出了演示功能的代码.它只创建了两个阵列,一个在CPU上,一个在GPU上,用7号填充GPU阵列,并将GPU阵列数据复制到CPU阵列中.
#include <stdlib.h>
#include <stdio.h>
__global__ void kernel(int *array)
{
int index = blockIdx.x * blockDim.x + threadIdx.x;
array[index] = 7;
}
int main(void)
{
int num_elements = 256;
int num_bytes = num_elements * sizeof(int);
// pointers to host & device arrays
int *device_array = 0;
int *host_array = 0;
// malloc a host array
host_array = (int*)malloc(num_bytes);
// cudaMalloc a device array
cudaMalloc((void**)&device_array, num_bytes);
int block_size = 128;
int grid_size = num_elements / block_size;
kernel<<<grid_size,block_size>>>(device_array);
// download and inspect the result on the host:
cudaMemcpy(host_array, device_array, num_bytes, cudaMemcpyDeviceToHost);
// print out the result element by element
for(int i=0; i < num_elements; ++i)
{
printf("%d ", host_array[i]);
}
// deallocate memory
free(host_array);
cudaFree(device_array);
}
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么他们cudaMalloc((void**)&device_array, num_bytes);
用双指针措辞?即使在这里定义cudamalloc()on说第一个参数是双指针.
为什么不简单地将指针返回到GPU上已分配内存的开头,就像malloc
CPU上的函数一样?
Cyg*_*sX1 22
所有CUDA API函数都返回错误代码(如果没有错误,则返回cudaSuccess).所有其他参数都通过引用传递.但是,在普通C中,您不能有引用,这就是为什么您必须传递要存储返回信息的变量的地址.由于要返回指针,因此需要传递双指针.
由于相同原因在地址上操作的另一个众所周知的功能是scanf
功能.有多少次你忘记&
在要存储值的变量之前写这个?;)
int i;
scanf("%d",&i);
Run Code Online (Sandbox Code Playgroud)
R..*_*R.. 20
这只是一个可怕的,可怕的API设计.为获取abstract(void *
)内存的分配函数传递双指针的问题是,您必须创建一个类型的临时变量void *
来保存结果,然后将其分配给您要使用的正确类型的实际指针.如在(void**)&device_array
,转换是无效的C并导致未定义的行为.您应该只编写一个行为与普通行为相似的包装函数malloc
并返回一个指针,如:
void *fixed_cudaMalloc(size_t len)
{
void *p;
if (cudaMalloc(&p, len) == success_code) return p;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我们将它转换为双指针,因为它是指向指针的指针.它必须指向GPU内存的指针.cudaMalloc()所做的是它在GPU上分配一个内存指针(带空格),然后由我们给出的第一个参数指向.
小智 6
在C / C ++中,您可以在运行时通过调用malloc
函数动态分配一个内存块。
int * h_array;
h_array = malloc(sizeof(int));
Run Code Online (Sandbox Code Playgroud)
该malloc
函数返回分配的存储块的地址,该地址可以存储在某种指针的变量中。
CUDA中的内存分配在两个方面有所不同,
cudamalloc
返回一个整数作为错误代码,而不是一个指向存储块。除了要分配的字节大小外,cudamalloc
还需要一个double void指针作为其第一个参数。
int * d_array
cudamalloc((void **) &d_array, sizeof(int))
第一个区别的原因是所有CUDA API函数都遵循返回整数错误代码的约定。因此,为了使事情保持一致,cudamalloc
API还返回一个整数。
可以通过两个步骤来理解将双指针作为函数的第一个参数的要求。
首先,由于我们已经决定使cudamalloc返回一个整数值,所以我们不能再使用它来返回分配的内存的地址。在C语言中,函数进行通信的唯一其他方法是将指针或地址传递给函数。该函数可以更改存储在指针指向的地址或地址处的值。稍后可以使用相同的内存地址在功能范围之外检索对这些值的更改。
下图说明了如何使用双指针。
int cudamalloc((void **) &d_array, int type_size) {
*d_array = malloc(type_size);
return return_code;
}
Run Code Online (Sandbox Code Playgroud)
我通常生活在python世界中,所以我也很难理解为什么这行不通。
int cudamalloc((void *) d_array, int type_size) {
d_array = malloc(type_size);
...
return error_status;
}
Run Code Online (Sandbox Code Playgroud)
那么为什么它不起作用?因为在C中,当cudamalloc
被调用时,将创建一个名为d_array的局部变量,并为其分配第一个函数参数的值。我们无法在函数范围之外检索该局部变量中的值。这就是为什么我们需要在这里指向一个指针的原因。
int cudamalloc((void *) d_array, int type_size) {
*d_array = malloc(type_size);
...
return return_code;
}
Run Code Online (Sandbox Code Playgroud)