0

我上周开始使用 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;
}

谢谢!

4

1 回答 1

2

在 SO 问题的空间中教授 CUDA 是不可能的。我将尝试回答您的问题,但您可能应该利用一些资源。如果您不了解 C 或 C++,这将特别困难,因为典型的 CUDA 编程依赖于这些。

您可能想在这里参加一些介绍性网络研讨会,例如:

GPU Computing using CUDA C – An Introduction (2010) 介绍使用 CUDA C 进行 GPU 计算的基础知识。将通过代码示例的演练来说明概念。无需先前的 GPU 计算经验

GPU Computing using CUDA C – Advanced 1 (2010) 一级优化技术,例如全局内存优化和处理器利用率。将使用真实的代码示例来说明概念

现在回答你的问题:

有人能解释一下如何用空指针'dev_c'分配GPU内存吗?

dev_c开始是一个空指针。但是该cudaMalloc函数根据传递给它的大小分配 GPU 内存dev_c,建立指向该分配的指针,并将该指针存储到指针中。它可以这样做是因为我们传递的是 的地址 dev_c,而不是实际的指针本身。

然后,在调用函数“add”时不传递任何“dev_c”值,而是将 *c 视为全局函数中的数组并从函数内部写入?当它没有在任何地方定义为数组时,为什么这可能?

在 C 语言中,指针(即是什么dev_c)可以指向单个值或值数组。指针本身不包含有关它指向多少数据的信息。由于dev_c是存储结果,并且它已经被前面的cudaMalloc函数正确初始化,我们可以使用它来将操作的结果存储在内核中。 dev_c实际上指向 (an array of) 的存储区域int,其大小由 给定N * sizeof(int),传递给前面的cudaMalloc函数。

最后,在执行以下加法时,术语 c[0]、c[1] 等到底保存在哪里?

在 c 中,当我们有这样的函数定义时:

void my_function(int *c){...}

这表示函数中的语句可以引用一个变量,该变量被命名c为一个或多个int值的指针(单个值或值数组,从 指向的位置开始存储c)。

当我们调用该函数时,我们可以使用其他一些名为参数的变量,作为被调用的函数参数c,如下所示:

int my_ints[32];
my_function(my_ints);

现在,在里面my_function,无论参数 c被引用到哪里,它都会使用(pointer) 给出的参数my_ints值。

相同的概念适用于 cuda 函数(内核)及其参数和参数。

于 2013-07-04T16:10:33.597 回答